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

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