Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*
0002  *  linux/drivers/char/vt.c
0003  *
0004  *  Copyright (C) 1992 obz under the linux copyright
0005  *
0006  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
0007  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
0008  *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
0009  *  Some code moved for less code duplication - Andi Kleen - Mar 1997
0010  *
0011  *
0012  * by: Rosimildo da Silva --
0013  * Ported to RTEMS to provide the basic interface to the console
0014  * driver. Removed all stuff not required, such as VT_, Fonts, etc.
0015  */
0016 
0017 #include <string.h>  /* memcpy */
0018 #include <sys/types.h>
0019 #include <errno.h>
0020 
0021 #include <bsp.h>
0022 #include <i386_io.h>
0023 #include <rtems.h>
0024 #include <rtems/kd.h>
0025 #include <rtems/keyboard.h>
0026 
0027 /*
0028  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
0029  * experimentation and study of X386 SYSV handling.
0030  *
0031  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
0032  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
0033  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
0034  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
0035  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
0036  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
0037  * to the current console is done by the main ioctl code.
0038  */
0039 
0040 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
0041 
0042 /* Keyboard type: Default is KB_101, but can be set by machine
0043  * specific code.
0044  */
0045 unsigned char keyboard_type = KB_101;
0046 
0047 /*
0048  * Generates sound of some frequency for some number of clock ticks
0049  *
0050  * If freq is 0, will turn off sound, else will turn it on for that time.
0051  * If msec is 0, will return immediately, else will sleep for msec time, then
0052  * turn sound off.
0053  *
0054  * We also return immediately, which is what was implied within the X
0055  * comments - KDMKTONE doesn't put the process to sleep.
0056  */
0057 
0058 #if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
0059     || (defined(__mips__) && !defined(CONFIG_SGI))
0060 
0061 static void
0062 kd_nosound(unsigned long ignored)
0063 {
0064   /* disable counter 2 */
0065   outb(inb_p(0x61)&0xFC, 0x61);
0066   return;
0067 }
0068 
0069 static void
0070 _kd_mksound(unsigned int hz, unsigned int ticks)
0071 {
0072   unsigned int          count = 0;
0073   rtems_interrupt_lock_context lock_context;
0074 
0075   if (hz > 20 && hz < 32767)
0076     count = 1193180 / hz;
0077 
0078   rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
0079 /*  del_timer(&sound_timer);  */
0080   if (count) {
0081     /* enable counter 2 */
0082     outb_p(inb_p(0x61)|3, 0x61);
0083     /* set command for counter 2, 2 byte write */
0084     outb_p(0xB6, TIMER_MODE);
0085     /* select desired HZ */
0086     outb_p(count & 0xff, TIMER_CNTR2);
0087     outb((count >> 8) & 0xff, TIMER_CNTR2);
0088 
0089 /*
0090     if (ticks) {
0091       sound_timer.expires = jiffies+ticks;
0092       add_timer(&sound_timer);
0093     }
0094 */
0095   } else
0096     kd_nosound(0);
0097 
0098   rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
0099   return;
0100 }
0101 
0102 #else
0103 
0104 void
0105 _kd_mksound(unsigned int hz, unsigned int ticks)
0106 {
0107 }
0108 
0109 #endif
0110 
0111 void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
0112 
0113 #define i (tmp.kb_index)
0114 #define s (tmp.kb_table)
0115 #define v (tmp.kb_value)
0116 static inline int
0117 do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
0118 {
0119   struct kbentry tmp;
0120   ushort *key_map, val;
0121 
0122   tmp = *user_kbe;
0123   if (i >= NR_KEYS)  /*  s cannot be >= MAX_NR_KEYMAPS */
0124     return -EINVAL;
0125 
0126   switch (cmd) {
0127   case KDGKBENT:
0128     key_map = key_maps[s];
0129     if (key_map) {
0130         val = U(key_map[i]);
0131         if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
0132       val = K_HOLE;
0133     } else
0134         val = (i ? K_HOLE : K_NOSUCHMAP);
0135     user_kbe->kb_value = val;
0136     return 0;
0137 
0138   case KDSKBENT:
0139     return -EINVAL;
0140   }
0141   return 0;
0142 }
0143 #undef i
0144 #undef s
0145 #undef v
0146 
0147 #define  HZ  100
0148 
0149 static inline int
0150 do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
0151 {
0152   struct kbkeycode tmp;
0153   int kc = 0;
0154 
0155   tmp = *user_kbkc;
0156   switch (cmd) {
0157   case KDGETKEYCODE:
0158     kc = getkeycode(tmp.scancode);
0159     if (kc >= 0)
0160       user_kbkc->keycode = kc;
0161     break;
0162   case KDSETKEYCODE:
0163     if (!perm)
0164       return -EPERM;
0165     kc = setkeycode(tmp.scancode, tmp.keycode);
0166     break;
0167   }
0168   return kc;
0169 }
0170 
0171 static inline int
0172 do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
0173 {
0174   return -EINVAL;
0175 }
0176 
0177 /*
0178  * We handle the console-specific ioctl's here.  We allow the
0179  * capability to modify any console, not just the fg_console.
0180  */
0181 int vt_ioctl( unsigned int cmd, unsigned long arg)
0182 {
0183   int perm;
0184   unsigned int console;
0185   unsigned char ucval;
0186   struct kbd_struct * kbd;
0187 
0188    console = 0;
0189   /*
0190    * To have permissions to do most of the vt ioctls, we either have
0191    * to be the owner of the tty, or super-user.
0192    */
0193   perm = 1;
0194   kbd = kbd_table + console;
0195   switch (cmd) {
0196   case KIOCSOUND:
0197     if (!perm)
0198       return -EPERM;
0199     if (arg)
0200       arg = 1193180 / arg;
0201     kd_mksound(arg, 0);
0202     return 0;
0203 
0204   case KDMKTONE:
0205     if (!perm)
0206       return -EPERM;
0207   {
0208     unsigned int ticks, count;
0209 
0210     /*
0211      * Generate the tone for the appropriate number of ticks.
0212      * If the time is zero, turn off sound ourselves.
0213      */
0214     ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
0215     count = ticks ? (arg & 0xffff) : 0;
0216     if (count)
0217       count = 1193180 / count;
0218     kd_mksound(count, ticks);
0219     return 0;
0220   }
0221 
0222   case KDGKBTYPE:
0223     /*
0224      * this is naive.
0225      */
0226     ucval = keyboard_type;
0227     goto setchar;
0228 
0229   case KDSETMODE:
0230   case KDGETMODE:
0231     return -EINVAL;
0232 
0233   case KDSKBMODE:
0234     if (!perm)
0235       return -EPERM;
0236     switch(arg) {
0237       case K_RAW:
0238       kbd->kbdmode = VC_RAW;
0239       break;
0240       case K_MEDIUMRAW:
0241       kbd->kbdmode = VC_MEDIUMRAW;
0242       break;
0243       case K_XLATE:
0244       kbd->kbdmode = VC_XLATE;
0245       compute_shiftstate();
0246       break;
0247       case K_UNICODE:
0248       kbd->kbdmode = VC_UNICODE;
0249       compute_shiftstate();
0250       break;
0251       default:
0252       return -EINVAL;
0253     }
0254     return 0;
0255 
0256   case KDGKBMODE:
0257     ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
0258          (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
0259          (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
0260          K_XLATE);
0261     goto setint;
0262 
0263   /* this could be folded into KDSKBMODE, but for compatibility
0264      reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
0265   case KDSKBMETA:
0266     switch(arg) {
0267       case K_METABIT:
0268       clr_vc_kbd_mode(kbd, VC_META);
0269       break;
0270       case K_ESCPREFIX:
0271       set_vc_kbd_mode(kbd, VC_META);
0272       break;
0273       default:
0274       return -EINVAL;
0275     }
0276     return 0;
0277 
0278   case KDGKBMETA:
0279     ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
0280   setint:
0281     *(int *)arg = ucval;
0282     return 0;
0283 
0284   case KDGETKEYCODE:
0285   case KDSETKEYCODE:
0286     return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
0287 
0288   case KDGKBENT:
0289   case KDSKBENT:
0290     return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
0291 
0292   case KDGKBDIACR:
0293   {
0294     struct kbdiacrs *a = (struct kbdiacrs *)arg;
0295     a->kb_cnt = accent_table_size;
0296     memcpy( a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr) );
0297     return 0;
0298   }
0299 
0300   case KDSKBDIACR:
0301   {
0302     struct kbdiacrs *a = (struct kbdiacrs *)arg;
0303     unsigned int ct;
0304 
0305     if (!perm)
0306       return -EPERM;
0307     ct = a->kb_cnt;
0308     if (ct >= MAX_DIACR)
0309       return -EINVAL;
0310     accent_table_size = ct;
0311     memcpy(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
0312     return 0;
0313   }
0314 
0315   /* the ioctls below read/set the flags usually shown in the leds */
0316   /* don't use them - they will go away without warning */
0317   case KDGKBLED:
0318     ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
0319     goto setchar;
0320 
0321   case KDSKBLED:
0322     if (!perm)
0323       return -EPERM;
0324     if (arg & ~0x77)
0325       return -EINVAL;
0326     kbd->ledflagstate = (arg & 7);
0327     kbd->default_ledflagstate = ((arg >> 4) & 7);
0328     set_leds();
0329     return 0;
0330 
0331   /* the ioctls below only set the lights, not the functions */
0332   /* for those, see KDGKBLED and KDSKBLED above */
0333   case KDGETLED:
0334     ucval = getledstate();
0335   setchar:
0336     *(char*)arg = ucval;
0337       return 0;
0338 
0339   case KDSETLED:
0340     if (!perm)
0341       return -EPERM;
0342     setledstate(kbd, arg);
0343     return 0;
0344 
0345   default:
0346     return -EINVAL;
0347   }
0348 }