Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

vt.c

Go to the documentation of this file.
00001 /*
00002  *  linux/drivers/char/vt.c
00003  *
00004  *  Copyright (C) 1992 obz under the linux copyright
00005  *
00006  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
00007  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
00008  *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
00009  *  Some code moved for less code duplication - Andi Kleen - Mar 1997
00010  */
00011 
00012 #include <linux/config.h>
00013 #include <linux/types.h>
00014 #include <linux/errno.h>
00015 #include <linux/sched.h>
00016 #include <linux/tty.h>
00017 #include <linux/timer.h>
00018 #include <linux/kernel.h>
00019 #include <linux/kd.h>
00020 #include <linux/vt.h>
00021 #include <linux/string.h>
00022 #include <linux/malloc.h>
00023 #include <linux/major.h>
00024 #include <linux/fs.h>
00025 
00026 #include <asm/io.h>
00027 #include <asm/uaccess.h>
00028 
00029 #include <linux/kbd_kern.h>
00030 #include <linux/vt_kern.h>
00031 #include <linux/kbd_diacr.h>
00032 #include <linux/selection.h>
00033 
00034 #ifdef CONFIG_FB_COMPAT_XPMAC
00035 #include <asm/vc_ioctl.h>
00036 #endif /* CONFIG_FB_COMPAT_XPMAC */
00037 
00038 char vt_dont_switch = 0;
00039 extern struct tty_driver console_driver;
00040 
00041 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
00042 #define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
00043 
00044 /*
00045  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
00046  * experimentation and study of X386 SYSV handling.
00047  *
00048  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
00049  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
00050  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
00051  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
00052  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
00053  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
00054  * to the current console is done by the main ioctl code.
00055  */
00056 
00057 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
00058 
00059 /* Keyboard type: Default is KB_101, but can be set by machine
00060  * specific code.
00061  */
00062 unsigned char keyboard_type = KB_101;
00063 
00064 #ifndef __alpha__
00065 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
00066 #endif
00067 
00068 unsigned int video_font_height;
00069 unsigned int default_font_height;
00070 unsigned int video_scan_lines;
00071 
00072 /*
00073  * these are the valid i/o ports we're allowed to change. they map all the
00074  * video ports
00075  */
00076 #define GPFIRST 0x3b4
00077 #define GPLAST 0x3df
00078 #define GPNUM (GPLAST - GPFIRST + 1)
00079 
00080 /*
00081  * Generates sound of some frequency for some number of clock ticks
00082  *
00083  * If freq is 0, will turn off sound, else will turn it on for that time.
00084  * If msec is 0, will return immediately, else will sleep for msec time, then
00085  * turn sound off.
00086  *
00087  * We also return immediately, which is what was implied within the X
00088  * comments - KDMKTONE doesn't put the process to sleep.
00089  */
00090 
00091 #if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
00092     || (defined(__mips__) && !defined(CONFIG_SGI))
00093 
00094 static void
00095 kd_nosound(unsigned long ignored)
00096 {
00097         /* disable counter 2 */
00098         outb(inb_p(0x61)&0xFC, 0x61);
00099         return;
00100 }
00101 
00102 void
00103 _kd_mksound(unsigned int hz, unsigned int ticks)
00104 {
00105         static struct timer_list sound_timer = { NULL, NULL, 0, 0,
00106                                                  kd_nosound };
00107 
00108         unsigned int count = 0;
00109 
00110         if (hz > 20 && hz < 32767)
00111                 count = 1193180 / hz;
00112         
00113         cli();
00114         del_timer(&sound_timer);
00115         if (count) {
00116                 /* enable counter 2 */
00117                 outb_p(inb_p(0x61)|3, 0x61);
00118                 /* set command for counter 2, 2 byte write */
00119                 outb_p(0xB6, 0x43);
00120                 /* select desired HZ */
00121                 outb_p(count & 0xff, 0x42);
00122                 outb((count >> 8) & 0xff, 0x42);
00123 
00124                 if (ticks) {
00125                         sound_timer.expires = jiffies+ticks;
00126                         add_timer(&sound_timer);
00127                 }
00128         } else
00129                 kd_nosound(0);
00130         sti();
00131         return;
00132 }
00133 
00134 #else
00135 
00136 void
00137 _kd_mksound(unsigned int hz, unsigned int ticks)
00138 {
00139 }
00140 
00141 #endif
00142 
00143 void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
00144 
00145 
00146 #define i (tmp.kb_index)
00147 #define s (tmp.kb_table)
00148 #define v (tmp.kb_value)
00149 static inline int
00150 do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
00151 {
00152         struct kbentry tmp;
00153         ushort *key_map, val, ov;
00154 
00155         if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
00156                 return -EFAULT;
00157         if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
00158                 return -EINVAL; 
00159 
00160         switch (cmd) {
00161         case KDGKBENT:
00162                 key_map = key_maps[s];
00163                 if (key_map) {
00164                     val = U(key_map[i]);
00165                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
00166                         val = K_HOLE;
00167                 } else
00168                     val = (i ? K_HOLE : K_NOSUCHMAP);
00169                 return put_user(val, &user_kbe->kb_value);
00170         case KDSKBENT:
00171                 if (!perm)
00172                         return -EPERM;
00173                 if (!i && v == K_NOSUCHMAP) {
00174                         /* disallocate map */
00175                         key_map = key_maps[s];
00176                         if (s && key_map) {
00177                             key_maps[s] = 0;
00178                             if (key_map[0] == U(K_ALLOCATED)) {
00179                                         kfree_s(key_map, sizeof(plain_map));
00180                                         keymap_count--;
00181                             }
00182                         }
00183                         break;
00184                 }
00185 
00186                 if (KTYP(v) < NR_TYPES) {
00187                     if (KVAL(v) > max_vals[KTYP(v)])
00188                                 return -EINVAL;
00189                 } else
00190                     if (kbd->kbdmode != VC_UNICODE)
00191                                 return -EINVAL;
00192 
00193                 /* ++Geert: non-PC keyboards may generate keycode zero */
00194 #if !defined(__mc68000__) && !defined(__powerpc__)
00195                 /* assignment to entry 0 only tests validity of args */
00196                 if (!i)
00197                         break;
00198 #endif
00199 
00200                 if (!(key_map = key_maps[s])) {
00201                         int j;
00202 
00203                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 
00204                             !capable(CAP_SYS_RESOURCE))
00205                                 return -EPERM;
00206 
00207                         key_map = (ushort *) kmalloc(sizeof(plain_map),
00208                                                      GFP_KERNEL);
00209                         if (!key_map)
00210                                 return -ENOMEM;
00211                         key_maps[s] = key_map;
00212                         key_map[0] = U(K_ALLOCATED);
00213                         for (j = 1; j < NR_KEYS; j++)
00214                                 key_map[j] = U(K_HOLE);
00215                         keymap_count++;
00216                 }
00217                 ov = U(key_map[i]);
00218                 if (v == ov)
00219                         break;  /* nothing to do */
00220                 /*
00221                  * Attention Key.
00222                  */
00223                 if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
00224                         return -EPERM;
00225                 key_map[i] = U(v);
00226                 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
00227                         compute_shiftstate();
00228                 break;
00229         }
00230         return 0;
00231 }
00232 #undef i
00233 #undef s
00234 #undef v
00235 
00236 static inline int 
00237 do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
00238 {
00239         struct kbkeycode tmp;
00240         int kc = 0;
00241 
00242         if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
00243                 return -EFAULT;
00244         switch (cmd) {
00245         case KDGETKEYCODE:
00246                 kc = getkeycode(tmp.scancode);
00247                 if (kc >= 0)
00248                         kc = put_user(kc, &user_kbkc->keycode);
00249                 break;
00250         case KDSETKEYCODE:
00251                 if (!perm)
00252                         return -EPERM;
00253                 kc = setkeycode(tmp.scancode, tmp.keycode);
00254                 break;
00255         }
00256         return kc;
00257 }
00258 
00259 static inline int
00260 do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
00261 {
00262         struct kbsentry tmp;
00263         char *p;
00264         u_char *q;
00265         int sz;
00266         int delta;
00267         char *first_free, *fj, *fnw;
00268         int i, j, k;
00269 
00270         /* we mostly copy too much here (512bytes), but who cares ;) */
00271         if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
00272                 return -EFAULT;
00273         tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0';
00274         if (tmp.kb_func >= MAX_NR_FUNC)
00275                 return -EINVAL;
00276         i = tmp.kb_func;
00277 
00278         switch (cmd) {
00279         case KDGKBSENT:
00280                 sz = sizeof(tmp.kb_string) - 1; /* sz should have been
00281                                                   a struct member */
00282                 q = user_kdgkb->kb_string;
00283                 p = func_table[i];
00284                 if(p)
00285                         for ( ; *p && sz; p++, sz--)
00286                                 put_user(*p, q++);
00287                 put_user('\0', q);
00288                 return ((p && *p) ? -EOVERFLOW : 0);
00289         case KDSKBSENT:
00290                 if (!perm)
00291                         return -EPERM;
00292 
00293                 q = func_table[i];
00294                 first_free = funcbufptr + (funcbufsize - funcbufleft);
00295                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 
00296                         ;
00297                 if (j < MAX_NR_FUNC)
00298                         fj = func_table[j];
00299                 else
00300                         fj = first_free;
00301 
00302                 delta = (q ? -strlen(q) : 1) + strlen(tmp.kb_string);
00303                 if (delta <= funcbufleft) {     /* it fits in current buf */
00304                     if (j < MAX_NR_FUNC) {
00305                         memmove(fj + delta, fj, first_free - fj);
00306                         for (k = j; k < MAX_NR_FUNC; k++)
00307                             if (func_table[k])
00308                                 func_table[k] += delta;
00309                     }
00310                     if (!q)
00311                       func_table[i] = fj;
00312                     funcbufleft -= delta;
00313                 } else {                        /* allocate a larger buffer */
00314                     sz = 256;
00315                     while (sz < funcbufsize - funcbufleft + delta)
00316                       sz <<= 1;
00317                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
00318                     if(!fnw)
00319                       return -ENOMEM;
00320 
00321                     if (!q)
00322                       func_table[i] = fj;
00323                     if (fj > funcbufptr)
00324                         memmove(fnw, funcbufptr, fj - funcbufptr);
00325                     for (k = 0; k < j; k++)
00326                       if (func_table[k])
00327                         func_table[k] = fnw + (func_table[k] - funcbufptr);
00328 
00329                     if (first_free > fj) {
00330                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
00331                         for (k = j; k < MAX_NR_FUNC; k++)
00332                           if (func_table[k])
00333                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
00334                     }
00335                     if (funcbufptr != func_buf)
00336                       kfree_s(funcbufptr, funcbufsize);
00337                     funcbufptr = fnw;
00338                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
00339                     funcbufsize = sz;
00340                 }
00341                 strcpy(func_table[i], tmp.kb_string);
00342                 break;
00343         }
00344         return 0;
00345 }
00346 
00347 static inline int 
00348 do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm)
00349 {
00350         struct consolefontdesc cfdarg;
00351         struct console_font_op op;
00352         int i;
00353 
00354         if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 
00355                 return -EFAULT;
00356         
00357         switch (cmd) {
00358         case PIO_FONTX:
00359                 if (!perm)
00360                         return -EPERM;
00361                 op.op = KD_FONT_OP_SET;
00362                 op.flags = KD_FONT_FLAG_OLD;
00363                 op.width = 8;
00364                 op.height = cfdarg.charheight;
00365                 op.charcount = cfdarg.charcount;
00366                 op.data = cfdarg.chardata;
00367                 return con_font_op(fg_console, &op);
00368         case GIO_FONTX: {
00369                 op.op = KD_FONT_OP_GET;
00370                 op.flags = KD_FONT_FLAG_OLD;
00371                 op.width = 8;
00372                 op.height = cfdarg.charheight;
00373                 op.charcount = cfdarg.charcount;
00374                 op.data = cfdarg.chardata;
00375                 i = con_font_op(fg_console, &op);
00376                 if (i)
00377                         return i;
00378                 cfdarg.charheight = op.height;
00379                 cfdarg.charcount = op.charcount;
00380                 if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
00381                         return -EFAULT;
00382                 return 0;
00383                 }
00384         }
00385         return -EINVAL;
00386 }
00387 
00388 static inline int 
00389 do_unimap_ioctl(int cmd, struct unimapdesc *user_ud,int perm)
00390 {
00391         struct unimapdesc tmp;
00392         int i = 0; 
00393 
00394         if (copy_from_user(&tmp, user_ud, sizeof tmp))
00395                 return -EFAULT;
00396         if (tmp.entries) {
00397                 /* tmp.entry_ct is an unsigned short */
00398                 i = verify_area(VERIFY_WRITE, tmp.entries,
00399                                 (size_t)tmp.entry_ct * sizeof(struct unipair));
00400                 if (i) return i;
00401         }
00402         switch (cmd) {
00403         case PIO_UNIMAP:
00404                 if (!perm)
00405                         return -EPERM;
00406                 return con_set_unimap(fg_console, tmp.entry_ct, tmp.entries);
00407         case GIO_UNIMAP:
00408                 return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
00409         }
00410         return 0;
00411 }
00412 
00413 /*
00414  * We handle the console-specific ioctl's here.  We allow the
00415  * capability to modify any console, not just the fg_console. 
00416  */
00417 int vt_ioctl(struct tty_struct *tty, struct file * file,
00418              unsigned int cmd, unsigned long arg)
00419 {
00420         int i, perm;
00421         unsigned int console;
00422         unsigned char ucval;
00423         struct kbd_struct * kbd;
00424         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
00425 
00426         console = vt->vc_num;
00427 
00428         if (!vc_cons_allocated(console))        /* impossible? */
00429                 return -ENOIOCTLCMD;
00430 
00431         /*
00432          * To have permissions to do most of the vt ioctls, we either have
00433          * to be the owner of the tty, or super-user.
00434          */
00435         perm = 0;
00436         if (current->tty == tty || suser())
00437                 perm = 1;
00438  
00439         kbd = kbd_table + console;
00440         switch (cmd) {
00441         case KIOCSOUND:
00442                 if (!perm)
00443                         return -EPERM;
00444                 if (arg)
00445                         arg = 1193180 / arg;
00446                 kd_mksound(arg, 0);
00447                 return 0;
00448 
00449         case KDMKTONE:
00450                 if (!perm)
00451                         return -EPERM;
00452         {
00453                 unsigned int ticks, count;
00454                 
00455                 /*
00456                  * Generate the tone for the appropriate number of ticks.
00457                  * If the time is zero, turn off sound ourselves.
00458                  */
00459                 ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
00460                 count = ticks ? (arg & 0xffff) : 0;
00461                 if (count)
00462                         count = 1193180 / count;
00463                 kd_mksound(count, ticks);
00464                 return 0;
00465         }
00466 
00467         case KDGKBTYPE:
00468                 /*
00469                  * this is naive.
00470                  */
00471                 ucval = keyboard_type;
00472                 goto setchar;
00473 
00474 #ifndef __alpha__
00475                 /*
00476                  * These cannot be implemented on any machine that implements
00477                  * ioperm() in user level (such as Alpha PCs).
00478                  */
00479         case KDADDIO:
00480         case KDDELIO:
00481                 /*
00482                  * KDADDIO and KDDELIO may be able to add ports beyond what
00483                  * we reject here, but to be safe...
00484                  */
00485                 if (arg < GPFIRST || arg > GPLAST)
00486                         return -EINVAL;
00487                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
00488 
00489         case KDENABIO:
00490         case KDDISABIO:
00491                 return sys_ioperm(GPFIRST, GPNUM,
00492                                   (cmd == KDENABIO)) ? -ENXIO : 0;
00493 #endif
00494 
00495         case KDSETMODE:
00496                 /*
00497                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
00498                  * doesn't do a whole lot. i'm not sure if it should do any
00499                  * restoration of modes or what...
00500                  */
00501                 if (!perm)
00502                         return -EPERM;
00503                 switch (arg) {
00504                 case KD_GRAPHICS:
00505                         break;
00506                 case KD_TEXT0:
00507                 case KD_TEXT1:
00508                         arg = KD_TEXT;
00509                 case KD_TEXT:
00510                         break;
00511                 default:
00512                         return -EINVAL;
00513                 }
00514                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
00515                         return 0;
00516                 vt_cons[console]->vc_mode = (unsigned char) arg;
00517                 if (console != fg_console)
00518                         return 0;
00519                 /*
00520                  * explicitly blank/unblank the screen if switching modes
00521                  */
00522                 if (arg == KD_TEXT)
00523                         unblank_screen();
00524                 else
00525                         do_blank_screen(1);
00526                 return 0;
00527 
00528         case KDGETMODE:
00529                 ucval = vt_cons[console]->vc_mode;
00530                 goto setint;
00531 
00532         case KDMAPDISP:
00533         case KDUNMAPDISP:
00534                 /*
00535                  * these work like a combination of mmap and KDENABIO.
00536                  * this could be easily finished.
00537                  */
00538                 return -EINVAL;
00539 
00540         case KDSKBMODE:
00541                 if (!perm)
00542                         return -EPERM;
00543                 switch(arg) {
00544                   case K_RAW:
00545                         kbd->kbdmode = VC_RAW;
00546                         break;
00547                   case K_MEDIUMRAW:
00548                         kbd->kbdmode = VC_MEDIUMRAW;
00549                         break;
00550                   case K_XLATE:
00551                         kbd->kbdmode = VC_XLATE;
00552                         compute_shiftstate();
00553                         break;
00554                   case K_UNICODE:
00555                         kbd->kbdmode = VC_UNICODE;
00556                         compute_shiftstate();
00557                         break;
00558                   default:
00559                         return -EINVAL;
00560                 }
00561                 if (tty->ldisc.flush_buffer)
00562                         tty->ldisc.flush_buffer(tty);
00563                 return 0;
00564 
00565         case KDGKBMODE:
00566                 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
00567                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
00568                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
00569                                  K_XLATE);
00570                 goto setint;
00571 
00572         /* this could be folded into KDSKBMODE, but for compatibility
00573            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
00574         case KDSKBMETA:
00575                 switch(arg) {
00576                   case K_METABIT:
00577                         clr_vc_kbd_mode(kbd, VC_META);
00578                         break;
00579                   case K_ESCPREFIX:
00580                         set_vc_kbd_mode(kbd, VC_META);
00581                         break;
00582                   default:
00583                         return -EINVAL;
00584                 }
00585                 return 0;
00586 
00587         case KDGKBMETA:
00588                 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
00589         setint:
00590                 return put_user(ucval, (int *)arg); 
00591 
00592         case KDGETKEYCODE:
00593         case KDSETKEYCODE:
00594                 if(!suser())
00595                         perm=0;
00596                 return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
00597 
00598         case KDGKBENT:
00599         case KDSKBENT:
00600                 return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
00601 
00602         case KDGKBSENT:
00603         case KDSKBSENT:
00604                 return do_kdgkb_ioctl(cmd, (struct kbsentry *)arg, perm);
00605 
00606         case KDGKBDIACR:
00607         {
00608                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
00609 
00610                 if (put_user(accent_table_size, &a->kb_cnt))
00611                         return -EFAULT;
00612                 if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
00613                         return -EFAULT;
00614                 return 0;
00615         }
00616 
00617         case KDSKBDIACR:
00618         {
00619                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
00620                 unsigned int ct;
00621 
00622                 if (!perm)
00623                         return -EPERM;
00624                 if (get_user(ct,&a->kb_cnt))
00625                         return -EFAULT;
00626                 if (ct >= MAX_DIACR)
00627                         return -EINVAL;
00628                 accent_table_size = ct;
00629                 if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
00630                         return -EFAULT;
00631                 return 0;
00632         }
00633 
00634         /* the ioctls below read/set the flags usually shown in the leds */
00635         /* don't use them - they will go away without warning */
00636         case KDGKBLED:
00637                 ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
00638                 goto setchar;
00639 
00640         case KDSKBLED:
00641                 if (!perm)
00642                         return -EPERM;
00643                 if (arg & ~0x77)
00644                         return -EINVAL;
00645                 kbd->ledflagstate = (arg & 7);
00646                 kbd->default_ledflagstate = ((arg >> 4) & 7);
00647                 set_leds();
00648                 return 0;
00649 
00650         /* the ioctls below only set the lights, not the functions */
00651         /* for those, see KDGKBLED and KDSKBLED above */
00652         case KDGETLED:
00653                 ucval = getledstate();
00654         setchar:
00655                 return put_user(ucval, (char*)arg);
00656 
00657         case KDSETLED:
00658                 if (!perm)
00659                   return -EPERM;
00660                 setledstate(kbd, arg);
00661                 return 0;
00662 
00663         /*
00664          * A process can indicate its willingness to accept signals
00665          * generated by pressing an appropriate key combination.
00666          * Thus, one can have a daemon that e.g. spawns a new console
00667          * upon a keypress and then changes to it.
00668          * Probably init should be changed to do this (and have a
00669          * field ks (`keyboard signal') in inittab describing the
00670          * desired action), so that the number of background daemons
00671          * does not increase.
00672          */
00673         case KDSIGACCEPT:
00674         {
00675                 extern int spawnpid, spawnsig;
00676                 if (!perm)
00677                   return -EPERM;
00678                 if (arg < 1 || arg > _NSIG || arg == SIGKILL)
00679                   return -EINVAL;
00680                 spawnpid = current->pid;
00681                 spawnsig = arg;
00682                 return 0;
00683         }
00684 
00685         case VT_SETMODE:
00686         {
00687                 struct vt_mode tmp;
00688 
00689                 if (!perm)
00690                         return -EPERM;
00691                 if (copy_from_user(&tmp, (void*)arg, sizeof(struct vt_mode)))
00692                         return -EFAULT;
00693                 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
00694                         return -EINVAL;
00695                 vt_cons[console]->vt_mode = tmp;
00696                 /* the frsig is ignored, so we set it to 0 */
00697                 vt_cons[console]->vt_mode.frsig = 0;
00698                 vt_cons[console]->vt_pid = current->pid;
00699                 /* no switch is required -- saw@shade.msu.ru */
00700                 vt_cons[console]->vt_newvt = -1; 
00701                 return 0;
00702         }
00703 
00704         case VT_GETMODE:
00705                 return copy_to_user((void*)arg, &(vt_cons[console]->vt_mode), 
00706                                                         sizeof(struct vt_mode)) ? -EFAULT : 0; 
00707 
00708         /*
00709          * Returns global vt state. Note that VT 0 is always open, since
00710          * it's an alias for the current VT, and people can't use it here.
00711          * We cannot return state for more than 16 VTs, since v_state is short.
00712          */
00713         case VT_GETSTATE:
00714         {
00715                 struct vt_stat *vtstat = (struct vt_stat *)arg;
00716                 unsigned short state, mask;
00717 
00718                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
00719                 if (i)
00720                         return i;
00721                 put_user(fg_console + 1, &vtstat->v_active);
00722                 state = 1;      /* /dev/tty0 is always open */
00723                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
00724                         if (VT_IS_IN_USE(i))
00725                                 state |= mask;
00726                 return put_user(state, &vtstat->v_state);
00727         }
00728 
00729         /*
00730          * Returns the first available (non-opened) console.
00731          */
00732         case VT_OPENQRY:
00733                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
00734                         if (! VT_IS_IN_USE(i))
00735                                 break;
00736                 ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;
00737                 goto setint;             
00738 
00739         /*
00740          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
00741          * with num >= 1 (switches to vt 0, our console, are not allowed, just
00742          * to preserve sanity).
00743          */
00744         case VT_ACTIVATE:
00745                 if (!perm)
00746                         return -EPERM;
00747                 if (arg == 0 || arg > MAX_NR_CONSOLES)
00748                         return -ENXIO;
00749                 arg--;
00750                 i = vc_allocate(arg);
00751                 if (i)
00752                         return i;
00753                 set_console(arg);
00754                 return 0;
00755 
00756         /*
00757          * wait until the specified VT has been activated
00758          */
00759         case VT_WAITACTIVE:
00760                 if (!perm)
00761                         return -EPERM;
00762                 if (arg == 0 || arg > MAX_NR_CONSOLES)
00763                         return -ENXIO;
00764                 return vt_waitactive(arg-1);
00765 
00766         /*
00767          * If a vt is under process control, the kernel will not switch to it
00768          * immediately, but postpone the operation until the process calls this
00769          * ioctl, allowing the switch to complete.
00770          *
00771          * According to the X sources this is the behavior:
00772          *      0:      pending switch-from not OK
00773          *      1:      pending switch-from OK
00774          *      2:      completed switch-to OK
00775          */
00776         case VT_RELDISP:
00777                 if (!perm)
00778                         return -EPERM;
00779                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
00780                         return -EINVAL;
00781 
00782                 /*
00783                  * Switching-from response
00784                  */
00785                 if (vt_cons[console]->vt_newvt >= 0)
00786                 {
00787                         if (arg == 0)
00788                                 /*
00789                                  * Switch disallowed, so forget we were trying
00790                                  * to do it.
00791                                  */
00792                                 vt_cons[console]->vt_newvt = -1;
00793 
00794                         else
00795                         {
00796                                 /*
00797                                  * The current vt has been released, so
00798                                  * complete the switch.
00799                                  */
00800                                 int newvt = vt_cons[console]->vt_newvt;
00801                                 vt_cons[console]->vt_newvt = -1;
00802                                 i = vc_allocate(newvt);
00803                                 if (i)
00804                                         return i;
00805                                 /*
00806                                  * When we actually do the console switch,
00807                                  * make sure we are atomic with respect to
00808                                  * other console switches..
00809                                  */
00810                                 start_bh_atomic();
00811                                 complete_change_console(newvt);
00812                                 end_bh_atomic();
00813                         }
00814                 }
00815 
00816                 /*
00817                  * Switched-to response
00818                  */
00819                 else
00820                 {
00821                         /*
00822                          * If it's just an ACK, ignore it
00823                          */
00824                         if (arg != VT_ACKACQ)
00825                                 return -EINVAL;
00826                 }
00827 
00828                 return 0;
00829 
00830          /*
00831           * Disallocate memory associated to VT (but leave VT1)
00832           */
00833          case VT_DISALLOCATE:
00834                 if (arg > MAX_NR_CONSOLES)
00835                         return -ENXIO;
00836                 if (arg == 0) {
00837                     /* disallocate all unused consoles, but leave 0 */
00838                     for (i=1; i<MAX_NR_CONSOLES; i++)
00839                       if (! VT_BUSY(i))
00840                         vc_disallocate(i);
00841                 } else {
00842                     /* disallocate a single console, if possible */
00843                     arg--;
00844                     if (VT_BUSY(arg))
00845                       return -EBUSY;
00846                     if (arg)                          /* leave 0 */
00847                       vc_disallocate(arg);
00848                 }
00849                 return 0;
00850 
00851         case VT_RESIZE:
00852         {
00853                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
00854                 ushort ll,cc;
00855                 if (!perm)
00856                         return -EPERM;
00857                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
00858                 if (i)
00859                         return i;
00860                 get_user(ll, &vtsizes->v_rows);
00861                 get_user(cc, &vtsizes->v_cols);
00862                 return vc_resize_all(ll, cc);
00863         }
00864 
00865         case VT_RESIZEX:
00866         {
00867                 struct vt_consize *vtconsize = (struct vt_consize *) arg;
00868                 ushort ll,cc,vlin,clin,vcol,ccol;
00869                 if (!perm)
00870                         return -EPERM;
00871                 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
00872                 if (i)
00873                         return i;
00874                 get_user(ll, &vtconsize->v_rows);
00875                 get_user(cc, &vtconsize->v_cols);
00876                 get_user(vlin, &vtconsize->v_vlin);
00877                 get_user(clin, &vtconsize->v_clin);
00878                 get_user(vcol, &vtconsize->v_vcol);
00879                 get_user(ccol, &vtconsize->v_ccol);
00880                 vlin = vlin ? vlin : video_scan_lines;
00881                 if ( clin )
00882                   {
00883                     if ( ll )
00884                       {
00885                         if ( ll != vlin/clin )
00886                           return -EINVAL; /* Parameters don't add up */
00887                       }
00888                     else 
00889                       ll = vlin/clin;
00890                   }
00891                 if ( vcol && ccol )
00892                   {
00893                     if ( cc )
00894                       {
00895                         if ( cc != vcol/ccol )
00896                           return -EINVAL;
00897                       }
00898                     else
00899                       cc = vcol/ccol;
00900                   }
00901 
00902                 if ( clin > 32 )
00903                   return -EINVAL;
00904                     
00905                 if ( vlin )
00906                   video_scan_lines = vlin;
00907                 if ( clin )
00908                   video_font_height = clin;
00909                 
00910                 return vc_resize_all(ll, cc);
00911         }
00912 
00913         case PIO_FONT: {
00914                 struct console_font_op op;
00915                 if (!perm)
00916                         return -EPERM;
00917                 op.op = KD_FONT_OP_SET;
00918                 op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
00919                 op.width = 8;
00920                 op.height = 0;
00921                 op.charcount = 256;
00922                 op.data = (char *) arg;
00923                 return con_font_op(fg_console, &op);
00924         }
00925 
00926         case GIO_FONT: {
00927                 struct console_font_op op;
00928                 op.op = KD_FONT_OP_GET;
00929                 op.flags = KD_FONT_FLAG_OLD;
00930                 op.width = 8;
00931                 op.height = 32;
00932                 op.charcount = 256;
00933                 op.data = (char *) arg;
00934                 return con_font_op(fg_console, &op);
00935         }
00936 
00937         case PIO_CMAP:
00938                 if (!perm)
00939                         return -EPERM;
00940                 return con_set_cmap((char *)arg);
00941 
00942         case GIO_CMAP:
00943                 return con_get_cmap((char *)arg);
00944 
00945         case PIO_FONTX:
00946         case GIO_FONTX:
00947                 return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm);
00948 
00949         case PIO_FONTRESET:
00950         {
00951                 if (!perm)
00952                         return -EPERM;
00953 
00954 #ifdef BROKEN_GRAPHICS_PROGRAMS
00955                 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
00956                    font is not saved. */
00957                 return -ENOSYS;
00958 #else
00959                 {
00960                 struct console_font_op op;
00961                 op.op = KD_FONT_OP_SET_DEFAULT;
00962                 op.data = NULL;
00963                 i = con_font_op(fg_console, &op);
00964                 if (i) return i;
00965                 con_set_default_unimap(fg_console);
00966                 return 0;
00967                 }
00968 #endif
00969         }
00970 
00971         case KDFONTOP: {
00972                 struct console_font_op op;
00973                 if (copy_from_user(&op, (void *) arg, sizeof(op)))
00974                         return -EFAULT;
00975                 if (!perm && op.op != KD_FONT_OP_GET)
00976                         return -EPERM;
00977                 i = con_font_op(console, &op);
00978                 if (i) return i;
00979                 if (copy_to_user((void *) arg, &op, sizeof(op)))
00980                         return -EFAULT;
00981                 return 0;
00982         }
00983 
00984         case PIO_SCRNMAP:
00985                 if (!perm)
00986                         return -EPERM;
00987                 return con_set_trans_old((unsigned char *)arg);
00988 
00989         case GIO_SCRNMAP:
00990                 return con_get_trans_old((unsigned char *)arg);
00991 
00992         case PIO_UNISCRNMAP:
00993                 if (!perm)
00994                         return -EPERM;
00995                 return con_set_trans_new((unsigned short *)arg);
00996 
00997         case GIO_UNISCRNMAP:
00998                 return con_get_trans_new((unsigned short *)arg);
00999 
01000         case PIO_UNIMAPCLR:
01001               { struct unimapinit ui;
01002                 if (!perm)
01003                         return -EPERM;
01004                 i = copy_from_user(&ui, (void *)arg, sizeof(struct unimapinit));
01005                 if (i) return -EFAULT;
01006                 con_clear_unimap(fg_console, &ui);
01007                 return 0;
01008               }
01009 
01010         case PIO_UNIMAP:
01011         case GIO_UNIMAP:
01012                 return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm);
01013 
01014         case VT_LOCKSWITCH:
01015                 if (!suser())
01016                    return -EPERM;
01017                 vt_dont_switch = 1;
01018                 return 0;
01019         case VT_UNLOCKSWITCH:
01020                 if (!suser())
01021                    return -EPERM;
01022                 vt_dont_switch = 0;
01023                 return 0;
01024 #ifdef CONFIG_FB_COMPAT_XPMAC
01025         case VC_GETMODE:
01026                 {
01027                         struct vc_mode mode;
01028 
01029                         i = verify_area(VERIFY_WRITE, (void *) arg,
01030                                         sizeof(struct vc_mode));
01031                         if (i == 0)
01032                                 i = console_getmode(&mode);
01033                         if (i)
01034                                 return i;
01035                         if (copy_to_user((void *) arg, &mode, sizeof(mode)))
01036                                 return -EFAULT;
01037                         return 0;
01038                 }
01039         case VC_SETMODE:
01040         case VC_INQMODE:
01041                 {
01042                         struct vc_mode mode;
01043 
01044                         if (!perm)
01045                                 return -EPERM;
01046                         i = verify_area(VERIFY_READ, (void *) arg,
01047                                         sizeof(struct vc_mode));
01048                         if (i)
01049                                 return i;
01050                         if (copy_from_user(&mode, (void *) arg, sizeof(mode)))
01051                                 return -EFAULT;
01052                         return console_setmode(&mode, cmd == VC_SETMODE);
01053                 }
01054         case VC_SETCMAP:
01055                 {
01056                         unsigned char cmap[3][256], *p;
01057                         int n_entries, cmap_size, i, j;
01058 
01059                         if (!perm)
01060                                 return -EPERM;
01061                         if (arg == (unsigned long) VC_POWERMODE_INQUIRY
01062                             || arg <= VESA_POWERDOWN) {
01063                                 /* compatibility hack: VC_POWERMODE
01064                                    was changed from 0x766a to 0x766c */
01065                                 return console_powermode((int) arg);
01066                         }
01067                         i = verify_area(VERIFY_READ, (void *) arg,
01068                                         sizeof(int));
01069                         if (i)
01070                                 return i;
01071                         if (get_user(cmap_size, (int *) arg))
01072                                 return -EFAULT;
01073                         if (cmap_size % 3)
01074                                 return -EINVAL;
01075                         n_entries = cmap_size / 3;
01076                         if ((unsigned) n_entries > 256)
01077                                 return -EINVAL;
01078                         p = (unsigned char *) (arg + sizeof(int));
01079                         for (j = 0; j < n_entries; ++j)
01080                                 for (i = 0; i < 3; ++i)
01081                                         if (get_user(cmap[i][j], p++))
01082                                                 return -EFAULT;
01083                         return console_setcmap(n_entries, cmap[0],
01084                                                cmap[1], cmap[2]);
01085                 }
01086         case VC_GETCMAP:
01087                 /* not implemented yet */
01088                 return -ENOIOCTLCMD;
01089         case VC_POWERMODE:
01090                 if (!perm)
01091                         return -EPERM;
01092                 return console_powermode((int) arg);
01093 #endif /* CONFIG_FB_COMPAT_XPMAC */
01094         default:
01095                 return -ENOIOCTLCMD;
01096         }
01097 }
01098 
01099 /*
01100  * Sometimes we want to wait until a particular VT has been activated. We
01101  * do it in a very simple manner. Everybody waits on a single queue and
01102  * get woken up at once. Those that are satisfied go on with their business,
01103  * while those not ready go back to sleep. Seems overkill to add a wait
01104  * to each vt just for this - usually this does nothing!
01105  */
01106 static struct wait_queue *vt_activate_queue = NULL;
01107 
01108 /*
01109  * Sleeps until a vt is activated, or the task is interrupted. Returns
01110  * 0 if activation, -EINTR if interrupted.
01111  */
01112 int vt_waitactive(int vt)
01113 {
01114         int retval;
01115         struct wait_queue wait = { current, NULL };
01116 
01117         add_wait_queue(&vt_activate_queue, &wait);
01118         for (;;) {
01119                 current->state = TASK_INTERRUPTIBLE;
01120                 retval = 0;
01121                 if (vt == fg_console)
01122                         break;
01123                 retval = -EINTR;
01124                 if (signal_pending(current))
01125                         break;
01126                 schedule();
01127         }
01128         remove_wait_queue(&vt_activate_queue, &wait);
01129         current->state = TASK_RUNNING;
01130         return retval;
01131 }
01132 
01133 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
01134 
01135 void reset_vc(unsigned int new_console)
01136 {
01137         vt_cons[new_console]->vc_mode = KD_TEXT;
01138         kbd_table[new_console].kbdmode = VC_XLATE;
01139         vt_cons[new_console]->vt_mode.mode = VT_AUTO;
01140         vt_cons[new_console]->vt_mode.waitv = 0;
01141         vt_cons[new_console]->vt_mode.relsig = 0;
01142         vt_cons[new_console]->vt_mode.acqsig = 0;
01143         vt_cons[new_console]->vt_mode.frsig = 0;
01144         vt_cons[new_console]->vt_pid = -1;
01145         vt_cons[new_console]->vt_newvt = -1;
01146         reset_palette (new_console) ;
01147 }
01148 
01149 /*
01150  * Performs the back end of a vt switch
01151  */
01152 void complete_change_console(unsigned int new_console)
01153 {
01154         unsigned char old_vc_mode;
01155 
01156         last_console = fg_console;
01157 
01158         /*
01159          * If we're switching, we could be going from KD_GRAPHICS to
01160          * KD_TEXT mode or vice versa, which means we need to blank or
01161          * unblank the screen later.
01162          */
01163         old_vc_mode = vt_cons[fg_console]->vc_mode;
01164         switch_screen(new_console);
01165 
01166         /*
01167          * If this new console is under process control, send it a signal
01168          * telling it that it has acquired. Also check if it has died and
01169          * clean up (similar to logic employed in change_console())
01170          */
01171         if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
01172         {
01173                 /*
01174                  * Send the signal as privileged - kill_proc() will
01175                  * tell us if the process has gone or something else
01176                  * is awry
01177                  */
01178                 if (kill_proc(vt_cons[new_console]->vt_pid,
01179                               vt_cons[new_console]->vt_mode.acqsig,
01180                               1) != 0)
01181                 {
01182                 /*
01183                  * The controlling process has died, so we revert back to
01184                  * normal operation. In this case, we'll also change back
01185                  * to KD_TEXT mode. I'm not sure if this is strictly correct
01186                  * but it saves the agony when the X server dies and the screen
01187                  * remains blanked due to KD_GRAPHICS! It would be nice to do
01188                  * this outside of VT_PROCESS but there is no single process
01189                  * to account for and tracking tty count may be undesirable.
01190                  */
01191                         reset_vc(new_console);
01192                 }
01193         }
01194 
01195         /*
01196          * We do this here because the controlling process above may have
01197          * gone, and so there is now a new vc_mode
01198          */
01199         if (old_vc_mode != vt_cons[new_console]->vc_mode)
01200         {
01201                 if (vt_cons[new_console]->vc_mode == KD_TEXT)
01202                         unblank_screen();
01203                 else
01204                         do_blank_screen(1);
01205         }
01206 
01207         /*
01208          * Wake anyone waiting for their VT to activate
01209          */
01210         vt_wake_waitactive();
01211         return;
01212 }
01213 
01214 /*
01215  * Performs the front-end of a vt switch
01216  */
01217 void change_console(unsigned int new_console)
01218 {
01219         if ((new_console == fg_console) || (vt_dont_switch))
01220                 return;
01221         if (!vc_cons_allocated(new_console))
01222                 return;
01223 
01224         /*
01225          * If this vt is in process mode, then we need to handshake with
01226          * that process before switching. Essentially, we store where that
01227          * vt wants to switch to and wait for it to tell us when it's done
01228          * (via VT_RELDISP ioctl).
01229          *
01230          * We also check to see if the controlling process still exists.
01231          * If it doesn't, we reset this vt to auto mode and continue.
01232          * This is a cheap way to track process control. The worst thing
01233          * that can happen is: we send a signal to a process, it dies, and
01234          * the switch gets "lost" waiting for a response; hopefully, the
01235          * user will try again, we'll detect the process is gone (unless
01236          * the user waits just the right amount of time :-) and revert the
01237          * vt to auto control.
01238          */
01239         if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
01240         {
01241                 /*
01242                  * Send the signal as privileged - kill_proc() will
01243                  * tell us if the process has gone or something else
01244                  * is awry
01245                  */
01246                 if (kill_proc(vt_cons[fg_console]->vt_pid,
01247                               vt_cons[fg_console]->vt_mode.relsig,
01248                               1) == 0)
01249                 {
01250                         /*
01251                          * It worked. Mark the vt to switch to and
01252                          * return. The process needs to send us a
01253                          * VT_RELDISP ioctl to complete the switch.
01254                          */
01255                         vt_cons[fg_console]->vt_newvt = new_console;
01256                         return;
01257                 }
01258 
01259                 /*
01260                  * The controlling process has died, so we revert back to
01261                  * normal operation. In this case, we'll also change back
01262                  * to KD_TEXT mode. I'm not sure if this is strictly correct
01263                  * but it saves the agony when the X server dies and the screen
01264                  * remains blanked due to KD_GRAPHICS! It would be nice to do
01265                  * this outside of VT_PROCESS but there is no single process
01266                  * to account for and tracking tty count may be undesirable.
01267                  */
01268                 reset_vc(fg_console);
01269 
01270                 /*
01271                  * Fall through to normal (VT_AUTO) handling of the switch...
01272                  */
01273         }
01274 
01275         /*
01276          * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
01277          */
01278         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
01279                 return;
01280 
01281         complete_change_console(new_console);
01282 }
01283