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