root/drivers/char/vt.c

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

DEFINITIONS

This source file includes following definitions.
  1. kd_size_changed
  2. kd_nosound
  3. kd_mksound
  4. 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 #include <linux/major.h>
  21 #include <linux/fs.h>
  22 
  23 #include <asm/io.h>
  24 #include <asm/segment.h>
  25 
  26 #include "kbd_kern.h"
  27 #include "vt_kern.h"
  28 #include "diacr.h"
  29 #include "selection.h"
  30 
  31 extern struct tty_driver console_driver;
  32 
  33 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
  34 #define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
  35 
  36 /*
  37  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  38  * experimentation and study of X386 SYSV handling.
  39  *
  40  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  41  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  42  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  43  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
  44  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  45  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  46  * to the current console is done by the main ioctl code.
  47  */
  48 
  49 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
  50 
  51 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  52 
  53 extern int getkeycode(unsigned int scancode);
  54 extern int setkeycode(unsigned int scancode, unsigned int keycode);
  55 extern void compute_shiftstate(void);
  56 extern void change_console(unsigned int new_console);
  57 extern void complete_change_console(unsigned int new_console);
  58 extern int vt_waitactive(void);
  59 extern void do_blank_screen(int nopowersave);
  60 
  61 extern unsigned int keymap_count;
  62 
  63 /*
  64  * routines to load custom translation table, EGA/VGA font and
  65  * VGA colour palette from console.c
  66  */
  67 extern int con_set_trans_old(unsigned char * table);
  68 extern int con_get_trans_old(unsigned char * table);
  69 extern int con_set_trans_new(unsigned short * table);
  70 extern int con_get_trans_new(unsigned short * table);
  71 extern void con_clear_unimap(struct unimapinit *ui);
  72 extern int con_set_unimap(ushort ct, struct unipair *list);
  73 extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
  74 extern int con_set_font(char * fontmap, int ch512);
  75 extern int con_get_font(char * fontmap);
  76 extern int con_set_cmap(unsigned char *cmap);
  77 extern int con_get_cmap(unsigned char *cmap);
  78 extern void reset_palette(int currcons);
  79 extern int con_adjust_height(unsigned long fontheight);
  80 
  81 extern int video_mode_512ch;
  82 extern unsigned long video_font_height;
  83 extern unsigned long video_scan_lines;
  84 
  85 /*
  86  * these are the valid i/o ports we're allowed to change. they map all the
  87  * video ports
  88  */
  89 #define GPFIRST 0x3b4
  90 #define GPLAST 0x3df
  91 #define GPNUM (GPLAST - GPFIRST + 1)
  92 
  93 /*
  94  * This function is called when the size of the physical screen has been
  95  * changed.  If either the row or col argument is nonzero, set the appropriate
  96  * entry in each winsize structure for all the virtual consoles, then
  97  * send SIGWINCH to all processes with a virtual console as controlling
  98  * tty.
  99  */
 100 
 101 static int
 102 kd_size_changed(int row, int col)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104   struct task_struct *p;
 105   int i;
 106 
 107   if ( !row && !col ) return 0;
 108 
 109   for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
 110     {
 111       if ( console_driver.table[i] )
 112         {
 113           if ( row ) console_driver.table[i]->winsize.ws_row = row;
 114           if ( col ) console_driver.table[i]->winsize.ws_col = col;
 115         }
 116     }
 117 
 118   for_each_task(p)
 119     {
 120       if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
 121            MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
 122         {
 123           send_sig(SIGWINCH, p, 1);
 124         }
 125     }
 126 
 127   return 0;
 128 }
 129 
 130 /*
 131  * Generates sound of some count for some number of clock ticks
 132  * [count = 1193180 / frequency]
 133  *
 134  * If freq is 0, will turn off sound, else will turn it on for that time.
 135  * If msec is 0, will return immediately, else will sleep for msec time, then
 136  * turn sound off.
 137  *
 138  * We use the BEEP_TIMER vector since we're using the same method to
 139  * generate sound, and we'll overwrite any beep in progress. That may
 140  * be something to fix later, if we like.
 141  *
 142  * We also return immediately, which is what was implied within the X
 143  * comments - KDMKTONE doesn't put the process to sleep.
 144  */
 145 static void
 146 kd_nosound(unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         /* disable counter 2 */
 149         outb(inb_p(0x61)&0xFC, 0x61);
 150         return;
 151 }
 152 
 153 void
 154 kd_mksound(unsigned int count, unsigned int ticks)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156         static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
 157 
 158         cli();
 159         del_timer(&sound_timer);
 160         if (count) {
 161                 /* enable counter 2 */
 162                 outb_p(inb_p(0x61)|3, 0x61);
 163                 /* set command for counter 2, 2 byte write */
 164                 outb_p(0xB6, 0x43);
 165                 /* select desired HZ */
 166                 outb_p(count & 0xff, 0x42);
 167                 outb((count >> 8) & 0xff, 0x42);
 168 
 169                 if (ticks) {
 170                         sound_timer.expires = jiffies+ticks;
 171                         add_timer(&sound_timer);
 172                 }
 173         } else
 174                 kd_nosound(0);
 175         sti();
 176         return;
 177 }
 178 
 179 /*
 180  * We handle the console-specific ioctl's here.  We allow the
 181  * capability to modify any console, not just the fg_console. 
 182  */
 183 int vt_ioctl(struct tty_struct *tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 184              unsigned int cmd, unsigned long arg)
 185 {
 186         int i, perm;
 187         unsigned int console;
 188         unsigned char ucval;
 189         struct kbd_struct * kbd;
 190         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 191 
 192         console = vt->vc_num;
 193 
 194         if (!vc_cons_allocated(console))        /* impossible? */
 195                 return -ENOIOCTLCMD;
 196 
 197         /*
 198          * To have permissions to do most of the vt ioctls, we either have
 199          * to be the owner of the tty, or super-user.
 200          */
 201         perm = 0;
 202         if (current->tty == tty || suser())
 203                 perm = 1;
 204 
 205         kbd = kbd_table + console;
 206         switch (cmd) {
 207         case KIOCSOUND:
 208                 if (!perm)
 209                         return -EPERM;
 210                 kd_mksound((unsigned int)arg, 0);
 211                 return 0;
 212 
 213         case KDMKTONE:
 214                 if (!perm)
 215                         return -EPERM;
 216         {
 217                 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
 218 
 219                 /*
 220                  * Generate the tone for the appropriate number of ticks.
 221                  * If the time is zero, turn off sound ourselves.
 222                  */
 223                 kd_mksound(arg & 0xffff, ticks);
 224                 if (ticks == 0)
 225                         kd_nosound(0);
 226                 return 0;
 227         }
 228 
 229         case KDGKBTYPE:
 230                 /*
 231                  * this is naive.
 232                  */
 233                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 234                 if (!i)
 235                         put_user(KB_101, (char *) arg);
 236                 return i;
 237 
 238         case KDADDIO:
 239         case KDDELIO:
 240                 /*
 241                  * KDADDIO and KDDELIO may be able to add ports beyond what
 242                  * we reject here, but to be safe...
 243                  */
 244                 if (arg < GPFIRST || arg > GPLAST)
 245                         return -EINVAL;
 246                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
 247 
 248         case KDENABIO:
 249         case KDDISABIO:
 250                 return sys_ioperm(GPFIRST, GPNUM,
 251                                   (cmd == KDENABIO)) ? -ENXIO : 0;
 252 
 253         case KDSETMODE:
 254                 /*
 255                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
 256                  * doesn't do a whole lot. i'm not sure if it should do any
 257                  * restoration of modes or what...
 258                  */
 259                 if (!perm)
 260                         return -EPERM;
 261                 switch (arg) {
 262                 case KD_GRAPHICS:
 263                         break;
 264                 case KD_TEXT0:
 265                 case KD_TEXT1:
 266                         arg = KD_TEXT;
 267                 case KD_TEXT:
 268                         break;
 269                 default:
 270                         return -EINVAL;
 271                 }
 272                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
 273                         return 0;
 274                 vt_cons[console]->vc_mode = (unsigned char) arg;
 275                 if (console != fg_console)
 276                         return 0;
 277                 /*
 278                  * explicitly blank/unblank the screen if switching modes
 279                  */
 280                 if (arg == KD_TEXT)
 281                         do_unblank_screen();
 282                 else
 283                         do_blank_screen(1);
 284                 return 0;
 285 
 286         case KDGETMODE:
 287                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 288                 if (!i)
 289                         put_user(vt_cons[console]->vc_mode, (int *) arg);
 290                 return i;
 291 
 292         case KDMAPDISP:
 293         case KDUNMAPDISP:
 294                 /*
 295                  * these work like a combination of mmap and KDENABIO.
 296                  * this could be easily finished.
 297                  */
 298                 return -EINVAL;
 299 
 300         case KDSKBMODE:
 301                 if (!perm)
 302                         return -EPERM;
 303                 switch(arg) {
 304                   case K_RAW:
 305                         kbd->kbdmode = VC_RAW;
 306                         break;
 307                   case K_MEDIUMRAW:
 308                         kbd->kbdmode = VC_MEDIUMRAW;
 309                         break;
 310                   case K_XLATE:
 311                         kbd->kbdmode = VC_XLATE;
 312                         compute_shiftstate();
 313                         break;
 314                   case K_UNICODE:
 315                         kbd->kbdmode = VC_UNICODE;
 316                         compute_shiftstate();
 317                         break;
 318                   default:
 319                         return -EINVAL;
 320                 }
 321                 if (tty->ldisc.flush_buffer)
 322                         tty->ldisc.flush_buffer(tty);
 323                 return 0;
 324 
 325         case KDGKBMODE:
 326                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 327                 if (!i) {
 328                         ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 329                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 330                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 331                                  K_XLATE);
 332                         put_user(ucval, (int *) arg);
 333                 }
 334                 return i;
 335 
 336         /* this could be folded into KDSKBMODE, but for compatibility
 337            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
 338         case KDSKBMETA:
 339                 switch(arg) {
 340                   case K_METABIT:
 341                         clr_vc_kbd_mode(kbd, VC_META);
 342                         break;
 343                   case K_ESCPREFIX:
 344                         set_vc_kbd_mode(kbd, VC_META);
 345                         break;
 346                   default:
 347                         return -EINVAL;
 348                 }
 349                 return 0;
 350 
 351         case KDGKBMETA:
 352                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 353                 if (!i) {
 354                         ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
 355                                  K_METABIT);
 356                         put_user(ucval, (int *) arg);
 357                 }
 358                 return i;
 359 
 360         case KDGETKEYCODE:
 361         {
 362                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 363                 unsigned int sc;
 364                 int kc;
 365 
 366                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 367                 if (i)
 368                         return i;
 369                 sc = get_user(&a->scancode);
 370                 kc = getkeycode(sc);
 371                 if (kc < 0)
 372                         return kc;
 373                 put_user(kc, &a->keycode);
 374                 return 0;
 375         }
 376 
 377         case KDSETKEYCODE:
 378         {
 379                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 380                 unsigned int sc, kc;
 381 
 382                 if (!perm)
 383                         return -EPERM;
 384                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 385                 if (i)
 386                         return i;
 387                 sc = get_user(&a->scancode);
 388                 kc = get_user(&a->keycode);
 389                 return setkeycode(sc, kc);
 390         }
 391 
 392         case KDGKBENT:
 393         {
 394                 struct kbentry * const a = (struct kbentry *)arg;
 395                 ushort *key_map, val;
 396                 u_char s;
 397 
 398                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 399                 if (i)
 400                         return i;
 401                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 402                         return -EINVAL;
 403                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 404                         return -EINVAL;
 405                 key_map = key_maps[s];
 406                 if (key_map) {
 407                     val = U(key_map[i]);
 408                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
 409                         val = K_HOLE;
 410                 } else
 411                     val = (i ? K_HOLE : K_NOSUCHMAP);
 412                 put_user(val, &a->kb_value);
 413                 return 0;
 414         }
 415 
 416         case KDSKBENT:
 417         {
 418                 const struct kbentry * a = (struct kbentry *)arg;
 419                 ushort *key_map;
 420                 u_char s;
 421                 u_short v, ov;
 422 
 423                 if (!perm)
 424                         return -EPERM;
 425                 i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
 426                 if (i)
 427                         return i;
 428                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 429                         return -EINVAL;
 430                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 431                         return -EINVAL;
 432                 v = get_user(&a->kb_value);
 433                 if (!i && v == K_NOSUCHMAP) {
 434                         /* disallocate map */
 435                         key_map = key_maps[s];
 436                         if (s && key_map) {
 437                             key_maps[s] = 0;
 438                             if (key_map[0] == U(K_ALLOCATED)) {
 439                                 kfree_s(key_map, sizeof(plain_map));
 440                                 keymap_count--;
 441                             }
 442                         }
 443                         return 0;
 444                 }
 445 
 446                 if (KTYP(v) < NR_TYPES) {
 447                     if (KVAL(v) > max_vals[KTYP(v)])
 448                         return -EINVAL;
 449                 } else
 450                     if (kbd->kbdmode != VC_UNICODE)
 451                         return -EINVAL;
 452 
 453                 /* assignment to entry 0 only tests validity of args */
 454                 if (!i)
 455                         return 0;
 456 
 457                 if (!(key_map = key_maps[s])) {
 458                         int j;
 459 
 460                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
 461                                 return -EPERM;
 462 
 463                         key_map = (ushort *) kmalloc(sizeof(plain_map),
 464                                                      GFP_KERNEL);
 465                         if (!key_map)
 466                                 return -ENOMEM;
 467                         key_maps[s] = key_map;
 468                         key_map[0] = U(K_ALLOCATED);
 469                         for (j = 1; j < NR_KEYS; j++)
 470                                 key_map[j] = U(K_HOLE);
 471                         keymap_count++;
 472                 }
 473                 ov = U(key_map[i]);
 474                 if (v == ov)
 475                         return 0;       /* nothing to do */
 476                 /*
 477                  * Only the Superuser can set or unset the Secure
 478                  * Attention Key.
 479                  */
 480                 if (((ov == K_SAK) || (v == K_SAK)) && !suser())
 481                         return -EPERM;
 482                 key_map[i] = U(v);
 483                 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
 484                         compute_shiftstate();
 485                 return 0;
 486         }
 487 
 488         case KDGKBSENT:
 489         {
 490                 struct kbsentry *a = (struct kbsentry *)arg;
 491                 char *p;
 492                 u_char *q;
 493                 int sz;
 494 
 495                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 496                 if (i)
 497                         return i;
 498                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 499                         return -EINVAL;
 500                 sz = sizeof(a->kb_string) - 1; /* sz should have been
 501                                                   a struct member */
 502                 q = a->kb_string;
 503                 p = func_table[i];
 504                 if(p)
 505                         for ( ; *p && sz; p++, sz--)
 506                                 put_user(*p, q++);
 507                 put_user('\0', q);
 508                 return ((p && *p) ? -EOVERFLOW : 0);
 509         }
 510 
 511         case KDSKBSENT:
 512         {
 513                 struct kbsentry * const a = (struct kbsentry *)arg;
 514                 int delta;
 515                 char *first_free, *fj, *fnw;
 516                 int j, k, sz;
 517                 u_char *p;
 518                 char *q;
 519 
 520                 if (!perm)
 521                         return -EPERM;
 522                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 523                 if (i)
 524                         return i;
 525                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
 526                         return -EINVAL;
 527                 q = func_table[i];
 528 
 529                 first_free = funcbufptr + (funcbufsize - funcbufleft);
 530                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
 531                 if (j < MAX_NR_FUNC)
 532                         fj = func_table[j];
 533                 else
 534                         fj = first_free;
 535 
 536                 delta = (q ? -strlen(q) : 1);
 537                 sz = sizeof(a->kb_string);      /* sz should have been
 538                                                    a struct member */
 539                 for (p = a->kb_string; get_user(p) && sz; p++,sz--)
 540                         delta++;
 541                 if (!sz)
 542                         return -EOVERFLOW;
 543                 if (delta <= funcbufleft) {     /* it fits in current buf */
 544                     if (j < MAX_NR_FUNC) {
 545                         memmove(fj + delta, fj, first_free - fj);
 546                         for (k = j; k < MAX_NR_FUNC; k++)
 547                             if (func_table[k])
 548                                 func_table[k] += delta;
 549                     }
 550                     if (!q)
 551                       func_table[i] = fj;
 552                     funcbufleft -= delta;
 553                 } else {                        /* allocate a larger buffer */
 554                     sz = 256;
 555                     while (sz < funcbufsize - funcbufleft + delta)
 556                       sz <<= 1;
 557                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
 558                     if(!fnw)
 559                       return -ENOMEM;
 560 
 561                     if (!q)
 562                       func_table[i] = fj;
 563                     if (fj > funcbufptr)
 564                         memmove(fnw, funcbufptr, fj - funcbufptr);
 565                     for (k = 0; k < j; k++)
 566                       if (func_table[k])
 567                         func_table[k] = fnw + (func_table[k] - funcbufptr);
 568 
 569                     if (first_free > fj) {
 570                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
 571                         for (k = j; k < MAX_NR_FUNC; k++)
 572                           if (func_table[k])
 573                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
 574                     }
 575                     if (funcbufptr != func_buf)
 576                       kfree_s(funcbufptr, funcbufsize);
 577                     funcbufptr = fnw;
 578                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
 579                     funcbufsize = sz;
 580                 }
 581                 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 582                         if (!(*q = get_user(p)))
 583                                 break;
 584                 return 0;
 585         }
 586 
 587         case KDGKBDIACR:
 588         {
 589                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 590 
 591                 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 592                 if (i)
 593                         return i;
 594                 put_user(accent_table_size, &a->kb_cnt);
 595                 memcpy_tofs(a->kbdiacr, accent_table,
 596                             accent_table_size*sizeof(struct kbdiacr));
 597                 return 0;
 598         }
 599 
 600         case KDSKBDIACR:
 601         {
 602                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 603                 unsigned int ct;
 604 
 605                 if (!perm)
 606                         return -EPERM;
 607                 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 608                 if (i)
 609                         return i;
 610                 ct = get_user(&a->kb_cnt);
 611                 if (ct >= MAX_DIACR)
 612                         return -EINVAL;
 613                 accent_table_size = ct;
 614                 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 615                 return 0;
 616         }
 617 
 618         /* the ioctls below read/set the flags usually shown in the leds */
 619         /* don't use them - they will go away without warning */
 620         case KDGKBLED:
 621                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 622                 if (i)
 623                         return i;
 624                 put_user(kbd->ledflagstate |
 625                          (kbd->default_ledflagstate << 4), (char *) arg);
 626                 return 0;
 627 
 628         case KDSKBLED:
 629                 if (!perm)
 630                         return -EPERM;
 631                 if (arg & ~0x77)
 632                         return -EINVAL;
 633                 kbd->ledflagstate = (arg & 7);
 634                 kbd->default_ledflagstate = ((arg >> 4) & 7);
 635                 set_leds();
 636                 return 0;
 637 
 638         /* the ioctls below only set the lights, not the functions */
 639         /* for those, see KDGKBLED and KDSKBLED above */
 640         case KDGETLED:
 641                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 642                 if (i)
 643                         return i;
 644                 put_user(getledstate(), (char *) arg);
 645                 return 0;
 646 
 647         case KDSETLED:
 648                 if (!perm)
 649                   return -EPERM;
 650                 setledstate(kbd, arg);
 651                 return 0;
 652 
 653         /*
 654          * A process can indicate its willingness to accept signals
 655          * generated by pressing an appropriate key combination.
 656          * Thus, one can have a daemon that e.g. spawns a new console
 657          * upon a keypress and then changes to it.
 658          * Probably init should be changed to do this (and have a
 659          * field ks (`keyboard signal') in inittab describing the
 660          * desired action), so that the number of background daemons
 661          * does not increase.
 662          */
 663         case KDSIGACCEPT:
 664         {
 665                 extern int spawnpid, spawnsig;
 666                 if (!perm)
 667                   return -EPERM;
 668                 if (arg < 1 || arg > NSIG || arg == SIGKILL)
 669                   return -EINVAL;
 670                 spawnpid = current->pid;
 671                 spawnsig = arg;
 672                 return 0;
 673         }
 674 
 675         case VT_SETMODE:
 676         {
 677                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 678                 char mode;
 679 
 680                 if (!perm)
 681                         return -EPERM;
 682                 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
 683                 if (i)
 684                         return i;
 685                 mode = get_user(&vtmode->mode);
 686                 if (mode != VT_AUTO && mode != VT_PROCESS)
 687                         return -EINVAL;
 688                 vt_cons[console]->vt_mode.mode = mode;
 689                 vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
 690                 vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
 691                 vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
 692                 /* the frsig is ignored, so we set it to 0 */
 693                 vt_cons[console]->vt_mode.frsig = 0;
 694                 vt_cons[console]->vt_pid = current->pid;
 695                 vt_cons[console]->vt_newvt = 0;
 696                 return 0;
 697         }
 698 
 699         case VT_GETMODE:
 700         {
 701                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 702 
 703                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 704                 if (i)
 705                         return i;
 706                 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 707                 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 708                 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 709                 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 710                 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 711                 return 0;
 712         }
 713 
 714         /*
 715          * Returns global vt state. Note that VT 0 is always open, since
 716          * it's an alias for the current VT, and people can't use it here.
 717          * We cannot return state for more than 16 VTs, since v_state is short.
 718          */
 719         case VT_GETSTATE:
 720         {
 721                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 722                 unsigned short state, mask;
 723 
 724                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 725                 if (i)
 726                         return i;
 727                 put_user(fg_console + 1, &vtstat->v_active);
 728                 state = 1;      /* /dev/tty0 is always open */
 729                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 730                         if (VT_IS_IN_USE(i))
 731                                 state |= mask;
 732                 put_user(state, &vtstat->v_state);
 733                 return 0;
 734         }
 735 
 736         /*
 737          * Returns the first available (non-opened) console.
 738          */
 739         case VT_OPENQRY:
 740                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 741                 if (i)
 742                         return i;
 743                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 744                         if (! VT_IS_IN_USE(i))
 745                                 break;
 746                 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
 747                 return 0;
 748 
 749         /*
 750          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 751          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 752          * to preserve sanity).
 753          */
 754         case VT_ACTIVATE:
 755                 if (!perm)
 756                         return -EPERM;
 757                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 758                         return -ENXIO;
 759                 arg--;
 760                 i = vc_allocate(arg);
 761                 if (i)
 762                         return i;
 763                 change_console(arg);
 764                 return 0;
 765 
 766         /*
 767          * wait until the specified VT has been activated
 768          */
 769         case VT_WAITACTIVE:
 770                 if (!perm)
 771                         return -EPERM;
 772                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 773                         return -ENXIO;
 774                 arg--;
 775                 while (fg_console != arg)
 776                 {
 777                         if (vt_waitactive() < 0)
 778                                 return -EINTR;
 779                 }
 780                 return 0;
 781 
 782         /*
 783          * If a vt is under process control, the kernel will not switch to it
 784          * immediately, but postpone the operation until the process calls this
 785          * ioctl, allowing the switch to complete.
 786          *
 787          * According to the X sources this is the behavior:
 788          *      0:      pending switch-from not OK
 789          *      1:      pending switch-from OK
 790          *      2:      completed switch-to OK
 791          */
 792         case VT_RELDISP:
 793                 if (!perm)
 794                         return -EPERM;
 795                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 796                         return -EINVAL;
 797 
 798                 /*
 799                  * Switching-from response
 800                  */
 801                 if (vt_cons[console]->vt_newvt >= 0)
 802                 {
 803                         if (arg == 0)
 804                                 /*
 805                                  * Switch disallowed, so forget we were trying
 806                                  * to do it.
 807                                  */
 808                                 vt_cons[console]->vt_newvt = -1;
 809 
 810                         else
 811                         {
 812                                 /*
 813                                  * The current vt has been released, so
 814                                  * complete the switch.
 815                                  */
 816                                 int newvt = vt_cons[console]->vt_newvt;
 817                                 vt_cons[console]->vt_newvt = -1;
 818                                 i = vc_allocate(newvt);
 819                                 if (i)
 820                                         return i;
 821                                 complete_change_console(newvt);
 822                         }
 823                 }
 824 
 825                 /*
 826                  * Switched-to response
 827                  */
 828                 else
 829                 {
 830                         /*
 831                          * If it's just an ACK, ignore it
 832                          */
 833                         if (arg != VT_ACKACQ)
 834                                 return -EINVAL;
 835                 }
 836 
 837                 return 0;
 838 
 839          /*
 840           * Disallocate memory associated to VT (but leave VT1)
 841           */
 842          case VT_DISALLOCATE:
 843                 if (arg > MAX_NR_CONSOLES)
 844                         return -ENXIO;
 845                 if (arg == 0) {
 846                     /* disallocate all unused consoles, but leave 0 */
 847                     for (i=1; i<MAX_NR_CONSOLES; i++)
 848                       if (! VT_BUSY(i))
 849                         vc_disallocate(i);
 850                 } else {
 851                     /* disallocate a single console, if possible */
 852                     arg--;
 853                     if (VT_BUSY(arg))
 854                       return -EBUSY;
 855                     if (arg)                          /* leave 0 */
 856                       vc_disallocate(arg);
 857                 }
 858                 return 0;
 859 
 860         case VT_RESIZE:
 861         {
 862                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 863                 ushort ll,cc;
 864                 if (!perm)
 865                         return -EPERM;
 866                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 867                 if (i)
 868                         return i;
 869                 ll = get_user(&vtsizes->v_rows);
 870                 cc = get_user(&vtsizes->v_cols);
 871                 i = vc_resize(ll, cc);
 872                 return i ? i :  kd_size_changed(ll, cc);
 873         }
 874 
 875         case VT_RESIZEX:
 876         {
 877                 struct vt_consize *vtconsize = (struct vt_consize *) arg;
 878                 ushort ll,cc,vlin,clin,vcol,ccol;
 879                 if (!perm)
 880                         return -EPERM;
 881                 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 882                 if (i)
 883                         return i;
 884                 ll = get_user(&vtconsize->v_rows);
 885                 cc = get_user(&vtconsize->v_cols);
 886                 vlin = get_user(&vtconsize->v_vlin);
 887                 clin = get_user(&vtconsize->v_clin);
 888                 vcol = get_user(&vtconsize->v_vcol);
 889                 ccol = get_user(&vtconsize->v_ccol);
 890                 vlin = vlin ? vlin : video_scan_lines;
 891                 if ( clin )
 892                   {
 893                     if ( ll )
 894                       {
 895                         if ( ll != vlin/clin )
 896                           return EINVAL; /* Parameters don't add up */
 897                       }
 898                     else 
 899                       ll = vlin/clin;
 900                   }
 901                 if ( vcol && ccol )
 902                   {
 903                     if ( cc )
 904                       {
 905                         if ( cc != vcol/ccol )
 906                           return EINVAL;
 907                       }
 908                     else
 909                       cc = vcol/ccol;
 910                   }
 911 
 912                 if ( clin > 32 )
 913                   return EINVAL;
 914                     
 915                 if ( vlin )
 916                   video_scan_lines = vlin;
 917                 if ( clin )
 918                   video_font_height = clin;
 919                 
 920                 i = vc_resize(ll, cc);
 921                 if (i)
 922                         return i;
 923 
 924                 kd_size_changed(ll, cc);
 925                 return 0;
 926         }
 927 
 928         case PIO_FONT:
 929                 if (!perm)
 930                         return -EPERM;
 931                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 932                         return -EINVAL;
 933                 return con_set_font((char *)arg, 0);
 934                 /* con_set_font() defined in console.c */
 935 
 936         case GIO_FONT:
 937                 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
 938                     video_mode_512ch)
 939                         return -EINVAL;
 940                 return con_get_font((char *)arg);
 941                 /* con_get_font() defined in console.c */
 942 
 943         case PIO_CMAP:
 944                 if (!perm)
 945                         return -EPERM;
 946                 return con_set_cmap((char *)arg);
 947                 /* con_set_cmap() defined in console.c */
 948 
 949         case GIO_CMAP:
 950                 return con_get_cmap((char *)arg);
 951                 /* con_get_cmap() defined in console.c */
 952 
 953         case PIO_FONTX:
 954         {
 955                 struct consolefontdesc cfdarg;
 956 
 957                 if (!perm)
 958                         return -EPERM;
 959                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 960                         return -EINVAL;
 961                 i = verify_area(VERIFY_READ, (void *)arg,
 962                                 sizeof(struct consolefontdesc));
 963                 if (i) return i;
 964                 memcpy_fromfs(&cfdarg, (void *)arg,
 965                               sizeof(struct consolefontdesc)); 
 966                 
 967                 if ( cfdarg.charcount == 256 ||
 968                      cfdarg.charcount == 512 ) {
 969                         i = con_set_font(cfdarg.chardata,
 970                                 cfdarg.charcount == 512);
 971                         if (i)
 972                                 return i;
 973                         i = con_adjust_height(cfdarg.charheight);
 974                         return (i <= 0) ? i : kd_size_changed(i, 0);
 975                 } else
 976                         return -EINVAL;
 977         }
 978 
 979         case GIO_FONTX:
 980         {
 981                 struct consolefontdesc cfdarg;
 982                 int nchar;
 983 
 984                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 985                         return -EINVAL;
 986                 i = verify_area(VERIFY_WRITE, (void *)arg,
 987                         sizeof(struct consolefontdesc));
 988                 if (i) return i;        
 989                 memcpy_fromfs(&cfdarg, (void *) arg,
 990                               sizeof(struct consolefontdesc)); 
 991                 i = cfdarg.charcount;
 992                 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
 993                 cfdarg.charheight = video_font_height;
 994                 memcpy_tofs((void *) arg, &cfdarg,
 995                             sizeof(struct consolefontdesc)); 
 996                 if ( cfdarg.chardata )
 997                 {
 998                         if ( i < nchar )
 999                                 return -ENOMEM;
1000                         return con_get_font(cfdarg.chardata);
1001                 } else
1002                         return 0;
1003         }
1004 
1005         case PIO_SCRNMAP:
1006                 if (!perm)
1007                         return -EPERM;
1008                 return con_set_trans_old((unsigned char *)arg);
1009 
1010         case GIO_SCRNMAP:
1011                 return con_get_trans_old((unsigned char *)arg);
1012 
1013         case PIO_UNISCRNMAP:
1014                 if (!perm)
1015                         return -EPERM;
1016                 return con_set_trans_new((unsigned short *)arg);
1017 
1018         case GIO_UNISCRNMAP:
1019                 return con_get_trans_new((unsigned short *)arg);
1020 
1021         case PIO_UNIMAPCLR:
1022               { struct unimapinit ui;
1023                 if (!perm)
1024                         return -EPERM;
1025                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1026                 if (i)
1027                   return i;
1028                 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1029                 con_clear_unimap(&ui);
1030                 return 0;
1031               }
1032 
1033         case PIO_UNIMAP:
1034               { struct unimapdesc *ud;
1035                 u_short ct;
1036                 struct unipair *list;
1037 
1038                 if (!perm)
1039                         return -EPERM;
1040                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1041                 if (i == 0) {
1042                     ud = (struct unimapdesc *) arg;
1043                     ct = get_user(&ud->entry_ct);
1044                     list = get_user(&ud->entries);
1045                     i = verify_area(VERIFY_READ, (void *) list,
1046                                     ct*sizeof(struct unipair));
1047                 }
1048                 if (i)
1049                   return i;
1050                 return con_set_unimap(ct, list);
1051               }
1052 
1053         case GIO_UNIMAP:
1054               { struct unimapdesc *ud;
1055                 u_short ct;
1056                 struct unipair *list;
1057 
1058                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1059                 if (i == 0) {
1060                     ud = (struct unimapdesc *) arg;
1061                     ct = get_user(&ud->entry_ct);
1062                     list = get_user(&ud->entries);
1063                     if (ct)
1064                       i = verify_area(VERIFY_WRITE, (void *) list,
1065                                       ct*sizeof(struct unipair));
1066                 }
1067                 if (i)
1068                   return i;
1069                 return con_get_unimap(ct, &(ud->entry_ct), list);
1070               }
1071  
1072         default:
1073                 return -ENOIOCTLCMD;
1074         }
1075 }

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