root/drivers/char/keyboard.c

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

DEFINITIONS

This source file includes following definitions.
  1. kb_wait
  2. send_cmd
  3. to_utf8
  4. keyboard_interrupt
  5. put_queue
  6. puts_queue
  7. applkey
  8. enter
  9. caps_toggle
  10. caps_on
  11. show_ptregs
  12. hold
  13. num
  14. lastcons
  15. decr_console
  16. incr_console
  17. send_intr
  18. scroll_forw
  19. scroll_back
  20. boot_it
  21. compose
  22. SAK
  23. do_ignore
  24. do_spec
  25. do_lowercase
  26. do_self
  27. do_dead
  28. handle_diacr
  29. do_cons
  30. do_fn
  31. do_pad
  32. do_cur
  33. do_shift
  34. compute_shiftstate
  35. do_meta
  36. do_ascii
  37. do_lock
  38. send_data
  39. getledstate
  40. setledstate
  41. register_leds
  42. getleds
  43. kbd_bh
  44. hard_reset_now
  45. kbd_init

   1 /*
   2  * linux/drivers/char/keyboard.c
   3  *
   4  * Keyboard driver for Linux v0.99 using Latin-1.
   5  *
   6  * Written for linux by Johan Myreen as a translation from
   7  * the assembly version by Linus (with diacriticals added)
   8  *
   9  * Some additional features added by Christoph Niemann (ChN), March 1993
  10  *
  11  * Loadable keymaps by Risto Kankkunen, May 1993
  12  *
  13  * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
  14  * Added decr/incr_console, dynamic keymaps, Unicode support,
  15  * dynamic function/string keys, led setting,  Sept 1994
  16  * 
  17  */
  18 
  19 #define KEYBOARD_IRQ 1
  20 
  21 #include <linux/sched.h>
  22 #include <linux/interrupt.h>
  23 #include <linux/tty.h>
  24 #include <linux/tty_flip.h>
  25 #include <linux/mm.h>
  26 #include <linux/ptrace.h>
  27 #include <linux/config.h>
  28 #include <linux/signal.h>
  29 #include <linux/string.h>
  30 
  31 #include <asm/bitops.h>
  32 
  33 #include "kbd_kern.h"
  34 #include "diacr.h"
  35 #include "vt_kern.h"
  36 
  37 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  38 
  39 #define KBD_REPORT_ERR
  40 #define KBD_REPORT_UNKN
  41 /* #define KBD_IS_FOCUS_9000 */
  42 
  43 #ifndef KBD_DEFMODE
  44 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
  45 #endif
  46 
  47 #ifndef KBD_DEFLEDS
  48 /*
  49  * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  50  * is on. This seems a good reason to start with NumLock off.
  51  */
  52 #define KBD_DEFLEDS 0
  53 #endif
  54 
  55 #ifndef KBD_DEFLOCK
  56 #define KBD_DEFLOCK 0
  57 #endif
  58 
  59 /*
  60  * The default IO slowdown is doing 'inb()'s from 0x61, which should be
  61  * safe. But as that is the keyboard controller chip address, we do our
  62  * slowdowns here by doing short jumps: the keyboard controller should
  63  * be able to keep up
  64  */
  65 #define REALLY_SLOW_IO
  66 #define SLOW_IO_BY_JUMPING
  67 #include <asm/io.h>
  68 #include <asm/system.h>
  69 
  70 extern void poke_blanked_console(void);
  71 extern void ctrl_alt_del(void);
  72 extern void reset_vc(unsigned int new_console);
  73 extern void change_console(unsigned int new_console);
  74 extern void scrollback(int);
  75 extern void scrollfront(int);
  76 extern int vc_cons_allocated(unsigned int);
  77 
  78 #define fake_keyboard_interrupt() \
  79 __asm__ __volatile__("int $0x21")
  80 
  81 unsigned char kbd_read_mask = 0x01;     /* modified by psaux.c */
  82 
  83 /*
  84  * global state includes the following, and various static variables
  85  * in this module: prev_scancode, shift_state, diacr, npadch,
  86  *   dead_key_next, last_console
  87  */
  88 
  89 /* shift state counters.. */
  90 static unsigned char k_down[NR_SHIFT] = {0, };
  91 /* keyboard key bitmap */
  92 static unsigned long key_down[8] = { 0, };
  93 
  94 static int want_console = -1;
  95 static int last_console = 0;            /* last used VC */
  96 static int dead_key_next = 0;
  97 /* 
  98  * In order to retrieve the shift_state (for the mouse server), either
  99  * the variable must be global, or a new procedure must be created to 
 100  * return the value. I chose the former way.
 101  */
 102 /*static*/ int shift_state = 0;
 103 static int npadch = -1;                 /* -1 or number assembled on pad */
 104 static unsigned char diacr = 0;
 105 static char rep = 0;                    /* flag telling character repeat */
 106 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 107 static struct tty_struct **ttytab;
 108 static struct kbd_struct * kbd = kbd_table;
 109 static struct tty_struct * tty = NULL;
 110 
 111 /* used only by send_data - set by keyboard_interrupt */
 112 static volatile unsigned char reply_expected = 0;
 113 static volatile unsigned char acknowledge = 0;
 114 static volatile unsigned char resend = 0;
 115 
 116 typedef void (*k_hand)(unsigned char value, char up_flag);
 117 typedef void (k_handfn)(unsigned char value, char up_flag);
 118 
 119 static k_handfn
 120         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 121         do_meta, do_ascii, do_lock, do_lowercase, do_ignore;
 122 
 123 static k_hand key_handler[16] = {
 124         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 125         do_meta, do_ascii, do_lock, do_lowercase,
 126         do_ignore, do_ignore, do_ignore, do_ignore
 127 };
 128 
 129 typedef void (*void_fnp)(void);
 130 typedef void (void_fn)(void);
 131 
 132 static void_fn enter, show_ptregs, send_intr, lastcons, caps_toggle,
 133         num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
 134         SAK, decr_console, incr_console;
 135 
 136 static void_fnp spec_fn_table[] = {
 137         NULL,           enter,          show_ptregs,    show_mem,
 138         show_state,     send_intr,      lastcons,       caps_toggle,
 139         num,            hold,           scroll_forw,    scroll_back,
 140         boot_it,        caps_on,        compose,        SAK,
 141         decr_console,   incr_console
 142 };
 143 
 144 /* maximum values each key_handler can handle */
 145 const int max_vals[] = {
 146         255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
 147         NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
 148         255, NR_ASCII - 1, NR_LOCK - 1, 255
 149 };
 150 
 151 const int NR_TYPES = SIZE(max_vals);
 152 
 153 static void put_queue(int);
 154 static unsigned char handle_diacr(unsigned char);
 155 
 156 /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
 157 static struct pt_regs * pt_regs;
 158 
 159 static inline void kb_wait(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int i;
 162 
 163         for (i=0; i<0x10000; i++)
 164                 if ((inb_p(0x64) & 0x02) == 0)
 165                         break;
 166 }
 167 
 168 static inline void send_cmd(unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170         kb_wait();
 171         outb(c,0x64);
 172 }
 173 
 174 /*
 175  * Many other routines do put_queue, but I think either
 176  * they produce ASCII, or they produce some user-assigned
 177  * string, and in both cases we might assume that it is
 178  * in utf-8 already.
 179  */
 180 void to_utf8(ushort c) {
     /* [previous][next][first][last][top][bottom][index][help] */
 181     if (c < 0x80)
 182         put_queue(c);                   /*  0*******  */
 183     else if (c < 0x800) {
 184         put_queue(0xc0 | (c >> 6));     /*  110***** 10******  */
 185         put_queue(0x80 | (c & 0x3f));
 186     } else {
 187         put_queue(0xe0 | (c >> 12));    /*  1110**** 10****** 10******  */
 188         put_queue(0x80 | ((c >> 6) & 0x3f));
 189         put_queue(0x80 | (c & 0x3f));
 190     }
 191     /* uft-8 is defined for words of up to 36 bits,
 192        but we need only 16 bits here */
 193 }
 194 
 195 /*
 196  * Translation of escaped scancodes to keysyms.
 197  * This should be user-settable.
 198  */
 199 #define E0_BASE 96
 200 
 201 #define E0_KPENTER (E0_BASE+0)
 202 #define E0_RCTRL   (E0_BASE+1)
 203 #define E0_KPSLASH (E0_BASE+2)
 204 #define E0_PRSCR   (E0_BASE+3)
 205 #define E0_RALT    (E0_BASE+4)
 206 #define E0_BREAK   (E0_BASE+5)  /* (control-pause) */
 207 #define E0_HOME    (E0_BASE+6)
 208 #define E0_UP      (E0_BASE+7)
 209 #define E0_PGUP    (E0_BASE+8)
 210 #define E0_LEFT    (E0_BASE+9)
 211 #define E0_RIGHT   (E0_BASE+10)
 212 #define E0_END     (E0_BASE+11)
 213 #define E0_DOWN    (E0_BASE+12)
 214 #define E0_PGDN    (E0_BASE+13)
 215 #define E0_INS     (E0_BASE+14)
 216 #define E0_DEL     (E0_BASE+15)
 217 /* BTC */
 218 #define E0_MACRO   (E0_BASE+16)
 219 /* LK450 */
 220 #define E0_F13     (E0_BASE+17)
 221 #define E0_F14     (E0_BASE+18)
 222 #define E0_HELP    (E0_BASE+19)
 223 #define E0_DO      (E0_BASE+20)
 224 #define E0_F17     (E0_BASE+21)
 225 #define E0_KPMINPLUS (E0_BASE+22)
 226 
 227 #define E1_PAUSE   (E0_BASE+23)                       /* 119 */
 228 
 229 static unsigned char e0_keys[128] = {
 230   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x00-0x07 */
 231   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x08-0x0f */
 232   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x10-0x17 */
 233   0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,             /* 0x18-0x1f */
 234   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x20-0x27 */
 235   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x28-0x2f */
 236   0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,             /* 0x30-0x37 */
 237   E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,       /* 0x38-0x3f */
 238   E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,       /* 0x40-0x47 */
 239   E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
 240   E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,       /* 0x50-0x57 */
 241   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x58-0x5f */
 242   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x60-0x67 */
 243   0, 0, 0, 0, 0, 0, 0, E0_MACRO,                      /* 0x68-0x6f */
 244   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x70-0x77 */
 245   0, 0, 0, 0, 0, 0, 0, 0                              /* 0x78-0x7f */
 246 };
 247 
 248 /* kludge to stay below 128 - next time someone comes with a strange
 249    keyboard, key codes will have to become 2 (or 4) bytes. */
 250 /* Owners of a FOCUS 9000 can assign F1,F2-F8,F9-F12 to 85,89-95,120-123 */
 251 /* Owners of a certain Japanese keyboard can use 89 and 124 */
 252 /* Owners of a certain Brazilian keyboard can use 89 and 121 */
 253 /* Note: MEDIUMRAW mode will change, and all keycodes above 89 will change;
 254    this is only a temporary solution */
 255 
 256 #define SC_LIM 89
 257 
 258 #define FOCUS_PF1 85           /* actual code! */
 259 #define FOCUS_PF2 89
 260 #define FOCUS_PF3 90
 261 #define FOCUS_PF4 91
 262 #define FOCUS_PF5 92
 263 #define FOCUS_PF6 93
 264 #define FOCUS_PF7 94
 265 #define FOCUS_PF8 95
 266 #define FOCUS_PF9 (E1_PAUSE + 1)
 267 #define FOCUS_PF10 (E1_PAUSE + 2)
 268 #define FOCUS_PF11 (E1_PAUSE + 3)
 269 #define FOCUS_PF12 (E1_PAUSE + 4)                    /* 123 */
 270 #define JAP_86     (E1_PAUSE + 5)                    /* 124 */
 271 
 272 static unsigned char high_keys[128 - SC_LIM] = {
 273   0, 0, 0, 0, 0, 0, 0,                               /* 0x59-0x5f */
 274   0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
 275   0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
 276   0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
 277   FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
 278   FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
 279 };
 280 
 281 static void keyboard_interrupt(int int_pt_regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283         unsigned char scancode, keycode;
 284         static unsigned int prev_scancode = 0;   /* remember E0, E1 */
 285         char up_flag;                            /* 0 or 0200 */
 286         char raw_mode;
 287 
 288         pt_regs = (struct pt_regs *) int_pt_regs;
 289         send_cmd(0xAD);         /* disable keyboard */
 290         kb_wait();
 291         if ((inb_p(0x64) & kbd_read_mask) != 0x01)
 292                 goto end_kbd_intr;
 293         scancode = inb(0x60);
 294         mark_bh(KEYBOARD_BH);
 295         if (reply_expected) {
 296           /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
 297           /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
 298                 reply_expected = 0;
 299                 if (scancode == 0xfa) {
 300                         acknowledge = 1;
 301                         goto end_kbd_intr;
 302                 } else if (scancode == 0xfe) {
 303                         resend = 1;
 304                         goto end_kbd_intr;
 305                 }
 306                 /* strange ... */
 307                 reply_expected = 1;
 308 #if 0
 309                 printk("keyboard reply expected - got %02x\n", scancode);
 310 #endif
 311         }
 312         if (scancode == 0) {
 313 #ifdef KBD_REPORT_ERR
 314                 printk("keyboard buffer overflow\n");
 315 #endif
 316                 prev_scancode = 0;
 317                 goto end_kbd_intr;
 318         }
 319         if (scancode == 0xff) {
 320                 /* the calculator keys on a FOCUS 9000 generate 0xff */
 321 #ifndef KBD_IS_FOCUS_9000
 322 #ifdef KBD_REPORT_ERR
 323                 printk("keyboard error\n");
 324 #endif
 325 #endif
 326                 prev_scancode = 0;
 327                 goto end_kbd_intr;
 328         }
 329 
 330         tty = ttytab[fg_console];
 331         kbd = kbd_table + fg_console;
 332         if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
 333                 put_queue(scancode);
 334                 /* we do not return yet, because we want to maintain
 335                    the key_down array, so that we have the correct
 336                    values when finishing RAW mode or when changing VT's */
 337         }
 338         if (scancode == 0xe0 || scancode == 0xe1) {
 339                 prev_scancode = scancode;
 340                 goto end_kbd_intr;
 341         }
 342 
 343         /*
 344          *  Convert scancode to keycode, using prev_scancode.
 345          */
 346         up_flag = (scancode & 0200);
 347         scancode &= 0x7f;
 348 
 349         if (prev_scancode) {
 350           /*
 351            * usually it will be 0xe0, but a Pause key generates
 352            * e1 1d 45 e1 9d c5 when pressed, and nothing when released
 353            */
 354           if (prev_scancode != 0xe0) {
 355               if (prev_scancode == 0xe1 && scancode == 0x1d) {
 356                   prev_scancode = 0x100;
 357                   goto end_kbd_intr;
 358               } else if (prev_scancode == 0x100 && scancode == 0x45) {
 359                   keycode = E1_PAUSE;
 360                   prev_scancode = 0;
 361               } else {
 362 #ifdef KBD_REPORT_UNKN
 363                   printk("keyboard: unknown e1 escape sequence\n");
 364 #endif
 365                   prev_scancode = 0;
 366                   goto end_kbd_intr;
 367               }
 368           } else {
 369               prev_scancode = 0;
 370               /*
 371                *  The keyboard maintains its own internal caps lock and
 372                *  num lock statuses. In caps lock mode E0 AA precedes make
 373                *  code and E0 2A follows break code. In num lock mode,
 374                *  E0 2A precedes make code and E0 AA follows break code.
 375                *  We do our own book-keeping, so we will just ignore these.
 376                */
 377               /*
 378                *  For my keyboard there is no caps lock mode, but there are
 379                *  both Shift-L and Shift-R modes. The former mode generates
 380                *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
 381                *  So, we should also ignore the latter. - aeb@cwi.nl
 382                */
 383               if (scancode == 0x2a || scancode == 0x36)
 384                 goto end_kbd_intr;
 385 
 386               if (e0_keys[scancode])
 387                 keycode = e0_keys[scancode];
 388               else {
 389 #ifdef KBD_REPORT_UNKN
 390                   if (!raw_mode)
 391                     printk("keyboard: unknown scancode e0 %02x\n", scancode);
 392 #endif
 393                   goto end_kbd_intr;
 394               }
 395           }
 396         } else if (scancode >= SC_LIM) {
 397             /* This happens with the FOCUS 9000 keyboard
 398                Its keys PF1..PF12 are reported to generate
 399                55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
 400                Moreover, unless repeated, they do not generate
 401                key-down events, so we have to zero up_flag below */
 402             /* Also, Japanese 86/106 keyboards are reported to
 403                generate 0x73 and 0x7d for \ - and \ | respectively. */
 404             /* Also, some Brazilian keyboard is reported to produce
 405                0x73 and 0x7e for \ ? and KP-dot, respectively. */
 406 
 407           keycode = high_keys[scancode - SC_LIM];
 408 
 409           if (!keycode) {
 410               if (!raw_mode) {
 411 #ifdef KBD_REPORT_UNKN
 412                   printk("keyboard: unrecognized scancode (%02x) - ignored\n"
 413                          , scancode);
 414 #endif
 415               }
 416               goto end_kbd_intr;
 417           }
 418         } else
 419           keycode = scancode;
 420 
 421         /*
 422          * At this point the variable `keycode' contains the keycode.
 423          * Note: the keycode must not be 0.
 424          * We keep track of the up/down status of the key, and
 425          * return the keycode if in MEDIUMRAW mode.
 426          */
 427 
 428         if (up_flag) {
 429                 rep = 0;
 430                 if(!clear_bit(keycode, key_down)) {
 431                     /* unexpected, but this can happen:
 432                        maybe this was a key release for a FOCUS 9000
 433                        PF key; if we want to see it, we have to clear
 434                        up_flag */
 435                     if (keycode >= SC_LIM || keycode == 85)
 436                       up_flag = 0;
 437                 }
 438         } else
 439                 rep = set_bit(keycode, key_down);
 440 
 441         if (raw_mode)
 442                 goto end_kbd_intr;
 443 
 444         if (kbd->kbdmode == VC_MEDIUMRAW) {
 445                 /* soon keycodes will require more than one byte */
 446                 put_queue(keycode + up_flag);
 447                 goto end_kbd_intr;
 448         }
 449 
 450         /*
 451          * Small change in philosophy: earlier we defined repetition by
 452          *       rep = keycode == prev_keycode;
 453          *       prev_keycode = keycode;
 454          * but now by the fact that the depressed key was down already.
 455          * Does this ever make a difference? Yes.
 456          */
 457 
 458         /*
 459          *  Repeat a key only if the input buffers are empty or the
 460          *  characters get echoed locally. This makes key repeat usable
 461          *  with slow applications and under heavy loads.
 462          */
 463         if (!rep ||
 464             (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 465              (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
 466                 u_short keysym;
 467                 u_char type;
 468 
 469                 /* the XOR below used to be an OR */
 470                 int shift_final = shift_state ^ kbd->lockstate;
 471                 ushort *key_map = key_maps[shift_final];
 472 
 473                 if (key_map != NULL) {
 474                         keysym = key_map[keycode];
 475                         type = KTYP(keysym);
 476 
 477                         if (type >= 0xf0) {
 478                             type -= 0xf0;
 479                             if (type == KT_LETTER) {
 480                                 type = KT_LATIN;
 481                                 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
 482                                     key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
 483                                     if (key_map)
 484                                       keysym = key_map[keycode];
 485                                 }
 486                             }
 487                             (*key_handler[type])(keysym & 0xff, up_flag);
 488                         } else {
 489                             /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
 490                             if (!up_flag)
 491                               to_utf8(keysym);
 492                         }
 493                 } else {
 494                         /* maybe beep? */
 495                         /* we have at least to update shift_state */
 496 #if 0                   /* how? two almost equivalent choices follow */
 497                         compute_shiftstate();
 498 #else
 499                         keysym = U(plain_map[keycode]);
 500                         type = KTYP(keysym);
 501                         if (type == KT_SHIFT)
 502                           (*key_handler[type])(keysym & 0xff, up_flag);
 503 #endif
 504                 }
 505         }
 506 
 507 end_kbd_intr:
 508         send_cmd(0xAE);         /* enable keyboard */
 509 }
 510 
 511 static void put_queue(int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         wake_up(&keypress_wait);
 514         if (tty) {
 515                 tty_insert_flip_char(tty, ch, 0);
 516                 tty_schedule_flip(tty);
 517         }
 518 }
 519 
 520 static void puts_queue(char *cp)
     /* [previous][next][first][last][top][bottom][index][help] */
 521 {
 522         wake_up(&keypress_wait);
 523         if (!tty)
 524                 return;
 525 
 526         while (*cp) {
 527                 tty_insert_flip_char(tty, *cp, 0);
 528                 cp++;
 529         }
 530         tty_schedule_flip(tty);
 531 }
 532 
 533 static void applkey(int key, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535         static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
 536 
 537         buf[1] = (mode ? 'O' : '[');
 538         buf[2] = key;
 539         puts_queue(buf);
 540 }
 541 
 542 static void enter(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 543 {
 544         put_queue(13);
 545         if (vc_kbd_mode(kbd,VC_CRLF))
 546                 put_queue(10);
 547 }
 548 
 549 static void caps_toggle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 550 {
 551         if (rep)
 552                 return;
 553         chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 554 }
 555 
 556 static void caps_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 557 {
 558         if (rep)
 559                 return;
 560         set_vc_kbd_led(kbd, VC_CAPSLOCK);
 561 }
 562 
 563 static void show_ptregs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 564 {
 565         if (!pt_regs)
 566                 return;
 567         printk("\n");
 568         printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
 569         if (pt_regs->cs & 3)
 570                 printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
 571         printk(" EFLAGS: %08lx\n",pt_regs->eflags);
 572         printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
 573                 pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
 574         printk("ESI: %08lx EDI: %08lx EBP: %08lx",
 575                 pt_regs->esi, pt_regs->edi, pt_regs->ebp);
 576         printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
 577                 0xffff & pt_regs->ds,0xffff & pt_regs->es,
 578                 0xffff & pt_regs->fs,0xffff & pt_regs->gs);
 579 }
 580 
 581 static void hold(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 582 {
 583         if (rep || !tty)
 584                 return;
 585 
 586         /*
 587          * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 588          * these routines are also activated by ^S/^Q.
 589          * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 590          */
 591         if (tty->stopped)
 592                 start_tty(tty);
 593         else
 594                 stop_tty(tty);
 595 }
 596 
 597 static void num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 598 {
 599         if (vc_kbd_mode(kbd,VC_APPLIC)) {
 600                 applkey('P', 1);
 601                 return;
 602         }
 603         if (!rep)       /* no autorepeat for numlock, ChN */
 604                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 605 }
 606 
 607 static void lastcons(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609         /* switch to the last used console, ChN */
 610         want_console = last_console;
 611 }
 612 
 613 static void decr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 614 {
 615         int i;
 616  
 617         for (i = fg_console-1; i != fg_console; i--) {
 618                 if (i == -1)
 619                         i = MAX_NR_CONSOLES-1;
 620                 if (vc_cons_allocated(i))
 621                         break;
 622         }
 623         want_console = i;
 624 }
 625 
 626 static void incr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 627 {
 628         int i;
 629 
 630         for (i = fg_console+1; i != fg_console; i++) {
 631                 if (i == MAX_NR_CONSOLES)
 632                         i = 0;
 633                 if (vc_cons_allocated(i))
 634                         break;
 635         }
 636         want_console = i;
 637 }
 638 
 639 static void send_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 640 {
 641         if (!tty || (tty->termios && I_IGNBRK(tty)))
 642                 return;
 643         tty_insert_flip_char(tty, 0, TTY_BREAK);
 644 }
 645 
 646 static void scroll_forw(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 647 {
 648         scrollfront(0);
 649 }
 650 
 651 static void scroll_back(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653         scrollback(0);
 654 }
 655 
 656 static void boot_it(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 657 {
 658         ctrl_alt_del();
 659 }
 660 
 661 static void compose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 662 {
 663         dead_key_next = 1;
 664 }
 665 
 666 static void SAK(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 667 {
 668         do_SAK(tty);
 669 #if 0
 670         /*
 671          * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 672          * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 673          * handling.
 674          * 
 675          * We should do this some day --- the whole point of a secure
 676          * attention key is that it should be guaranteed to always
 677          * work.
 678          */
 679         reset_vc(fg_console);
 680         unblank_screen();       /* not in interrupt routine? */
 681 #endif
 682 }
 683 
 684 static void do_ignore(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 685 {
 686 }
 687 
 688 static void do_spec(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 689 {
 690         if (up_flag)
 691                 return;
 692         if (value >= SIZE(spec_fn_table))
 693                 return;
 694         if (!spec_fn_table[value])
 695                 return;
 696         spec_fn_table[value]();
 697 }
 698 
 699 static void do_lowercase(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 700 {
 701         printk("keyboard.c: do_lowercase was called - impossible\n");
 702 }
 703 
 704 static void do_self(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 705 {
 706         if (up_flag)
 707                 return;         /* no action, if this is a key release */
 708 
 709         if (diacr)
 710                 value = handle_diacr(value);
 711 
 712         if (dead_key_next) {
 713                 dead_key_next = 0;
 714                 diacr = value;
 715                 return;
 716         }
 717 
 718         put_queue(value);
 719 }
 720 
 721 #define A_GRAVE  '`'
 722 #define A_ACUTE  '\''
 723 #define A_CFLEX  '^'
 724 #define A_TILDE  '~'
 725 #define A_DIAER  '"'
 726 static unsigned char ret_diacr[] =
 727         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 728 
 729 /* If a dead key pressed twice, output a character corresponding to it, */
 730 /* otherwise just remember the dead key.                                */
 731 
 732 static void do_dead(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 733 {
 734         if (up_flag)
 735                 return;
 736 
 737         value = ret_diacr[value];
 738         if (diacr == value) {   /* pressed twice */
 739                 diacr = 0;
 740                 put_queue(value);
 741                 return;
 742         }
 743         diacr = value;
 744 }
 745 
 746 
 747 /* If space is pressed, return the character corresponding the pending  */
 748 /* dead key, otherwise try to combine the two.                          */
 749 
 750 unsigned char handle_diacr(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 751 {
 752         int d = diacr;
 753         int i;
 754 
 755         diacr = 0;
 756         if (ch == ' ')
 757                 return d;
 758 
 759         for (i = 0; i < accent_table_size; i++) {
 760                 if (accent_table[i].diacr == d && accent_table[i].base == ch)
 761                         return accent_table[i].result;
 762         }
 763 
 764         put_queue(d);
 765         return ch;
 766 }
 767 
 768 static void do_cons(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 769 {
 770         if (up_flag)
 771                 return;
 772         want_console = value;
 773 }
 774 
 775 static void do_fn(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 776 {
 777         if (up_flag)
 778                 return;
 779         if (value < SIZE(func_table)) {
 780                 if (func_table[value])
 781                         puts_queue(func_table[value]);
 782         } else
 783                 printk("do_fn called with value=%d\n", value);
 784 }
 785 
 786 static void do_pad(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 787 {
 788         static char *pad_chars = "0123456789+-*/\015,.?";
 789         static char *app_map = "pqrstuvwxylSRQMnn?";
 790 
 791         if (up_flag)
 792                 return;         /* no action, if this is a key release */
 793 
 794         /* kludge... shift forces cursor/number keys */
 795         if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
 796                 applkey(app_map[value], 1);
 797                 return;
 798         }
 799 
 800         if (!vc_kbd_led(kbd,VC_NUMLOCK))
 801                 switch (value) {
 802                         case KVAL(K_PCOMMA):
 803                         case KVAL(K_PDOT):
 804                                 do_fn(KVAL(K_REMOVE), 0);
 805                                 return;
 806                         case KVAL(K_P0):
 807                                 do_fn(KVAL(K_INSERT), 0);
 808                                 return;
 809                         case KVAL(K_P1):
 810                                 do_fn(KVAL(K_SELECT), 0);
 811                                 return;
 812                         case KVAL(K_P2):
 813                                 do_cur(KVAL(K_DOWN), 0);
 814                                 return;
 815                         case KVAL(K_P3):
 816                                 do_fn(KVAL(K_PGDN), 0);
 817                                 return;
 818                         case KVAL(K_P4):
 819                                 do_cur(KVAL(K_LEFT), 0);
 820                                 return;
 821                         case KVAL(K_P6):
 822                                 do_cur(KVAL(K_RIGHT), 0);
 823                                 return;
 824                         case KVAL(K_P7):
 825                                 do_fn(KVAL(K_FIND), 0);
 826                                 return;
 827                         case KVAL(K_P8):
 828                                 do_cur(KVAL(K_UP), 0);
 829                                 return;
 830                         case KVAL(K_P9):
 831                                 do_fn(KVAL(K_PGUP), 0);
 832                                 return;
 833                         case KVAL(K_P5):
 834                                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
 835                                 return;
 836                 }
 837 
 838         put_queue(pad_chars[value]);
 839         if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
 840                 put_queue(10);
 841 }
 842 
 843 static void do_cur(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 844 {
 845         static char *cur_chars = "BDCA";
 846         if (up_flag)
 847                 return;
 848 
 849         applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 850 }
 851 
 852 static void do_shift(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         int old_state = shift_state;
 855 
 856         if (rep)
 857                 return;
 858 
 859         /* Mimic typewriter:
 860            a CapsShift key acts like Shift but undoes CapsLock */
 861         if (value == KVAL(K_CAPSSHIFT)) {
 862                 value = KVAL(K_SHIFT);
 863                 if (!up_flag)
 864                         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
 865         }
 866 
 867         if (up_flag) {
 868                 /* handle the case that two shift or control
 869                    keys are depressed simultaneously */
 870                 if (k_down[value])
 871                         k_down[value]--;
 872         } else
 873                 k_down[value]++;
 874 
 875         if (k_down[value])
 876                 shift_state |= (1 << value);
 877         else
 878                 shift_state &= ~ (1 << value);
 879 
 880         /* kludge */
 881         if (up_flag && shift_state != old_state && npadch != -1) {
 882                 if (kbd->kbdmode == VC_UNICODE)
 883                   to_utf8(npadch & 0xffff);
 884                 else
 885                   put_queue(npadch & 0xff);
 886                 npadch = -1;
 887         }
 888 }
 889 
 890 /* called after returning from RAW mode or when changing consoles -
 891    recompute k_down[] and shift_state from key_down[] */
 892 /* maybe called when keymap is undefined, so that shiftkey release is seen */
 893 void compute_shiftstate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 894 {
 895         int i, j, k, sym, val;
 896 
 897         shift_state = 0;
 898         for(i=0; i < SIZE(k_down); i++)
 899           k_down[i] = 0;
 900 
 901         for(i=0; i < SIZE(key_down); i++)
 902           if(key_down[i]) {     /* skip this word if not a single bit on */
 903             k = (i<<5);
 904             for(j=0; j<32; j++,k++)
 905               if(test_bit(k, key_down)) {
 906                 sym = U(plain_map[k]);
 907                 if(KTYP(sym) == KT_SHIFT) {
 908                   val = KVAL(sym);
 909                   if (val == KVAL(K_CAPSSHIFT))
 910                     val = KVAL(K_SHIFT);
 911                   k_down[val]++;
 912                   shift_state |= (1<<val);
 913                 }
 914               }
 915           }
 916 }
 917 
 918 static void do_meta(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 919 {
 920         if (up_flag)
 921                 return;
 922 
 923         if (vc_kbd_mode(kbd, VC_META)) {
 924                 put_queue('\033');
 925                 put_queue(value);
 926         } else
 927                 put_queue(value | 0x80);
 928 }
 929 
 930 static void do_ascii(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 931 {
 932         int base;
 933 
 934         if (up_flag)
 935                 return;
 936 
 937         if (value < 10)    /* decimal input of code, while Alt depressed */
 938             base = 10;
 939         else {       /* hexadecimal input of code, while AltGr depressed */
 940             value -= 10;
 941             base = 16;
 942         }
 943 
 944         if (npadch == -1)
 945           npadch = value;
 946         else
 947           npadch = npadch * base + value;
 948 }
 949 
 950 static void do_lock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 951 {
 952         if (up_flag || rep)
 953                 return;
 954         chg_vc_kbd_lock(kbd, value);
 955 }
 956 
 957 /*
 958  * send_data sends a character to the keyboard and waits
 959  * for a acknowledge, possibly retrying if asked to. Returns
 960  * the success status.
 961  */
 962 static int send_data(unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 963 {
 964         int retries = 3;
 965         int i;
 966 
 967         do {
 968                 kb_wait();
 969                 acknowledge = 0;
 970                 resend = 0;
 971                 reply_expected = 1;
 972                 outb_p(data, 0x60);
 973                 for(i=0; i<0x20000; i++) {
 974                         inb_p(0x64);            /* just as a delay */
 975                         if (acknowledge)
 976                                 return 1;
 977                         if (resend)
 978                                 break;
 979                 }
 980                 if (!resend)
 981                         return 0;
 982         } while (retries-- > 0);
 983         return 0;
 984 }
 985 
 986 /*
 987  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
 988  * or (ii) whatever pattern of lights people want to show using KDSETLED,
 989  * or (iii) specified bits of specified words in kernel memory.
 990  */
 991 
 992 static unsigned char ledstate = 0xff; /* undefined */
 993 static unsigned char ledioctl;
 994 
 995 unsigned char getledstate(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 996     return ledstate;
 997 }
 998 
 999 void setledstate(struct kbd_struct *kbd, unsigned int led) {
     /* [previous][next][first][last][top][bottom][index][help] */
1000     if (!(led & ~7)) {
1001         ledioctl = led;
1002         kbd->ledmode = LED_SHOW_IOCTL;
1003     } else
1004         kbd->ledmode = LED_SHOW_FLAGS;
1005     set_leds();
1006 }
1007 
1008 static struct ledptr {
1009     unsigned int *addr;
1010     unsigned int mask;
1011     unsigned char valid:1;
1012 } ledptrs[3];
1013 
1014 void register_leds(int console, unsigned int led,
     /* [previous][next][first][last][top][bottom][index][help] */
1015                    unsigned int *addr, unsigned int mask) {
1016     struct kbd_struct *kbd = kbd_table + console;
1017     if (led < 3) {
1018         ledptrs[led].addr = addr;
1019         ledptrs[led].mask = mask;
1020         ledptrs[led].valid = 1;
1021         kbd->ledmode = LED_SHOW_MEM;
1022     } else
1023         kbd->ledmode = LED_SHOW_FLAGS;
1024 }
1025 
1026 static inline unsigned char getleds(void){
     /* [previous][next][first][last][top][bottom][index][help] */
1027     struct kbd_struct *kbd = kbd_table + fg_console;
1028     unsigned char leds;
1029 
1030     if (kbd->ledmode == LED_SHOW_IOCTL)
1031       return ledioctl;
1032     leds = kbd->ledflagstate;
1033     if (kbd->ledmode == LED_SHOW_MEM) {
1034         if (ledptrs[0].valid) {
1035             if (*ledptrs[0].addr & ledptrs[0].mask)
1036               leds |= 1;
1037             else
1038               leds &= ~1;
1039         }
1040         if (ledptrs[1].valid) {
1041             if (*ledptrs[1].addr & ledptrs[1].mask)
1042               leds |= 2;
1043             else
1044               leds &= ~2;
1045         }
1046         if (ledptrs[2].valid) {
1047             if (*ledptrs[2].addr & ledptrs[2].mask)
1048               leds |= 4;
1049             else
1050               leds &= ~4;
1051         }
1052     }
1053     return leds;
1054 }
1055 
1056 /*
1057  * This routine is the bottom half of the keyboard interrupt
1058  * routine, and runs with all interrupts enabled. It does
1059  * console changing, led setting and copy_to_cooked, which can
1060  * take a reasonably long time.
1061  *
1062  * Aside from timing (which isn't really that important for
1063  * keyboard interrupts as they happen often), using the software
1064  * interrupt routines for this thing allows us to easily mask
1065  * this when we don't want any of the above to happen. Not yet
1066  * used, but this allows for easy and efficient race-condition
1067  * prevention later on.
1068  */
1069 static void kbd_bh(void * unused)
     /* [previous][next][first][last][top][bottom][index][help] */
1070 {
1071         unsigned char leds = getleds();
1072 
1073         if (leds != ledstate) {
1074                 ledstate = leds;
1075                 if (!send_data(0xed) || !send_data(leds))
1076                         send_data(0xf4);        /* re-enable kbd if any errors */
1077         }
1078         if (want_console >= 0) {
1079                 if (want_console != fg_console) {
1080                         last_console = fg_console;
1081                         change_console(want_console);
1082                         /* we only changed when the console had already
1083                            been allocated - a new console is not created
1084                            in an interrupt routine */
1085                 }
1086                 want_console = -1;
1087         }
1088         poke_blanked_console();
1089         cli();
1090         if ((inb_p(0x64) & kbd_read_mask) == 0x01)
1091                 fake_keyboard_interrupt();
1092         sti();
1093 }
1094 
1095 long no_idt[2] = {0, 0};
1096 
1097 /*
1098  * This routine reboots the machine by asking the keyboard
1099  * controller to pulse the reset-line low. We try that for a while,
1100  * and if it doesn't work, we do some other stupid things.
1101  */
1102 void hard_reset_now(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1103 {
1104         int i, j;
1105         extern unsigned long pg0[1024];
1106 
1107         sti();
1108 /* rebooting needs to touch the page at absolute addr 0 */
1109         pg0[0] = 7;
1110         *((unsigned short *)0x472) = 0x1234;
1111         for (;;) {
1112                 for (i=0; i<100; i++) {
1113                         kb_wait();
1114                         for(j = 0; j < 100000 ; j++)
1115                                 /* nothing */;
1116                         outb(0xfe,0x64);         /* pulse reset low */
1117                 }
1118                 __asm__("\tlidt _no_idt");
1119         }
1120 }
1121 
1122 unsigned long kbd_init(unsigned long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1123 {
1124         int i;
1125         struct kbd_struct kbd0;
1126         extern struct tty_driver console_driver;
1127 
1128         kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1129         kbd0.ledmode = LED_SHOW_FLAGS;
1130         kbd0.lockstate = KBD_DEFLOCK;
1131         kbd0.modeflags = KBD_DEFMODE;
1132         kbd0.kbdmode = VC_XLATE;
1133  
1134         for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1135                 kbd_table[i] = kbd0;
1136 
1137         ttytab = console_driver.table;
1138 
1139         bh_base[KEYBOARD_BH].routine = kbd_bh;
1140         request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
1141         mark_bh(KEYBOARD_BH);
1142         return kmem_start;
1143 }

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