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. setkeycode
  5. getkeycode
  6. keyboard_interrupt
  7. put_queue
  8. puts_queue
  9. applkey
  10. enter
  11. caps_toggle
  12. caps_on
  13. show_ptregs
  14. hold
  15. num
  16. bare_num
  17. lastcons
  18. decr_console
  19. incr_console
  20. send_intr
  21. scroll_forw
  22. scroll_back
  23. boot_it
  24. compose
  25. spawn_console
  26. SAK
  27. do_ignore
  28. do_null
  29. do_spec
  30. do_lowercase
  31. do_self
  32. do_dead
  33. handle_diacr
  34. do_cons
  35. do_fn
  36. do_pad
  37. do_cur
  38. do_shift
  39. compute_shiftstate
  40. do_meta
  41. do_ascii
  42. do_lock
  43. do_slock
  44. send_data
  45. getledstate
  46. setledstate
  47. register_leds
  48. getleds
  49. kbd_bh
  50. kbd_init
  51. kbd_wait_for_input
  52. kbd_write
  53. initialize_kbd

   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  * `Sticky' modifier keys, 951006.
  17  * 
  18  */
  19 
  20 #define KEYBOARD_IRQ 1
  21 
  22 #include <linux/sched.h>
  23 #include <linux/interrupt.h>
  24 #include <linux/tty.h>
  25 #include <linux/tty_flip.h>
  26 #include <linux/mm.h>
  27 #include <linux/ptrace.h>
  28 #include <linux/signal.h>
  29 #include <linux/string.h>
  30 #include <linux/ioport.h>
  31 #include <linux/random.h>
  32 
  33 #include <asm/bitops.h>
  34 
  35 #include "kbd_kern.h"
  36 #include "diacr.h"
  37 #include "vt_kern.h"
  38 
  39 /*
  40  * On non-x86 hardware we do a full keyboard controller
  41  * initialization, in case the bootup software hasn't done
  42  * it. On a x86, the BIOS will already have initialized the
  43  * keyboard.
  44  */
  45 #ifndef __i386__
  46 #define INIT_KBD
  47 static int initialize_kbd(void);
  48 #endif
  49 
  50 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  51 
  52 #define KBD_REPORT_ERR
  53 #define KBD_REPORT_UNKN
  54 /* #define KBD_IS_FOCUS_9000 */
  55 
  56 #ifndef KBD_DEFMODE
  57 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
  58 #endif
  59 
  60 #ifndef KBD_DEFLEDS
  61 /*
  62  * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  63  * is on. This seems a good reason to start with NumLock off.
  64  */
  65 #define KBD_DEFLEDS 0
  66 #endif
  67 
  68 #ifndef KBD_DEFLOCK
  69 #define KBD_DEFLOCK 0
  70 #endif
  71 
  72 /*
  73  * The default IO slowdown is doing 'inb()'s from 0x61, which should be
  74  * safe. But as that is the keyboard controller chip address, we do our
  75  * slowdowns here by doing short jumps: the keyboard controller should
  76  * be able to keep up
  77  */
  78 #define REALLY_SLOW_IO
  79 #define SLOW_IO_BY_JUMPING
  80 #include <asm/io.h>
  81 #include <asm/system.h>
  82 
  83 extern void poke_blanked_console(void);
  84 extern void ctrl_alt_del(void);
  85 extern void reset_vc(unsigned int new_console);
  86 extern void change_console(unsigned int new_console);
  87 extern void scrollback(int);
  88 extern void scrollfront(int);
  89 
  90 unsigned char kbd_read_mask = 0x01;     /* modified by psaux.c */
  91 
  92 /*
  93  * global state includes the following, and various static variables
  94  * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
  95  * (last_console is now a global variable)
  96  */
  97 
  98 /* shift state counters.. */
  99 static unsigned char k_down[NR_SHIFT] = {0, };
 100 /* keyboard key bitmap */
 101 #define BITS_PER_LONG (8*sizeof(unsigned long))
 102 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
 103 
 104 extern int last_console;
 105 static int want_console = -1;
 106 static int dead_key_next = 0;
 107 /* 
 108  * In order to retrieve the shift_state (for the mouse server), either
 109  * the variable must be global, or a new procedure must be created to 
 110  * return the value. I chose the former way.
 111  */
 112 /*static*/ int shift_state = 0;
 113 static int npadch = -1;                 /* -1 or number assembled on pad */
 114 static unsigned char diacr = 0;
 115 static char rep = 0;                    /* flag telling character repeat */
 116 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 117 static struct tty_struct **ttytab;
 118 static struct kbd_struct * kbd = kbd_table;
 119 static struct tty_struct * tty = NULL;
 120 
 121 /* used only by send_data - set by keyboard_interrupt */
 122 static volatile unsigned char reply_expected = 0;
 123 static volatile unsigned char acknowledge = 0;
 124 static volatile unsigned char resend = 0;
 125 /* used by kbd_bh - set by keyboard_interrupt */
 126 static volatile unsigned char do_poke_blanked_console = 0;
 127 
 128 extern void compute_shiftstate(void);
 129 
 130 typedef void (*k_hand)(unsigned char value, char up_flag);
 131 typedef void (k_handfn)(unsigned char value, char up_flag);
 132 
 133 static k_handfn
 134         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 135         do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_ignore;
 136 
 137 static k_hand key_handler[16] = {
 138         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 139         do_meta, do_ascii, do_lock, do_lowercase, do_slock,
 140         do_ignore, do_ignore, do_ignore
 141 };
 142 
 143 typedef void (*void_fnp)(void);
 144 typedef void (void_fn)(void);
 145 
 146 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 147         num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
 148         SAK, decr_console, incr_console, spawn_console, bare_num;
 149 
 150 static void_fnp spec_fn_table[] = {
 151         do_null,        enter,          show_ptregs,    show_mem,
 152         show_state,     send_intr,      lastcons,       caps_toggle,
 153         num,            hold,           scroll_forw,    scroll_back,
 154         boot_it,        caps_on,        compose,        SAK,
 155         decr_console,   incr_console,   spawn_console,  bare_num
 156 };
 157 
 158 /* maximum values each key_handler can handle */
 159 const int max_vals[] = {
 160         255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
 161         NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
 162         255, NR_ASCII - 1, NR_LOCK - 1, 255,
 163         NR_LOCK - 1
 164 };
 165 
 166 const int NR_TYPES = SIZE(max_vals);
 167 
 168 static void put_queue(int);
 169 static unsigned char handle_diacr(unsigned char);
 170 
 171 /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
 172 static struct pt_regs * pt_regs;
 173 
 174 static inline void kb_wait(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176         int i;
 177 
 178         for (i=0; i<0x100000; i++)
 179                 if ((inb_p(0x64) & 0x02) == 0)
 180                         return;
 181         printk("Keyboard timed out\n");
 182 }
 183 
 184 static inline void send_cmd(unsigned char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         kb_wait();
 187         outb(c,0x64);
 188 }
 189 
 190 /*
 191  * Many other routines do put_queue, but I think either
 192  * they produce ASCII, or they produce some user-assigned
 193  * string, and in both cases we might assume that it is
 194  * in utf-8 already.
 195  */
 196 void to_utf8(ushort c) {
     /* [previous][next][first][last][top][bottom][index][help] */
 197     if (c < 0x80)
 198         put_queue(c);                   /*  0*******  */
 199     else if (c < 0x800) {
 200         put_queue(0xc0 | (c >> 6));     /*  110***** 10******  */
 201         put_queue(0x80 | (c & 0x3f));
 202     } else {
 203         put_queue(0xe0 | (c >> 12));    /*  1110**** 10****** 10******  */
 204         put_queue(0x80 | ((c >> 6) & 0x3f));
 205         put_queue(0x80 | (c & 0x3f));
 206     }
 207     /* UTF-8 is defined for words of up to 31 bits,
 208        but we need only 16 bits here */
 209 }
 210 
 211 /*
 212  * Translation of escaped scancodes to keycodes.
 213  * This is now user-settable.
 214  * The keycodes 1-88,96-111,119 are fairly standard, and
 215  * should probably not be changed - changing might confuse X.
 216  * X also interprets scancode 0x5d (KEY_Begin).
 217  *
 218  * For 1-88 keycode equals scancode.
 219  */
 220 
 221 #define E0_KPENTER 96
 222 #define E0_RCTRL   97
 223 #define E0_KPSLASH 98
 224 #define E0_PRSCR   99
 225 #define E0_RALT    100
 226 #define E0_BREAK   101  /* (control-pause) */
 227 #define E0_HOME    102
 228 #define E0_UP      103
 229 #define E0_PGUP    104
 230 #define E0_LEFT    105
 231 #define E0_RIGHT   106
 232 #define E0_END     107
 233 #define E0_DOWN    108
 234 #define E0_PGDN    109
 235 #define E0_INS     110
 236 #define E0_DEL     111
 237 
 238 #define E1_PAUSE   119
 239 
 240 /*
 241  * The keycodes below are randomly located in 89-95,112-118,120-127.
 242  * They could be thrown away (and all occurrences below replaced by 0),
 243  * but that would force many users to use the `setkeycodes' utility, where
 244  * they needed not before. It does not matter that there are duplicates, as
 245  * long as no duplication occurs for any single keyboard.
 246  */
 247 #define SC_LIM 89
 248 
 249 #define FOCUS_PF1 85           /* actual code! */
 250 #define FOCUS_PF2 89
 251 #define FOCUS_PF3 90
 252 #define FOCUS_PF4 91
 253 #define FOCUS_PF5 92
 254 #define FOCUS_PF6 93
 255 #define FOCUS_PF7 94
 256 #define FOCUS_PF8 95
 257 #define FOCUS_PF9 120
 258 #define FOCUS_PF10 121
 259 #define FOCUS_PF11 122
 260 #define FOCUS_PF12 123
 261 
 262 #define JAP_86     124
 263 /* tfj@olivia.ping.dk:
 264  * The four keys are located over the numeric keypad, and are
 265  * labelled A1-A4. It's an rc930 keyboard, from
 266  * Regnecentralen/RC International, Now ICL.
 267  * Scancodes: 59, 5a, 5b, 5c.
 268  */
 269 #define RGN1 124
 270 #define RGN2 125
 271 #define RGN3 126
 272 #define RGN4 127
 273 
 274 static unsigned char high_keys[128 - SC_LIM] = {
 275   RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
 276   0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
 277   0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
 278   0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
 279   FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
 280   FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
 281 };
 282 
 283 /* BTC */
 284 #define E0_MACRO   112
 285 /* LK450 */
 286 #define E0_F13     113
 287 #define E0_F14     114
 288 #define E0_HELP    115
 289 #define E0_DO      116
 290 #define E0_F17     117
 291 #define E0_KPMINPLUS 118
 292 /*
 293  * My OmniKey generates e0 4c for  the "OMNI" key and the
 294  * right alt key does nada. [kkoller@nyx10.cs.du.edu]
 295  */
 296 #define E0_OK   124
 297 /*
 298  * New microsoft keyboard is rumoured to have
 299  * e0 5b (left window button), e0 5c (right window button),
 300  * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
 301  * [or: Windows_L, Windows_R, TaskMan]
 302  */
 303 #define E0_MSLW 125
 304 #define E0_MSRW 126
 305 #define E0_MSTM 127
 306 
 307 static unsigned char e0_keys[128] = {
 308   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x00-0x07 */
 309   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x08-0x0f */
 310   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x10-0x17 */
 311   0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,             /* 0x18-0x1f */
 312   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x20-0x27 */
 313   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x28-0x2f */
 314   0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,             /* 0x30-0x37 */
 315   E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,       /* 0x38-0x3f */
 316   E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,       /* 0x40-0x47 */
 317   E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
 318   E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,       /* 0x50-0x57 */
 319   0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,           /* 0x58-0x5f */
 320   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x60-0x67 */
 321   0, 0, 0, 0, 0, 0, 0, E0_MACRO,                      /* 0x68-0x6f */
 322   0, 0, 0, 0, 0, 0, 0, 0,                             /* 0x70-0x77 */
 323   0, 0, 0, 0, 0, 0, 0, 0                              /* 0x78-0x7f */
 324 };
 325 
 326 int setkeycode(unsigned int scancode, unsigned int keycode)
     /* [previous][next][first][last][top][bottom][index][help] */
 327 {
 328         if (scancode < SC_LIM || scancode > 255 || keycode > 127)
 329           return -EINVAL;
 330         if (scancode < 128)
 331           high_keys[scancode - SC_LIM] = keycode;
 332         else
 333           e0_keys[scancode - 128] = keycode;
 334         return 0;
 335 }
 336 
 337 int getkeycode(unsigned int scancode)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339         return
 340           (scancode < SC_LIM || scancode > 255) ? -EINVAL :
 341           (scancode < 128) ? high_keys[scancode - SC_LIM] :
 342             e0_keys[scancode - 128];
 343 }
 344 
 345 static void keyboard_interrupt(int irq, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 346 {
 347         unsigned char scancode, keycode;
 348         static unsigned int prev_scancode = 0;   /* remember E0, E1 */
 349         char up_flag;                            /* 0 or 0200 */
 350         char raw_mode;
 351 
 352         pt_regs = regs;
 353         send_cmd(0xAD);         /* disable keyboard */
 354         kb_wait();
 355         if ((inb_p(0x64) & kbd_read_mask) != 0x01)
 356                 goto end_kbd_intr;
 357         scancode = inb(0x60);
 358         mark_bh(KEYBOARD_BH);
 359         if (reply_expected) {
 360           /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
 361           /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
 362                 reply_expected = 0;
 363                 if (scancode == 0xfa) {
 364                         acknowledge = 1;
 365                         goto end_kbd_intr;
 366                 } else if (scancode == 0xfe) {
 367                         resend = 1;
 368                         goto end_kbd_intr;
 369                 }
 370                 /* strange ... */
 371                 reply_expected = 1;
 372 #if 0
 373                 printk("keyboard reply expected - got %02x\n", scancode);
 374 #endif
 375         }
 376         if (scancode == 0) {
 377 #ifdef KBD_REPORT_ERR
 378                 printk("keyboard buffer overflow\n");
 379 #endif
 380                 prev_scancode = 0;
 381                 goto end_kbd_intr;
 382         }
 383         do_poke_blanked_console = 1;
 384         add_keyboard_randomness(scancode);
 385 
 386         tty = ttytab[fg_console];
 387         kbd = kbd_table + fg_console;
 388         if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
 389                 put_queue(scancode);
 390                 /* we do not return yet, because we want to maintain
 391                    the key_down array, so that we have the correct
 392                    values when finishing RAW mode or when changing VT's */
 393         }
 394 
 395         if (scancode == 0xff) {
 396                 /* in scancode mode 1, my ESC key generates 0xff */
 397                 /* the calculator keys on a FOCUS 9000 generate 0xff */
 398 #ifndef KBD_IS_FOCUS_9000
 399 #ifdef KBD_REPORT_ERR
 400                 if (!raw_mode)
 401                   printk("keyboard error\n");
 402 #endif
 403 #endif
 404                 prev_scancode = 0;
 405                 goto end_kbd_intr;
 406         }
 407 
 408         if (scancode == 0xe0 || scancode == 0xe1) {
 409                 prev_scancode = scancode;
 410                 goto end_kbd_intr;
 411         }
 412 
 413         /*
 414          *  Convert scancode to keycode, using prev_scancode.
 415          */
 416         up_flag = (scancode & 0200);
 417         scancode &= 0x7f;
 418 
 419         if (prev_scancode) {
 420           /*
 421            * usually it will be 0xe0, but a Pause key generates
 422            * e1 1d 45 e1 9d c5 when pressed, and nothing when released
 423            */
 424           if (prev_scancode != 0xe0) {
 425               if (prev_scancode == 0xe1 && scancode == 0x1d) {
 426                   prev_scancode = 0x100;
 427                   goto end_kbd_intr;
 428               } else if (prev_scancode == 0x100 && scancode == 0x45) {
 429                   keycode = E1_PAUSE;
 430                   prev_scancode = 0;
 431               } else {
 432 #ifdef KBD_REPORT_UNKN
 433                   if (!raw_mode)
 434                     printk("keyboard: unknown e1 escape sequence\n");
 435 #endif
 436                   prev_scancode = 0;
 437                   goto end_kbd_intr;
 438               }
 439           } else {
 440               prev_scancode = 0;
 441               /*
 442                *  The keyboard maintains its own internal caps lock and
 443                *  num lock statuses. In caps lock mode E0 AA precedes make
 444                *  code and E0 2A follows break code. In num lock mode,
 445                *  E0 2A precedes make code and E0 AA follows break code.
 446                *  We do our own book-keeping, so we will just ignore these.
 447                */
 448               /*
 449                *  For my keyboard there is no caps lock mode, but there are
 450                *  both Shift-L and Shift-R modes. The former mode generates
 451                *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
 452                *  So, we should also ignore the latter. - aeb@cwi.nl
 453                */
 454               if (scancode == 0x2a || scancode == 0x36)
 455                 goto end_kbd_intr;
 456 
 457               if (e0_keys[scancode])
 458                 keycode = e0_keys[scancode];
 459               else {
 460 #ifdef KBD_REPORT_UNKN
 461                   if (!raw_mode)
 462                     printk("keyboard: unknown scancode e0 %02x\n", scancode);
 463 #endif
 464                   goto end_kbd_intr;
 465               }
 466           }
 467         } else if (scancode >= SC_LIM) {
 468             /* This happens with the FOCUS 9000 keyboard
 469                Its keys PF1..PF12 are reported to generate
 470                55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
 471                Moreover, unless repeated, they do not generate
 472                key-down events, so we have to zero up_flag below */
 473             /* Also, Japanese 86/106 keyboards are reported to
 474                generate 0x73 and 0x7d for \ - and \ | respectively. */
 475             /* Also, some Brazilian keyboard is reported to produce
 476                0x73 and 0x7e for \ ? and KP-dot, respectively. */
 477 
 478           keycode = high_keys[scancode - SC_LIM];
 479 
 480           if (!keycode) {
 481               if (!raw_mode) {
 482 #ifdef KBD_REPORT_UNKN
 483                   printk("keyboard: unrecognized scancode (%02x) - ignored\n"
 484                          , scancode);
 485 #endif
 486               }
 487               goto end_kbd_intr;
 488           }
 489         } else
 490           keycode = scancode;
 491 
 492         /*
 493          * At this point the variable `keycode' contains the keycode.
 494          * Note: the keycode must not be 0.
 495          * We keep track of the up/down status of the key, and
 496          * return the keycode if in MEDIUMRAW mode.
 497          */
 498 
 499         if (up_flag) {
 500                 rep = 0;
 501                 if(!clear_bit(keycode, key_down)) {
 502                     /* unexpected, but this can happen:
 503                        maybe this was a key release for a FOCUS 9000
 504                        PF key; if we want to see it, we have to clear
 505                        up_flag */
 506                     if (keycode >= SC_LIM || keycode == 85)
 507                       up_flag = 0;
 508                 }
 509         } else
 510                 rep = set_bit(keycode, key_down);
 511 
 512         if (raw_mode)
 513                 goto end_kbd_intr;
 514 
 515         if (kbd->kbdmode == VC_MEDIUMRAW) {
 516                 /* soon keycodes will require more than one byte */
 517                 put_queue(keycode + up_flag);
 518                 goto end_kbd_intr;
 519         }
 520 
 521         /*
 522          * Small change in philosophy: earlier we defined repetition by
 523          *       rep = keycode == prev_keycode;
 524          *       prev_keycode = keycode;
 525          * but now by the fact that the depressed key was down already.
 526          * Does this ever make a difference? Yes.
 527          */
 528 
 529         /*
 530          *  Repeat a key only if the input buffers are empty or the
 531          *  characters get echoed locally. This makes key repeat usable
 532          *  with slow applications and under heavy loads.
 533          */
 534         if (!rep ||
 535             (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 536              (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
 537                 u_short keysym;
 538                 u_char type;
 539 
 540                 /* the XOR below used to be an OR */
 541                 int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
 542                 ushort *key_map = key_maps[shift_final];
 543 
 544                 if (key_map != NULL) {
 545                         keysym = key_map[keycode];
 546                         type = KTYP(keysym);
 547 
 548                         if (type >= 0xf0) {
 549                             type -= 0xf0;
 550                             if (type == KT_LETTER) {
 551                                 type = KT_LATIN;
 552                                 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
 553                                     key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
 554                                     if (key_map)
 555                                       keysym = key_map[keycode];
 556                                 }
 557                             }
 558                             (*key_handler[type])(keysym & 0xff, up_flag);
 559                             if (type != KT_SLOCK)
 560                               kbd->slockstate = 0;
 561                         } else {
 562                             /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
 563                             if (!up_flag)
 564                               to_utf8(keysym);
 565                         }
 566                 } else {
 567                         /* maybe beep? */
 568                         /* we have at least to update shift_state */
 569 #if 1                   /* how? two almost equivalent choices follow */
 570                         compute_shiftstate();
 571 #else
 572                         keysym = U(plain_map[keycode]);
 573                         type = KTYP(keysym);
 574                         if (type == KT_SHIFT)
 575                           (*key_handler[type])(keysym & 0xff, up_flag);
 576 #endif
 577                 }
 578         }
 579 
 580 end_kbd_intr:
 581         send_cmd(0xAE);         /* enable keyboard */
 582 }
 583 
 584 static void put_queue(int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 585 {
 586         wake_up(&keypress_wait);
 587         if (tty) {
 588                 tty_insert_flip_char(tty, ch, 0);
 589                 tty_schedule_flip(tty);
 590         }
 591 }
 592 
 593 static void puts_queue(char *cp)
     /* [previous][next][first][last][top][bottom][index][help] */
 594 {
 595         wake_up(&keypress_wait);
 596         if (!tty)
 597                 return;
 598 
 599         while (*cp) {
 600                 tty_insert_flip_char(tty, *cp, 0);
 601                 cp++;
 602         }
 603         tty_schedule_flip(tty);
 604 }
 605 
 606 static void applkey(int key, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 607 {
 608         static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
 609 
 610         buf[1] = (mode ? 'O' : '[');
 611         buf[2] = key;
 612         puts_queue(buf);
 613 }
 614 
 615 static void enter(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 616 {
 617         put_queue(13);
 618         if (vc_kbd_mode(kbd,VC_CRLF))
 619                 put_queue(10);
 620 }
 621 
 622 static void caps_toggle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 623 {
 624         if (rep)
 625                 return;
 626         chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 627 }
 628 
 629 static void caps_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 630 {
 631         if (rep)
 632                 return;
 633         set_vc_kbd_led(kbd, VC_CAPSLOCK);
 634 }
 635 
 636 static void show_ptregs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 637 {
 638         if (pt_regs)
 639                 show_regs(pt_regs);
 640 }
 641 
 642 static void hold(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 643 {
 644         if (rep || !tty)
 645                 return;
 646 
 647         /*
 648          * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 649          * these routines are also activated by ^S/^Q.
 650          * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 651          */
 652         if (tty->stopped)
 653                 start_tty(tty);
 654         else
 655                 stop_tty(tty);
 656 }
 657 
 658 static void num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 659 {
 660         if (vc_kbd_mode(kbd,VC_APPLIC))
 661                 applkey('P', 1);
 662         else
 663                 bare_num();
 664 }
 665 
 666 /*
 667  * Bind this to Shift-NumLock if you work in application keypad mode
 668  * but want to be able to change the NumLock flag.
 669  * Bind this to NumLock if you prefer that the NumLock key always
 670  * changes the NumLock flag.
 671  */
 672 static void bare_num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 673 {
 674         if (!rep)
 675                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 676 }
 677 
 678 static void lastcons(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680         /* switch to the last used console, ChN */
 681         want_console = last_console;
 682 }
 683 
 684 static void decr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 685 {
 686         int i;
 687  
 688         for (i = fg_console-1; i != fg_console; i--) {
 689                 if (i == -1)
 690                         i = MAX_NR_CONSOLES-1;
 691                 if (vc_cons_allocated(i))
 692                         break;
 693         }
 694         want_console = i;
 695 }
 696 
 697 static void incr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 698 {
 699         int i;
 700 
 701         for (i = fg_console+1; i != fg_console; i++) {
 702                 if (i == MAX_NR_CONSOLES)
 703                         i = 0;
 704                 if (vc_cons_allocated(i))
 705                         break;
 706         }
 707         want_console = i;
 708 }
 709 
 710 static void send_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 711 {
 712         if (!tty)
 713                 return;
 714         tty_insert_flip_char(tty, 0, TTY_BREAK);
 715         tty_schedule_flip(tty);
 716 }
 717 
 718 static void scroll_forw(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 719 {
 720         scrollfront(0);
 721 }
 722 
 723 static void scroll_back(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 724 {
 725         scrollback(0);
 726 }
 727 
 728 static void boot_it(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 729 {
 730         ctrl_alt_del();
 731 }
 732 
 733 static void compose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 734 {
 735         dead_key_next = 1;
 736 }
 737 
 738 int spawnpid, spawnsig;
 739 
 740 static void spawn_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 741 {
 742         if (spawnpid)
 743            if(kill_proc(spawnpid, spawnsig, 1))
 744              spawnpid = 0;
 745 }
 746 
 747 static void SAK(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 748 {
 749         do_SAK(tty);
 750 #if 0
 751         /*
 752          * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 753          * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 754          * handling.
 755          * 
 756          * We should do this some day --- the whole point of a secure
 757          * attention key is that it should be guaranteed to always
 758          * work.
 759          */
 760         reset_vc(fg_console);
 761         do_unblank_screen();    /* not in interrupt routine? */
 762 #endif
 763 }
 764 
 765 static void do_ignore(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767 }
 768 
 769 static void do_null()
     /* [previous][next][first][last][top][bottom][index][help] */
 770 {
 771         compute_shiftstate();
 772 }
 773 
 774 static void do_spec(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 775 {
 776         if (up_flag)
 777                 return;
 778         if (value >= SIZE(spec_fn_table))
 779                 return;
 780         spec_fn_table[value]();
 781 }
 782 
 783 static void do_lowercase(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 784 {
 785         printk("keyboard.c: do_lowercase was called - impossible\n");
 786 }
 787 
 788 static void do_self(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 789 {
 790         if (up_flag)
 791                 return;         /* no action, if this is a key release */
 792 
 793         if (diacr)
 794                 value = handle_diacr(value);
 795 
 796         if (dead_key_next) {
 797                 dead_key_next = 0;
 798                 diacr = value;
 799                 return;
 800         }
 801 
 802         put_queue(value);
 803 }
 804 
 805 #define A_GRAVE  '`'
 806 #define A_ACUTE  '\''
 807 #define A_CFLEX  '^'
 808 #define A_TILDE  '~'
 809 #define A_DIAER  '"'
 810 static unsigned char ret_diacr[] =
 811         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 812 
 813 /* If a dead key pressed twice, output a character corresponding to it, */
 814 /* otherwise just remember the dead key.                                */
 815 
 816 static void do_dead(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 817 {
 818         if (up_flag)
 819                 return;
 820 
 821         value = ret_diacr[value];
 822         if (diacr == value) {   /* pressed twice */
 823                 diacr = 0;
 824                 put_queue(value);
 825                 return;
 826         }
 827         diacr = value;
 828 }
 829 
 830 
 831 /* If space is pressed, return the character corresponding the pending  */
 832 /* dead key, otherwise try to combine the two.                          */
 833 
 834 unsigned char handle_diacr(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 835 {
 836         int d = diacr;
 837         int i;
 838 
 839         diacr = 0;
 840         if (ch == ' ')
 841                 return d;
 842 
 843         for (i = 0; i < accent_table_size; i++) {
 844                 if (accent_table[i].diacr == d && accent_table[i].base == ch)
 845                         return accent_table[i].result;
 846         }
 847 
 848         put_queue(d);
 849         return ch;
 850 }
 851 
 852 static void do_cons(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         if (up_flag)
 855                 return;
 856         want_console = value;
 857 }
 858 
 859 static void do_fn(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 860 {
 861         if (up_flag)
 862                 return;
 863         if (value < SIZE(func_table)) {
 864                 if (func_table[value])
 865                         puts_queue(func_table[value]);
 866         } else
 867                 printk("do_fn called with value=%d\n", value);
 868 }
 869 
 870 static void do_pad(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 871 {
 872         static const char *pad_chars = "0123456789+-*/\015,.?";
 873         static const char *app_map = "pqrstuvwxylSRQMnn?";
 874 
 875         if (up_flag)
 876                 return;         /* no action, if this is a key release */
 877 
 878         /* kludge... shift forces cursor/number keys */
 879         if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
 880                 applkey(app_map[value], 1);
 881                 return;
 882         }
 883 
 884         if (!vc_kbd_led(kbd,VC_NUMLOCK))
 885                 switch (value) {
 886                         case KVAL(K_PCOMMA):
 887                         case KVAL(K_PDOT):
 888                                 do_fn(KVAL(K_REMOVE), 0);
 889                                 return;
 890                         case KVAL(K_P0):
 891                                 do_fn(KVAL(K_INSERT), 0);
 892                                 return;
 893                         case KVAL(K_P1):
 894                                 do_fn(KVAL(K_SELECT), 0);
 895                                 return;
 896                         case KVAL(K_P2):
 897                                 do_cur(KVAL(K_DOWN), 0);
 898                                 return;
 899                         case KVAL(K_P3):
 900                                 do_fn(KVAL(K_PGDN), 0);
 901                                 return;
 902                         case KVAL(K_P4):
 903                                 do_cur(KVAL(K_LEFT), 0);
 904                                 return;
 905                         case KVAL(K_P6):
 906                                 do_cur(KVAL(K_RIGHT), 0);
 907                                 return;
 908                         case KVAL(K_P7):
 909                                 do_fn(KVAL(K_FIND), 0);
 910                                 return;
 911                         case KVAL(K_P8):
 912                                 do_cur(KVAL(K_UP), 0);
 913                                 return;
 914                         case KVAL(K_P9):
 915                                 do_fn(KVAL(K_PGUP), 0);
 916                                 return;
 917                         case KVAL(K_P5):
 918                                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
 919                                 return;
 920                 }
 921 
 922         put_queue(pad_chars[value]);
 923         if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
 924                 put_queue(10);
 925 }
 926 
 927 static void do_cur(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 928 {
 929         static const char *cur_chars = "BDCA";
 930         if (up_flag)
 931                 return;
 932 
 933         applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 934 }
 935 
 936 static void do_shift(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 937 {
 938         int old_state = shift_state;
 939 
 940         if (rep)
 941                 return;
 942 
 943         /* Mimic typewriter:
 944            a CapsShift key acts like Shift but undoes CapsLock */
 945         if (value == KVAL(K_CAPSSHIFT)) {
 946                 value = KVAL(K_SHIFT);
 947                 if (!up_flag)
 948                         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
 949         }
 950 
 951         if (up_flag) {
 952                 /* handle the case that two shift or control
 953                    keys are depressed simultaneously */
 954                 if (k_down[value])
 955                         k_down[value]--;
 956         } else
 957                 k_down[value]++;
 958 
 959         if (k_down[value])
 960                 shift_state |= (1 << value);
 961         else
 962                 shift_state &= ~ (1 << value);
 963 
 964         /* kludge */
 965         if (up_flag && shift_state != old_state && npadch != -1) {
 966                 if (kbd->kbdmode == VC_UNICODE)
 967                   to_utf8(npadch & 0xffff);
 968                 else
 969                   put_queue(npadch & 0xff);
 970                 npadch = -1;
 971         }
 972 }
 973 
 974 /* called after returning from RAW mode or when changing consoles -
 975    recompute k_down[] and shift_state from key_down[] */
 976 /* maybe called when keymap is undefined, so that shiftkey release is seen */
 977 void compute_shiftstate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 978 {
 979         int i, j, k, sym, val;
 980 
 981         shift_state = 0;
 982         for(i=0; i < SIZE(k_down); i++)
 983           k_down[i] = 0;
 984 
 985         for(i=0; i < SIZE(key_down); i++)
 986           if(key_down[i]) {     /* skip this word if not a single bit on */
 987             k = i*BITS_PER_LONG;
 988             for(j=0; j<BITS_PER_LONG; j++,k++)
 989               if(test_bit(k, key_down)) {
 990                 sym = U(plain_map[k]);
 991                 if(KTYP(sym) == KT_SHIFT) {
 992                   val = KVAL(sym);
 993                   if (val == KVAL(K_CAPSSHIFT))
 994                     val = KVAL(K_SHIFT);
 995                   k_down[val]++;
 996                   shift_state |= (1<<val);
 997                 }
 998               }
 999           }
1000 }
1001 
1002 static void do_meta(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1003 {
1004         if (up_flag)
1005                 return;
1006 
1007         if (vc_kbd_mode(kbd, VC_META)) {
1008                 put_queue('\033');
1009                 put_queue(value);
1010         } else
1011                 put_queue(value | 0x80);
1012 }
1013 
1014 static void do_ascii(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1015 {
1016         int base;
1017 
1018         if (up_flag)
1019                 return;
1020 
1021         if (value < 10)    /* decimal input of code, while Alt depressed */
1022             base = 10;
1023         else {       /* hexadecimal input of code, while AltGr depressed */
1024             value -= 10;
1025             base = 16;
1026         }
1027 
1028         if (npadch == -1)
1029           npadch = value;
1030         else
1031           npadch = npadch * base + value;
1032 }
1033 
1034 static void do_lock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1035 {
1036         if (up_flag || rep)
1037                 return;
1038         chg_vc_kbd_lock(kbd, value);
1039 }
1040 
1041 static void do_slock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1042 {
1043         if (up_flag || rep)
1044                 return;
1045         chg_vc_kbd_slock(kbd, value);
1046 }
1047 
1048 /*
1049  * send_data sends a character to the keyboard and waits
1050  * for a acknowledge, possibly retrying if asked to. Returns
1051  * the success status.
1052  */
1053 static int send_data(unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
1054 {
1055         int retries = 3;
1056         int i;
1057 
1058         do {
1059                 kb_wait();
1060                 acknowledge = 0;
1061                 resend = 0;
1062                 reply_expected = 1;
1063                 outb_p(data, 0x60);
1064                 for(i=0; i<0x200000; i++) {
1065                         inb_p(0x64);            /* just as a delay */
1066                         if (acknowledge)
1067                                 return 1;
1068                         if (resend)
1069                                 break;
1070                 }
1071                 if (!resend)
1072                         return 0;
1073         } while (retries-- > 0);
1074         return 0;
1075 }
1076 
1077 /*
1078  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1079  * or (ii) whatever pattern of lights people want to show using KDSETLED,
1080  * or (iii) specified bits of specified words in kernel memory.
1081  */
1082 
1083 static unsigned char ledstate = 0xff; /* undefined */
1084 static unsigned char ledioctl;
1085 
1086 unsigned char getledstate(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
1087     return ledstate;
1088 }
1089 
1090 void setledstate(struct kbd_struct *kbd, unsigned int led) {
     /* [previous][next][first][last][top][bottom][index][help] */
1091     if (!(led & ~7)) {
1092         ledioctl = led;
1093         kbd->ledmode = LED_SHOW_IOCTL;
1094     } else
1095         kbd->ledmode = LED_SHOW_FLAGS;
1096     set_leds();
1097 }
1098 
1099 static struct ledptr {
1100     unsigned int *addr;
1101     unsigned int mask;
1102     unsigned char valid:1;
1103 } ledptrs[3];
1104 
1105 void register_leds(int console, unsigned int led,
     /* [previous][next][first][last][top][bottom][index][help] */
1106                    unsigned int *addr, unsigned int mask) {
1107     struct kbd_struct *kbd = kbd_table + console;
1108     if (led < 3) {
1109         ledptrs[led].addr = addr;
1110         ledptrs[led].mask = mask;
1111         ledptrs[led].valid = 1;
1112         kbd->ledmode = LED_SHOW_MEM;
1113     } else
1114         kbd->ledmode = LED_SHOW_FLAGS;
1115 }
1116 
1117 static inline unsigned char getleds(void){
     /* [previous][next][first][last][top][bottom][index][help] */
1118     struct kbd_struct *kbd = kbd_table + fg_console;
1119     unsigned char leds;
1120 
1121     if (kbd->ledmode == LED_SHOW_IOCTL)
1122       return ledioctl;
1123     leds = kbd->ledflagstate;
1124     if (kbd->ledmode == LED_SHOW_MEM) {
1125         if (ledptrs[0].valid) {
1126             if (*ledptrs[0].addr & ledptrs[0].mask)
1127               leds |= 1;
1128             else
1129               leds &= ~1;
1130         }
1131         if (ledptrs[1].valid) {
1132             if (*ledptrs[1].addr & ledptrs[1].mask)
1133               leds |= 2;
1134             else
1135               leds &= ~2;
1136         }
1137         if (ledptrs[2].valid) {
1138             if (*ledptrs[2].addr & ledptrs[2].mask)
1139               leds |= 4;
1140             else
1141               leds &= ~4;
1142         }
1143     }
1144     return leds;
1145 }
1146 
1147 /*
1148  * This routine is the bottom half of the keyboard interrupt
1149  * routine, and runs with all interrupts enabled. It does
1150  * console changing, led setting and copy_to_cooked, which can
1151  * take a reasonably long time.
1152  *
1153  * Aside from timing (which isn't really that important for
1154  * keyboard interrupts as they happen often), using the software
1155  * interrupt routines for this thing allows us to easily mask
1156  * this when we don't want any of the above to happen. Not yet
1157  * used, but this allows for easy and efficient race-condition
1158  * prevention later on.
1159  */
1160 static void kbd_bh(void * unused)
     /* [previous][next][first][last][top][bottom][index][help] */
1161 {
1162         unsigned char leds = getleds();
1163 
1164         if (leds != ledstate) {
1165                 ledstate = leds;
1166                 if (!send_data(0xed) || !send_data(leds))
1167                         send_data(0xf4);        /* re-enable kbd if any errors */
1168         }
1169         if (want_console >= 0) {
1170                 if (want_console != fg_console) {
1171                         change_console(want_console);
1172                         /* we only changed when the console had already
1173                            been allocated - a new console is not created
1174                            in an interrupt routine */
1175                 }
1176                 want_console = -1;
1177         }
1178         if (do_poke_blanked_console) { /* do not unblank for a LED change */
1179                 do_poke_blanked_console = 0;
1180                 poke_blanked_console();
1181         }
1182 }
1183 
1184 int kbd_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1185 {
1186         int i;
1187         struct kbd_struct kbd0;
1188         extern struct tty_driver console_driver;
1189 
1190         kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1191         kbd0.ledmode = LED_SHOW_FLAGS;
1192         kbd0.lockstate = KBD_DEFLOCK;
1193         kbd0.slockstate = 0;
1194         kbd0.modeflags = KBD_DEFMODE;
1195         kbd0.kbdmode = VC_XLATE;
1196  
1197         for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1198                 kbd_table[i] = kbd0;
1199 
1200         ttytab = console_driver.table;
1201 
1202         bh_base[KEYBOARD_BH].routine = kbd_bh;
1203         request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
1204         request_region(0x60,16,"kbd");
1205 #ifdef INIT_KBD
1206         initialize_kbd();
1207 #endif
1208         mark_bh(KEYBOARD_BH);
1209         enable_bh(KEYBOARD_BH);
1210         return 0;
1211 }
1212 
1213 #ifdef INIT_KBD
1214 /*
1215  * keyboard controller registers
1216  */
1217 #define KBD_STATUS_REG      (unsigned int) 0x64
1218 #define KBD_CNTL_REG        (unsigned int) 0x64
1219 #define KBD_DATA_REG        (unsigned int) 0x60
1220 /*
1221  * controller commands
1222  */
1223 #define KBD_READ_MODE       (unsigned int) 0x20
1224 #define KBD_WRITE_MODE      (unsigned int) 0x60
1225 #define KBD_SELF_TEST       (unsigned int) 0xAA
1226 #define KBD_SELF_TEST2      (unsigned int) 0xAB
1227 #define KBD_CNTL_ENABLE     (unsigned int) 0xAE
1228 /*
1229  * keyboard commands
1230  */
1231 #define KBD_ENABLE          (unsigned int) 0xF4
1232 #define KBD_DISABLE         (unsigned int) 0xF5
1233 #define KBD_RESET           (unsigned int) 0xFF
1234 /*
1235  * keyboard replies
1236  */
1237 #define KBD_ACK             (unsigned int) 0xFA
1238 #define KBD_POR             (unsigned int) 0xAA
1239 /*
1240  * status register bits
1241  */
1242 #define KBD_OBF             (unsigned int) 0x01
1243 #define KBD_IBF             (unsigned int) 0x02
1244 #define KBD_GTO             (unsigned int) 0x40
1245 #define KBD_PERR            (unsigned int) 0x80
1246 /*
1247  * keyboard controller mode register bits
1248  */
1249 #define KBD_EKI             (unsigned int) 0x01
1250 #define KBD_SYS             (unsigned int) 0x04
1251 #define KBD_DMS             (unsigned int) 0x20
1252 #define KBD_KCC             (unsigned int) 0x40
1253 
1254 #define TIMEOUT_CONST   500000
1255 
1256 static int kbd_wait_for_input(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1257 {
1258         int     n;
1259         int     status, data;
1260 
1261         n = TIMEOUT_CONST;
1262         do {
1263                 status = inb(KBD_STATUS_REG);
1264                 /*
1265                  * Wait for input data to become available.  This bit will
1266                  * then be cleared by the following read of the DATA
1267                  * register.
1268                  */
1269 
1270                 if (!(status & KBD_OBF))
1271                         continue;
1272 
1273                 data = inb(KBD_DATA_REG);
1274 
1275                 /*
1276                  * Check to see if a timeout error has occured.  This means
1277                  * that transmission was started but did not complete in the
1278                  * normal time cycle.  PERR is set when a parity error occured
1279                  * in the last transmission.
1280                  */
1281                 if (status & (KBD_GTO | KBD_PERR)) {
1282                         continue;
1283                 }
1284                 return (data & 0xff);
1285         } while (--n);
1286         return (-1);    /* timed-out if fell through to here... */
1287 }
1288 
1289 static void kbd_write(int address, int data)
     /* [previous][next][first][last][top][bottom][index][help] */
1290 {
1291         int status;
1292 
1293         do {
1294                 status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
1295         } while (status & KBD_IBF);
1296         outb(data, address);               /* write out the data*/
1297 }
1298 
1299 static int initialize_kbd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1300 {
1301         unsigned long flags;
1302 
1303         save_flags(flags); cli();
1304 
1305         /* Flush any pending input. */
1306         while (kbd_wait_for_input() != -1)
1307                 continue;
1308 
1309         /*
1310          * Test the keyboard interface.
1311          * This seems to be the only way to get it going.
1312          * If the test is successful a x55 is placed in the input buffer.
1313          */
1314         kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
1315         if (kbd_wait_for_input() != 0x55) {
1316                 printk("initialize_kbd: keyboard failed self test.\n");
1317                 restore_flags(flags);
1318                 return(-1);
1319         }
1320 
1321         /*
1322          * Perform a keyboard interface test.  This causes the controller
1323          * to test the keyboard clock and data lines.  The results of the
1324          * test are placed in the input buffer.
1325          */
1326         kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
1327         if (kbd_wait_for_input() != 0x00) {
1328                 printk("initialize_kbd: keyboard failed self test 2.\n");
1329                 restore_flags(flags);
1330                 return(-1);
1331         }
1332 
1333         /* Enable the keyboard by allowing the keyboard clock to run. */
1334         kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
1335 
1336         /*
1337          * Reset keyboard. If the read times out
1338          * then the assumption is that no keyboard is
1339          * plugged into the machine.
1340          * This defaults the keyboard to scan-code set 2.
1341          */
1342         kbd_write(KBD_DATA_REG, KBD_RESET);
1343         if (kbd_wait_for_input() != KBD_ACK) {
1344                 printk("initialize_kbd: reset kbd failed, no ACK.\n");
1345                 restore_flags(flags);
1346                 return(-1);
1347         }
1348 
1349         if (kbd_wait_for_input() != KBD_POR) {
1350                 printk("initialize_kbd: reset kbd failed, not POR.\n");
1351                 restore_flags(flags);
1352                 return(-1);
1353         }
1354 
1355         /*
1356          * now do a DEFAULTS_DISABLE always
1357          */
1358         kbd_write(KBD_DATA_REG, KBD_DISABLE);
1359         if (kbd_wait_for_input() != KBD_ACK) {
1360                 printk("initialize_kbd: disable kbd failed, no ACK.\n");
1361                 restore_flags(flags);
1362                 return(-1);
1363         }
1364 
1365         /*
1366          * Enable keyboard interrupt, operate in "sys" mode,
1367          *  enable keyboard (by clearing the disable keyboard bit),
1368          *  disable mouse, do conversion of keycodes.
1369          */
1370         kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
1371         kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
1372 
1373         /*
1374          * now ENABLE the keyboard to set it scanning...
1375          */
1376         kbd_write(KBD_DATA_REG, KBD_ENABLE);
1377         if (kbd_wait_for_input() != KBD_ACK) {
1378                 printk("initialize_kbd: keyboard enable failed.\n");
1379                 restore_flags(flags);
1380                 return(-1);
1381         }
1382 
1383         restore_flags(flags);
1384 
1385         return (1);
1386 }
1387 #endif /* INIT_KBD */

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