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

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