root/drivers/char/vt.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kd_nosound
  2. kd_mksound
  3. vt_ioctl

   1 /*
   2  *  linux/drivers/char/vt.c
   3  *
   4  *  Copyright (C) 1992 obz under the linux copyright
   5  *
   6  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
   7  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
   8  */
   9 
  10 #include <linux/types.h>
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/tty.h>
  14 #include <linux/timer.h>
  15 #include <linux/kernel.h>
  16 #include <linux/kd.h>
  17 #include <linux/vt.h>
  18 #include <linux/string.h>
  19 #include <linux/malloc.h>
  20 
  21 #include <asm/io.h>
  22 #include <asm/segment.h>
  23 
  24 #include "kbd_kern.h"
  25 #include "vt_kern.h"
  26 #include "diacr.h"
  27 
  28 extern struct tty_driver console_driver;
  29 
  30 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
  31 
  32 /*
  33  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  34  * experimentation and study of X386 SYSV handling.
  35  *
  36  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  37  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  38  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  39  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
  40  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  41  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  42  * to the current console is done by the main ioctl code.
  43  */
  44 
  45 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
  46 
  47 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  48 
  49 extern int getkeycode(unsigned int scancode);
  50 extern int setkeycode(unsigned int scancode, unsigned int keycode);
  51 extern void compute_shiftstate(void);
  52 extern void change_console(unsigned int new_console);
  53 extern void complete_change_console(unsigned int new_console);
  54 extern int vt_waitactive(void);
  55 
  56 extern unsigned int keymap_count;
  57 
  58 /*
  59  * routines to load custom translation table and EGA/VGA font from console.c
  60  */
  61 extern int con_set_trans(char * table);
  62 extern int con_get_trans(char * table);
  63 extern int con_set_font(char * fontmap);
  64 extern int con_get_font(char * fontmap);
  65 
  66 /*
  67  * these are the valid i/o ports we're allowed to change. they map all the
  68  * video ports
  69  */
  70 #define GPFIRST 0x3b4
  71 #define GPLAST 0x3df
  72 #define GPNUM (GPLAST - GPFIRST + 1)
  73 
  74 /*
  75  * Generates sound of some count for some number of clock ticks
  76  * [count = 1193180 / frequency]
  77  *
  78  * If freq is 0, will turn off sound, else will turn it on for that time.
  79  * If msec is 0, will return immediately, else will sleep for msec time, then
  80  * turn sound off.
  81  *
  82  * We use the BEEP_TIMER vector since we're using the same method to
  83  * generate sound, and we'll overwrite any beep in progress. That may
  84  * be something to fix later, if we like.
  85  *
  86  * We also return immediately, which is what was implied within the X
  87  * comments - KDMKTONE doesn't put the process to sleep.
  88  */
  89 static void
  90 kd_nosound(unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         /* disable counter 2 */
  93         outb(inb_p(0x61)&0xFC, 0x61);
  94         return;
  95 }
  96 
  97 void
  98 kd_mksound(unsigned int count, unsigned int ticks)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
 101 
 102         cli();
 103         del_timer(&sound_timer);
 104         if (count) {
 105                 /* enable counter 2 */
 106                 outb_p(inb_p(0x61)|3, 0x61);
 107                 /* set command for counter 2, 2 byte write */
 108                 outb_p(0xB6, 0x43);
 109                 /* select desired HZ */
 110                 outb_p(count & 0xff, 0x42);
 111                 outb((count >> 8) & 0xff, 0x42);
 112 
 113                 if (ticks) {
 114                         sound_timer.expires = ticks;
 115                         add_timer(&sound_timer);
 116                 }
 117         } else
 118                 kd_nosound(0);
 119         sti();
 120         return;
 121 }
 122 
 123 /*
 124  * We handle the console-specific ioctl's here.  We allow the
 125  * capability to modify any console, not just the fg_console. 
 126  */
 127 int vt_ioctl(struct tty_struct *tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 128              unsigned int cmd, unsigned long arg)
 129 {
 130         int i;
 131         unsigned int console;
 132         unsigned char ucval;
 133         struct kbd_struct * kbd;
 134         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 135 
 136         console = vt->vc_num;
 137 
 138         if (!vc_cons_allocated(console))        /* impossible? */
 139                 return -ENOIOCTLCMD;
 140 
 141         kbd = kbd_table + console;
 142         switch (cmd) {
 143         case KIOCSOUND:
 144                 kd_mksound((unsigned int)arg, 0);
 145                 return 0;
 146 
 147         case KDMKTONE:
 148         {
 149                 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
 150 
 151                 /*
 152                  * Generate the tone for the appropriate number of ticks.
 153                  * If the time is zero, turn off sound ourselves.
 154                  */
 155                 kd_mksound(arg & 0xffff, ticks);
 156                 if (ticks == 0)
 157                         kd_nosound(0);
 158                 return 0;
 159         }
 160 
 161         case KDGKBTYPE:
 162                 /*
 163                  * this is naive.
 164                  */
 165                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 166                 if (!i)
 167                         put_fs_byte(KB_101, (char *) arg);
 168                 return i;
 169 
 170         case KDADDIO:
 171         case KDDELIO:
 172                 /*
 173                  * KDADDIO and KDDELIO may be able to add ports beyond what
 174                  * we reject here, but to be safe...
 175                  */
 176                 if (arg < GPFIRST || arg > GPLAST)
 177                         return -EINVAL;
 178                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
 179 
 180         case KDENABIO:
 181         case KDDISABIO:
 182                 return sys_ioperm(GPFIRST, GPNUM,
 183                                   (cmd == KDENABIO)) ? -ENXIO : 0;
 184 
 185         case KDSETMODE:
 186                 /*
 187                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
 188                  * doesn't do a whole lot. i'm not sure if it should do any
 189                  * restoration of modes or what...
 190                  */
 191                 switch (arg) {
 192                 case KD_GRAPHICS:
 193                         break;
 194                 case KD_TEXT0:
 195                 case KD_TEXT1:
 196                         arg = KD_TEXT;
 197                 case KD_TEXT:
 198                         break;
 199                 default:
 200                         return -EINVAL;
 201                 }
 202                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
 203                         return 0;
 204                 vt_cons[console]->vc_mode = (unsigned char) arg;
 205                 if (console != fg_console)
 206                         return 0;
 207                 /*
 208                  * explicitly blank/unblank the screen if switching modes
 209                  */
 210                 if (arg == KD_TEXT)
 211                         unblank_screen();
 212                 else {
 213                         timer_active &= ~(1<<BLANK_TIMER);
 214                         blank_screen();
 215                 }
 216                 return 0;
 217 
 218         case KDGETMODE:
 219                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 220                 if (!i)
 221                         put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg);
 222                 return i;
 223 
 224         case KDMAPDISP:
 225         case KDUNMAPDISP:
 226                 /*
 227                  * these work like a combination of mmap and KDENABIO.
 228                  * this could be easily finished.
 229                  */
 230                 return -EINVAL;
 231 
 232         case KDSKBMODE:
 233                 switch(arg) {
 234                   case K_RAW:
 235                         kbd->kbdmode = VC_RAW;
 236                         break;
 237                   case K_MEDIUMRAW:
 238                         kbd->kbdmode = VC_MEDIUMRAW;
 239                         break;
 240                   case K_XLATE:
 241                         kbd->kbdmode = VC_XLATE;
 242                         compute_shiftstate();
 243                         break;
 244                   case K_UNICODE:
 245                         kbd->kbdmode = VC_UNICODE;
 246                         compute_shiftstate();
 247                         break;
 248                   default:
 249                         return -EINVAL;
 250                 }
 251                 if (tty->ldisc.flush_buffer)
 252                         tty->ldisc.flush_buffer(tty);
 253                 return 0;
 254 
 255         case KDGKBMODE:
 256                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 257                 if (!i) {
 258                         ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 259                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 260                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 261                                  K_XLATE);
 262                         put_fs_long(ucval, (unsigned long *) arg);
 263                 }
 264                 return i;
 265 
 266         /* this could be folded into KDSKBMODE, but for compatibility
 267            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
 268         case KDSKBMETA:
 269                 switch(arg) {
 270                   case K_METABIT:
 271                         clr_vc_kbd_mode(kbd, VC_META);
 272                         break;
 273                   case K_ESCPREFIX:
 274                         set_vc_kbd_mode(kbd, VC_META);
 275                         break;
 276                   default:
 277                         return -EINVAL;
 278                 }
 279                 return 0;
 280 
 281         case KDGKBMETA:
 282                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 283                 if (!i) {
 284                         ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
 285                                  K_METABIT);
 286                         put_fs_long(ucval, (unsigned long *) arg);
 287                 }
 288                 return i;
 289 
 290         case KDGETKEYCODE:
 291         {
 292                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 293                 unsigned int sc;
 294                 int kc;
 295 
 296                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 297                 if (i)
 298                         return i;
 299                 sc = get_fs_long((int *) &a->scancode);
 300                 kc = getkeycode(sc);
 301                 if (kc < 0)
 302                         return kc;
 303                 put_fs_long(kc, (int *) &a->keycode);
 304                 return 0;
 305         }
 306 
 307         case KDSETKEYCODE:
 308         {
 309                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 310                 unsigned int sc, kc;
 311 
 312                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 313                 if (i)
 314                         return i;
 315                 sc = get_fs_long((int *) &a->scancode);
 316                 kc = get_fs_long((int *) &a->keycode);
 317                 return setkeycode(sc, kc);
 318         }
 319 
 320         case KDGKBENT:
 321         {
 322                 struct kbentry * const a = (struct kbentry *)arg;
 323                 ushort *key_map, val;
 324                 u_char s;
 325 
 326                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 327                 if (i)
 328                         return i;
 329                 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 330                         return -EINVAL;
 331                 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 332                         return -EINVAL;
 333                 key_map = key_maps[s];
 334                 if (key_map) {
 335                     val = U(key_map[i]);
 336                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
 337                         val = K_HOLE;
 338                 } else
 339                     val = (i ? K_HOLE : K_NOSUCHMAP);
 340                 put_fs_word(val, (short *) &a->kb_value);
 341                 return 0;
 342         }
 343 
 344         case KDSKBENT:
 345         {
 346                 const struct kbentry * a = (struct kbentry *)arg;
 347                 ushort *key_map;
 348                 u_char s;
 349                 u_short v;
 350 
 351                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
 352                 if (i)
 353                         return i;
 354                 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 355                         return -EINVAL;
 356                 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 357                         return -EINVAL;
 358                 v = get_fs_word(&a->kb_value);
 359                 if (!i && v == K_NOSUCHMAP) {
 360                         /* disallocate map */
 361                         key_map = key_maps[s];
 362                         if (key_map) {
 363                             key_maps[s] = 0;
 364                             if (key_map[0] == U(K_ALLOCATED)) {
 365                                 kfree_s(key_map, sizeof(plain_map));
 366                                 keymap_count--;
 367                             }
 368                         }
 369                         return 0;
 370                 }
 371 
 372                 if (KTYP(v) < NR_TYPES) {
 373                     if (KVAL(v) > max_vals[KTYP(v)])
 374                         return -EINVAL;
 375                 } else
 376                     if (kbd->kbdmode != VC_UNICODE)
 377                         return -EINVAL;
 378 
 379                 /* assignment to entry 0 only tests validity of args */
 380                 if (!i)
 381                         return 0;
 382 
 383                 if (!(key_map = key_maps[s])) {
 384                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
 385                                 return -EPERM;
 386 
 387                         key_map = (ushort *) kmalloc(sizeof(plain_map),
 388                                                      GFP_KERNEL);
 389                         if (!key_map)
 390                                 return -ENOMEM;
 391                         key_maps[s] = key_map;
 392                         key_map[0] = U(K_ALLOCATED);
 393                         for (s = 1; s < NR_KEYS; s++)
 394                                 key_map[s] = U(K_HOLE);
 395                         keymap_count++;
 396                 }
 397                 /*
 398                  * Only the Superuser can set or unset the Secure
 399                  * Attention Key.
 400                  */
 401                 if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) &&
 402                     !suser())
 403                         return -EPERM;
 404                 key_map[i] = U(v);
 405                 return 0;
 406         }
 407 
 408         case KDGKBSENT:
 409         {
 410                 struct kbsentry *a = (struct kbsentry *)arg;
 411                 char *p;
 412                 u_char *q;
 413                 int sz;
 414 
 415                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 416                 if (i)
 417                         return i;
 418                 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 419                         return -EINVAL;
 420                 sz = sizeof(a->kb_string) - 1; /* sz should have been
 421                                                   a struct member */
 422                 q = a->kb_string;
 423                 p = func_table[i];
 424                 if(p)
 425                         for ( ; *p && sz; p++, sz--)
 426                                 put_fs_byte(*p, q++);
 427                 put_fs_byte(0, q);
 428                 return ((p && *p) ? -EOVERFLOW : 0);
 429         }
 430 
 431         case KDSKBSENT:
 432         {
 433                 struct kbsentry * const a = (struct kbsentry *)arg;
 434                 int delta;
 435                 char *first_free, *fj, *fnw;
 436                 int j, k, sz;
 437                 u_char *p;
 438                 char *q;
 439 
 440                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 441                 if (i)
 442                         return i;
 443                 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC)
 444                         return -EINVAL;
 445                 q = func_table[i];
 446 
 447                 first_free = funcbufptr + (funcbufsize - funcbufleft);
 448                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
 449                 if (j < MAX_NR_FUNC)
 450                         fj = func_table[j];
 451                 else
 452                         fj = first_free;
 453 
 454                 delta = (q ? -strlen(q) : 1);
 455                 sz = sizeof(a->kb_string);      /* sz should have been
 456                                                    a struct member */
 457                 for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--)
 458                         delta++;
 459                 if (!sz)
 460                         return -EOVERFLOW;
 461                 if (delta <= funcbufleft) {     /* it fits in current buf */
 462                     if (j < MAX_NR_FUNC) {
 463                         memmove(fj + delta, fj, first_free - fj);
 464                         for (k = j; k < MAX_NR_FUNC; k++)
 465                             if (func_table[k])
 466                                 func_table[k] += delta;
 467                     }
 468                     if (!q)
 469                       func_table[i] = fj;
 470                     funcbufleft -= delta;
 471                 } else {                        /* allocate a larger buffer */
 472                     sz = 256;
 473                     while (sz < funcbufsize - funcbufleft + delta)
 474                       sz <<= 1;
 475                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
 476                     if(!fnw)
 477                       return -ENOMEM;
 478 
 479                     if (!q)
 480                       func_table[i] = fj;
 481                     if (fj > funcbufptr)
 482                         memmove(fnw, funcbufptr, fj - funcbufptr);
 483                     for (k = 0; k < j; k++)
 484                       if (func_table[k])
 485                         func_table[k] = fnw + (func_table[k] - funcbufptr);
 486 
 487                     if (first_free > fj) {
 488                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
 489                         for (k = j; k < MAX_NR_FUNC; k++)
 490                           if (func_table[k])
 491                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
 492                     }
 493                     if (funcbufptr != func_buf)
 494                       kfree_s(funcbufptr, funcbufsize);
 495                     funcbufptr = fnw;
 496                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
 497                     funcbufsize = sz;
 498                 }
 499                 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 500                         if (!(*q = get_fs_byte(p)))
 501                                 break;
 502                 return 0;
 503         }
 504 
 505         case KDGKBDIACR:
 506         {
 507                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 508 
 509                 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 510                 if (i)
 511                         return i;
 512                 put_fs_long(accent_table_size, &a->kb_cnt);
 513                 memcpy_tofs(a->kbdiacr, accent_table,
 514                             accent_table_size*sizeof(struct kbdiacr));
 515                 return 0;
 516         }
 517 
 518         case KDSKBDIACR:
 519         {
 520                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 521                 unsigned int ct;
 522 
 523                 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 524                 if (i)
 525                         return i;
 526                 ct = get_fs_long(&a->kb_cnt);
 527                 if (ct >= MAX_DIACR)
 528                         return -EINVAL;
 529                 accent_table_size = ct;
 530                 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 531                 return 0;
 532         }
 533 
 534         /* the ioctls below read/set the flags usually shown in the leds */
 535         /* don't use them - they will go away without warning */
 536         case KDGKBLED:
 537                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 538                 if (i)
 539                         return i;
 540                 put_fs_byte(kbd->ledflagstate |
 541                             (kbd->default_ledflagstate << 4), (char *) arg);
 542                 return 0;
 543 
 544         case KDSKBLED:
 545                 if (arg & ~0x77)
 546                         return -EINVAL;
 547                 kbd->ledflagstate = (arg & 7);
 548                 kbd->default_ledflagstate = ((arg >> 4) & 7);
 549                 set_leds();
 550                 return 0;
 551 
 552         /* the ioctls below only set the lights, not the functions */
 553         /* for those, see KDGKBLED and KDSKBLED above */
 554         case KDGETLED:
 555                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 556                 if (i)
 557                         return i;
 558                 put_fs_byte(getledstate(), (char *) arg);
 559                 return 0;
 560 
 561         case KDSETLED:
 562                 setledstate(kbd, arg);
 563                 return 0;
 564 
 565         case VT_SETMODE:
 566         {
 567                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 568                 char mode;
 569 
 570                 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
 571                 if (i)
 572                         return i;
 573                 mode = get_fs_byte(&vtmode->mode);
 574                 if (mode != VT_AUTO && mode != VT_PROCESS)
 575                         return -EINVAL;
 576                 vt_cons[console]->vt_mode.mode = mode;
 577                 vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv);
 578                 vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig);
 579                 vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
 580                 /* the frsig is ignored, so we set it to 0 */
 581                 vt_cons[console]->vt_mode.frsig = 0;
 582                 vt_cons[console]->vt_pid = current->pid;
 583                 vt_cons[console]->vt_newvt = 0;
 584                 return 0;
 585         }
 586 
 587         case VT_GETMODE:
 588         {
 589                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 590 
 591                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 592                 if (i)
 593                         return i;
 594                 put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 595                 put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 596                 put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 597                 put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 598                 put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 599                 return 0;
 600         }
 601 
 602         /*
 603          * Returns global vt state. Note that VT 0 is always open, since
 604          * it's an alias for the current VT, and people can't use it here.
 605          * We cannot return state for more than 16 VTs, since v_state is short.
 606          */
 607         case VT_GETSTATE:
 608         {
 609                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 610                 unsigned short state, mask;
 611 
 612                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 613                 if (i)
 614                         return i;
 615                 put_fs_word(fg_console + 1, &vtstat->v_active);
 616                 state = 1;      /* /dev/tty0 is always open */
 617                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 618                         if (console_driver.table[i] &&
 619                             console_driver.table[i]->count > 0)
 620                                 state |= mask;
 621                 put_fs_word(state, &vtstat->v_state);
 622                 return 0;
 623         }
 624 
 625         /*
 626          * Returns the first available (non-opened) console.
 627          */
 628         case VT_OPENQRY:
 629                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
 630                 if (i)
 631                         return i;
 632                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 633                         if (! VT_IS_IN_USE(i))
 634                                 break;
 635                 put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1,
 636                             (unsigned long *)arg);
 637                 return 0;
 638 
 639         /*
 640          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 641          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 642          * to preserve sanity).
 643          */
 644         case VT_ACTIVATE:
 645                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 646                         return -ENXIO;
 647                 arg--;
 648                 i = vc_allocate(arg);
 649                 if (i)
 650                         return i;
 651                 change_console(arg);
 652                 return 0;
 653 
 654         /*
 655          * wait until the specified VT has been activated
 656          */
 657         case VT_WAITACTIVE:
 658                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 659                         return -ENXIO;
 660                 arg--;
 661                 while (fg_console != arg)
 662                 {
 663                         if (vt_waitactive() < 0)
 664                                 return -EINTR;
 665                 }
 666                 return 0;
 667 
 668         /*
 669          * If a vt is under process control, the kernel will not switch to it
 670          * immediately, but postpone the operation until the process calls this
 671          * ioctl, allowing the switch to complete.
 672          *
 673          * According to the X sources this is the behavior:
 674          *      0:      pending switch-from not OK
 675          *      1:      pending switch-from OK
 676          *      2:      completed switch-to OK
 677          */
 678         case VT_RELDISP:
 679                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 680                         return -EINVAL;
 681 
 682                 /*
 683                  * Switching-from response
 684                  */
 685                 if (vt_cons[console]->vt_newvt >= 0)
 686                 {
 687                         if (arg == 0)
 688                                 /*
 689                                  * Switch disallowed, so forget we were trying
 690                                  * to do it.
 691                                  */
 692                                 vt_cons[console]->vt_newvt = -1;
 693 
 694                         else
 695                         {
 696                                 /*
 697                                  * The current vt has been released, so
 698                                  * complete the switch.
 699                                  */
 700                                 int newvt = vt_cons[console]->vt_newvt;
 701                                 vt_cons[console]->vt_newvt = -1;
 702                                 i = vc_allocate(newvt);
 703                                 if (i)
 704                                         return i;
 705                                 complete_change_console(newvt);
 706                         }
 707                 }
 708 
 709                 /*
 710                  * Switched-to response
 711                  */
 712                 else
 713                 {
 714                         /*
 715                          * If it's just an ACK, ignore it
 716                          */
 717                         if (arg != VT_ACKACQ)
 718                                 return -EINVAL;
 719                 }
 720 
 721                 return 0;
 722 
 723          /*
 724           * Disallocate memory associated to VT (but leave VT1)
 725           */
 726          case VT_DISALLOCATE:
 727                 if (arg > MAX_NR_CONSOLES)
 728                         return -ENXIO;
 729                 if (arg == 0) {
 730                     /* disallocate all unused consoles, but leave 0 */
 731                     for (i=1; i<MAX_NR_CONSOLES; i++)
 732                       if (! VT_IS_IN_USE(i)) {
 733                           if (i == fg_console)
 734                             change_console(0);
 735                           vc_disallocate(i);
 736                       }
 737                 } else {
 738                     /* disallocate a single console, if possible */
 739                     arg--;
 740                     if (VT_IS_IN_USE(arg))
 741                       return -EBUSY;
 742                     if (arg) {                        /* leave 0 */
 743                         if (arg == fg_console)
 744                           change_console(0);
 745                         vc_disallocate(arg);
 746                     }
 747                 }
 748                 return 0;
 749 
 750         case VT_RESIZE:
 751         {
 752                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 753                 ushort ll,cc;
 754                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 755                 if (i)
 756                         return i;
 757                 ll = get_fs_word(&vtsizes->v_rows);
 758                 cc = get_fs_word(&vtsizes->v_cols);
 759                 return vc_resize(ll, cc);
 760         }
 761 
 762         case PIO_FONT:
 763                 return con_set_font((char *)arg);
 764                 /* con_set_font() defined in console.c */
 765 
 766         case GIO_FONT:
 767                 return con_get_font((char *)arg);
 768                 /* con_get_font() defined in console.c */
 769 
 770         case PIO_SCRNMAP:
 771                 return con_set_trans((char *)arg);
 772                 /* con_set_trans() defined in console.c */
 773 
 774         case GIO_SCRNMAP:
 775                 return con_get_trans((char *)arg);
 776                 /* con_get_trans() defined in console.c */
 777 
 778         default:
 779                 return -ENOIOCTLCMD;
 780         }
 781 }

/* [previous][next][first][last][top][bottom][index][help] */