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 
 347         pt_regs = regs;
 348         send_cmd(0xAD);         /* disable keyboard */
 349         kb_wait();
 350         if ((inb_p(0x64) & kbd_read_mask) != 0x01)
 351                 goto end_kbd_intr;
 352         scancode = inb(0x60);
 353         mark_bh(KEYBOARD_BH);
 354         if (reply_expected) {
 355           /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
 356           /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
 357                 reply_expected = 0;
 358                 if (scancode == 0xfa) {
 359                         acknowledge = 1;
 360                         goto end_kbd_intr;
 361                 } else if (scancode == 0xfe) {
 362                         resend = 1;
 363                         goto end_kbd_intr;
 364                 }
 365                 /* strange ... */
 366                 reply_expected = 1;
 367 #if 0
 368                 printk("keyboard reply expected - got %02x\n", scancode);
 369 #endif
 370         }
 371         if (scancode == 0) {
 372 #ifdef KBD_REPORT_ERR
 373                 printk("keyboard buffer overflow\n");
 374 #endif
 375                 prev_scancode = 0;
 376                 goto end_kbd_intr;
 377         }
 378         do_poke_blanked_console = 1;
 379         mark_bh(CONSOLE_BH);
 380         add_keyboard_randomness(scancode);
 381 
 382         tty = ttytab[fg_console];
 383         kbd = kbd_table + fg_console;
 384         if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
 385                 put_queue(scancode);
 386                 /* we do not return yet, because we want to maintain
 387                    the key_down array, so that we have the correct
 388                    values when finishing RAW mode or when changing VT's */
 389         }
 390 
 391         if (scancode == 0xff) {
 392                 /* in scancode mode 1, my ESC key generates 0xff */
 393                 /* the calculator keys on a FOCUS 9000 generate 0xff */
 394 #ifndef KBD_IS_FOCUS_9000
 395 #ifdef KBD_REPORT_ERR
 396                 if (!raw_mode)
 397                   printk("keyboard error\n");
 398 #endif
 399 #endif
 400                 prev_scancode = 0;
 401                 goto end_kbd_intr;
 402         }
 403 
 404         if (scancode == 0xe0 || scancode == 0xe1) {
 405                 prev_scancode = scancode;
 406                 goto end_kbd_intr;
 407         }
 408 
 409         /*
 410          *  Convert scancode to keycode, using prev_scancode.
 411          */
 412         up_flag = (scancode & 0200);
 413         scancode &= 0x7f;
 414 
 415         if (prev_scancode) {
 416           /*
 417            * usually it will be 0xe0, but a Pause key generates
 418            * e1 1d 45 e1 9d c5 when pressed, and nothing when released
 419            */
 420           if (prev_scancode != 0xe0) {
 421               if (prev_scancode == 0xe1 && scancode == 0x1d) {
 422                   prev_scancode = 0x100;
 423                   goto end_kbd_intr;
 424               } else if (prev_scancode == 0x100 && scancode == 0x45) {
 425                   keycode = E1_PAUSE;
 426                   prev_scancode = 0;
 427               } else {
 428 #ifdef KBD_REPORT_UNKN
 429                   if (!raw_mode)
 430                     printk("keyboard: unknown e1 escape sequence\n");
 431 #endif
 432                   prev_scancode = 0;
 433                   goto end_kbd_intr;
 434               }
 435           } else {
 436               prev_scancode = 0;
 437               /*
 438                *  The keyboard maintains its own internal caps lock and
 439                *  num lock statuses. In caps lock mode E0 AA precedes make
 440                *  code and E0 2A follows break code. In num lock mode,
 441                *  E0 2A precedes make code and E0 AA follows break code.
 442                *  We do our own book-keeping, so we will just ignore these.
 443                */
 444               /*
 445                *  For my keyboard there is no caps lock mode, but there are
 446                *  both Shift-L and Shift-R modes. The former mode generates
 447                *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
 448                *  So, we should also ignore the latter. - aeb@cwi.nl
 449                */
 450               if (scancode == 0x2a || scancode == 0x36)
 451                 goto end_kbd_intr;
 452 
 453               if (e0_keys[scancode])
 454                 keycode = e0_keys[scancode];
 455               else {
 456 #ifdef KBD_REPORT_UNKN
 457                   if (!raw_mode)
 458                     printk("keyboard: unknown scancode e0 %02x\n", scancode);
 459 #endif
 460                   goto end_kbd_intr;
 461               }
 462           }
 463         } else if (scancode >= SC_LIM) {
 464             /* This happens with the FOCUS 9000 keyboard
 465                Its keys PF1..PF12 are reported to generate
 466                55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
 467                Moreover, unless repeated, they do not generate
 468                key-down events, so we have to zero up_flag below */
 469             /* Also, Japanese 86/106 keyboards are reported to
 470                generate 0x73 and 0x7d for \ - and \ | respectively. */
 471             /* Also, some Brazilian keyboard is reported to produce
 472                0x73 and 0x7e for \ ? and KP-dot, respectively. */
 473 
 474           keycode = high_keys[scancode - SC_LIM];
 475 
 476           if (!keycode) {
 477               if (!raw_mode) {
 478 #ifdef KBD_REPORT_UNKN
 479                   printk("keyboard: unrecognized scancode (%02x) - ignored\n"
 480                          , scancode);
 481 #endif
 482               }
 483               goto end_kbd_intr;
 484           }
 485         } else
 486           keycode = scancode;
 487 
 488         /*
 489          * At this point the variable `keycode' contains the keycode.
 490          * Note: the keycode must not be 0.
 491          * We keep track of the up/down status of the key, and
 492          * return the keycode if in MEDIUMRAW mode.
 493          */
 494 
 495         if (up_flag) {
 496                 rep = 0;
 497                 if(!clear_bit(keycode, key_down)) {
 498                     /* unexpected, but this can happen:
 499                        maybe this was a key release for a FOCUS 9000
 500                        PF key; if we want to see it, we have to clear
 501                        up_flag */
 502                     if (keycode >= SC_LIM || keycode == 85)
 503                       up_flag = 0;
 504                 }
 505         } else
 506                 rep = set_bit(keycode, key_down);
 507 
 508         if (raw_mode)
 509                 goto end_kbd_intr;
 510 
 511         if (kbd->kbdmode == VC_MEDIUMRAW) {
 512                 /* soon keycodes will require more than one byte */
 513                 put_queue(keycode + up_flag);
 514                 goto end_kbd_intr;
 515         }
 516 
 517         /*
 518          * Small change in philosophy: earlier we defined repetition by
 519          *       rep = keycode == prev_keycode;
 520          *       prev_keycode = keycode;
 521          * but now by the fact that the depressed key was down already.
 522          * Does this ever make a difference? Yes.
 523          */
 524 
 525         /*
 526          *  Repeat a key only if the input buffers are empty or the
 527          *  characters get echoed locally. This makes key repeat usable
 528          *  with slow applications and under heavy loads.
 529          */
 530         if (!rep ||
 531             (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 532              (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
 533                 u_short keysym;
 534                 u_char type;
 535 
 536                 /* the XOR below used to be an OR */
 537                 int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
 538                 ushort *key_map = key_maps[shift_final];
 539 
 540                 if (key_map != NULL) {
 541                         keysym = key_map[keycode];
 542                         type = KTYP(keysym);
 543 
 544                         if (type >= 0xf0) {
 545                             type -= 0xf0;
 546                             if (type == KT_LETTER) {
 547                                 type = KT_LATIN;
 548                                 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
 549                                     key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
 550                                     if (key_map)
 551                                       keysym = key_map[keycode];
 552                                 }
 553                             }
 554                             (*key_handler[type])(keysym & 0xff, up_flag);
 555                             if (type != KT_SLOCK)
 556                               kbd->slockstate = 0;
 557                         } else {
 558                             /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
 559                             if (!up_flag)
 560                               to_utf8(keysym);
 561                         }
 562                 } else {
 563                         /* maybe beep? */
 564                         /* we have at least to update shift_state */
 565 #if 1                   /* how? two almost equivalent choices follow */
 566                         compute_shiftstate();
 567 #else
 568                         keysym = U(plain_map[keycode]);
 569                         type = KTYP(keysym);
 570                         if (type == KT_SHIFT)
 571                           (*key_handler[type])(keysym & 0xff, up_flag);
 572 #endif
 573                 }
 574         }
 575 
 576 end_kbd_intr:
 577         send_cmd(0xAE);         /* enable keyboard */
 578 }
 579 
 580 static void put_queue(int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         wake_up(&keypress_wait);
 583         if (tty) {
 584                 tty_insert_flip_char(tty, ch, 0);
 585                 tty_schedule_flip(tty);
 586         }
 587 }
 588 
 589 static void puts_queue(char *cp)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591         wake_up(&keypress_wait);
 592         if (!tty)
 593                 return;
 594 
 595         while (*cp) {
 596                 tty_insert_flip_char(tty, *cp, 0);
 597                 cp++;
 598         }
 599         tty_schedule_flip(tty);
 600 }
 601 
 602 static void applkey(int key, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 603 {
 604         static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
 605 
 606         buf[1] = (mode ? 'O' : '[');
 607         buf[2] = key;
 608         puts_queue(buf);
 609 }
 610 
 611 static void enter(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 612 {
 613         put_queue(13);
 614         if (vc_kbd_mode(kbd,VC_CRLF))
 615                 put_queue(10);
 616 }
 617 
 618 static void caps_toggle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 619 {
 620         if (rep)
 621                 return;
 622         chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 623 }
 624 
 625 static void caps_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 626 {
 627         if (rep)
 628                 return;
 629         set_vc_kbd_led(kbd, VC_CAPSLOCK);
 630 }
 631 
 632 static void show_ptregs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         if (pt_regs)
 635                 show_regs(pt_regs);
 636 }
 637 
 638 static void hold(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 639 {
 640         if (rep || !tty)
 641                 return;
 642 
 643         /*
 644          * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 645          * these routines are also activated by ^S/^Q.
 646          * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 647          */
 648         if (tty->stopped)
 649                 start_tty(tty);
 650         else
 651                 stop_tty(tty);
 652 }
 653 
 654 static void num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 655 {
 656         if (vc_kbd_mode(kbd,VC_APPLIC))
 657                 applkey('P', 1);
 658         else
 659                 bare_num();
 660 }
 661 
 662 /*
 663  * Bind this to Shift-NumLock if you work in application keypad mode
 664  * but want to be able to change the NumLock flag.
 665  * Bind this to NumLock if you prefer that the NumLock key always
 666  * changes the NumLock flag.
 667  */
 668 static void bare_num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 669 {
 670         if (!rep)
 671                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 672 }
 673 
 674 static void lastcons(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 675 {
 676         /* switch to the last used console, ChN */
 677         set_console(last_console);
 678 }
 679 
 680 static void decr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 681 {
 682         int i;
 683  
 684         for (i = fg_console-1; i != fg_console; i--) {
 685                 if (i == -1)
 686                         i = MAX_NR_CONSOLES-1;
 687                 if (vc_cons_allocated(i))
 688                         break;
 689         }
 690         set_console(i);
 691 }
 692 
 693 static void incr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 694 {
 695         int i;
 696 
 697         for (i = fg_console+1; i != fg_console; i++) {
 698                 if (i == MAX_NR_CONSOLES)
 699                         i = 0;
 700                 if (vc_cons_allocated(i))
 701                         break;
 702         }
 703         set_console(i);
 704 }
 705 
 706 static void send_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         if (!tty)
 709                 return;
 710         tty_insert_flip_char(tty, 0, TTY_BREAK);
 711         tty_schedule_flip(tty);
 712 }
 713 
 714 static void scroll_forw(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 715 {
 716         scrollfront(0);
 717 }
 718 
 719 static void scroll_back(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 720 {
 721         scrollback(0);
 722 }
 723 
 724 static void boot_it(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 725 {
 726         ctrl_alt_del();
 727 }
 728 
 729 static void compose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 730 {
 731         dead_key_next = 1;
 732 }
 733 
 734 int spawnpid, spawnsig;
 735 
 736 static void spawn_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 737 {
 738         if (spawnpid)
 739            if(kill_proc(spawnpid, spawnsig, 1))
 740              spawnpid = 0;
 741 }
 742 
 743 static void SAK(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 744 {
 745         do_SAK(tty);
 746 #if 0
 747         /*
 748          * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 749          * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 750          * handling.
 751          * 
 752          * We should do this some day --- the whole point of a secure
 753          * attention key is that it should be guaranteed to always
 754          * work.
 755          */
 756         reset_vc(fg_console);
 757         do_unblank_screen();    /* not in interrupt routine? */
 758 #endif
 759 }
 760 
 761 static void do_ignore(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 762 {
 763 }
 764 
 765 static void do_null()
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767         compute_shiftstate();
 768 }
 769 
 770 static void do_spec(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 771 {
 772         if (up_flag)
 773                 return;
 774         if (value >= SIZE(spec_fn_table))
 775                 return;
 776         spec_fn_table[value]();
 777 }
 778 
 779 static void do_lowercase(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 780 {
 781         printk("keyboard.c: do_lowercase was called - impossible\n");
 782 }
 783 
 784 static void do_self(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 785 {
 786         if (up_flag)
 787                 return;         /* no action, if this is a key release */
 788 
 789         if (diacr)
 790                 value = handle_diacr(value);
 791 
 792         if (dead_key_next) {
 793                 dead_key_next = 0;
 794                 diacr = value;
 795                 return;
 796         }
 797 
 798         put_queue(value);
 799 }
 800 
 801 #define A_GRAVE  '`'
 802 #define A_ACUTE  '\''
 803 #define A_CFLEX  '^'
 804 #define A_TILDE  '~'
 805 #define A_DIAER  '"'
 806 static unsigned char ret_diacr[] =
 807         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 808 
 809 /* If a dead key pressed twice, output a character corresponding to it, */
 810 /* otherwise just remember the dead key.                                */
 811 
 812 static void do_dead(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 813 {
 814         if (up_flag)
 815                 return;
 816 
 817         value = ret_diacr[value];
 818         if (diacr == value) {   /* pressed twice */
 819                 diacr = 0;
 820                 put_queue(value);
 821                 return;
 822         }
 823         diacr = value;
 824 }
 825 
 826 
 827 /* If space is pressed, return the character corresponding the pending  */
 828 /* dead key, otherwise try to combine the two.                          */
 829 
 830 unsigned char handle_diacr(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 831 {
 832         int d = diacr;
 833         int i;
 834 
 835         diacr = 0;
 836         if (ch == ' ')
 837                 return d;
 838 
 839         for (i = 0; i < accent_table_size; i++) {
 840                 if (accent_table[i].diacr == d && accent_table[i].base == ch)
 841                         return accent_table[i].result;
 842         }
 843 
 844         put_queue(d);
 845         return ch;
 846 }
 847 
 848 static void do_cons(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 849 {
 850         if (up_flag)
 851                 return;
 852         set_console(value);
 853 }
 854 
 855 static void do_fn(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857         if (up_flag)
 858                 return;
 859         if (value < SIZE(func_table)) {
 860                 if (func_table[value])
 861                         puts_queue(func_table[value]);
 862         } else
 863                 printk("do_fn called with value=%d\n", value);
 864 }
 865 
 866 static void do_pad(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 867 {
 868         static const char *pad_chars = "0123456789+-*/\015,.?";
 869         static const char *app_map = "pqrstuvwxylSRQMnn?";
 870 
 871         if (up_flag)
 872                 return;         /* no action, if this is a key release */
 873 
 874         /* kludge... shift forces cursor/number keys */
 875         if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
 876                 applkey(app_map[value], 1);
 877                 return;
 878         }
 879 
 880         if (!vc_kbd_led(kbd,VC_NUMLOCK))
 881                 switch (value) {
 882                         case KVAL(K_PCOMMA):
 883                         case KVAL(K_PDOT):
 884                                 do_fn(KVAL(K_REMOVE), 0);
 885                                 return;
 886                         case KVAL(K_P0):
 887                                 do_fn(KVAL(K_INSERT), 0);
 888                                 return;
 889                         case KVAL(K_P1):
 890                                 do_fn(KVAL(K_SELECT), 0);
 891                                 return;
 892                         case KVAL(K_P2):
 893                                 do_cur(KVAL(K_DOWN), 0);
 894                                 return;
 895                         case KVAL(K_P3):
 896                                 do_fn(KVAL(K_PGDN), 0);
 897                                 return;
 898                         case KVAL(K_P4):
 899                                 do_cur(KVAL(K_LEFT), 0);
 900                                 return;
 901                         case KVAL(K_P6):
 902                                 do_cur(KVAL(K_RIGHT), 0);
 903                                 return;
 904                         case KVAL(K_P7):
 905                                 do_fn(KVAL(K_FIND), 0);
 906                                 return;
 907                         case KVAL(K_P8):
 908                                 do_cur(KVAL(K_UP), 0);
 909                                 return;
 910                         case KVAL(K_P9):
 911                                 do_fn(KVAL(K_PGUP), 0);
 912                                 return;
 913                         case KVAL(K_P5):
 914                                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
 915                                 return;
 916                 }
 917 
 918         put_queue(pad_chars[value]);
 919         if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
 920                 put_queue(10);
 921 }
 922 
 923 static void do_cur(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 924 {
 925         static const char *cur_chars = "BDCA";
 926         if (up_flag)
 927                 return;
 928 
 929         applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 930 }
 931 
 932 static void do_shift(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 933 {
 934         int old_state = shift_state;
 935 
 936         if (rep)
 937                 return;
 938 
 939         /* Mimic typewriter:
 940            a CapsShift key acts like Shift but undoes CapsLock */
 941         if (value == KVAL(K_CAPSSHIFT)) {
 942                 value = KVAL(K_SHIFT);
 943                 if (!up_flag)
 944                         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
 945         }
 946 
 947         if (up_flag) {
 948                 /* handle the case that two shift or control
 949                    keys are depressed simultaneously */
 950                 if (k_down[value])
 951                         k_down[value]--;
 952         } else
 953                 k_down[value]++;
 954 
 955         if (k_down[value])
 956                 shift_state |= (1 << value);
 957         else
 958                 shift_state &= ~ (1 << value);
 959 
 960         /* kludge */
 961         if (up_flag && shift_state != old_state && npadch != -1) {
 962                 if (kbd->kbdmode == VC_UNICODE)
 963                   to_utf8(npadch & 0xffff);
 964                 else
 965                   put_queue(npadch & 0xff);
 966                 npadch = -1;
 967         }
 968 }
 969 
 970 /* called after returning from RAW mode or when changing consoles -
 971    recompute k_down[] and shift_state from key_down[] */
 972 /* maybe called when keymap is undefined, so that shiftkey release is seen */
 973 void compute_shiftstate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 974 {
 975         int i, j, k, sym, val;
 976 
 977         shift_state = 0;
 978         for(i=0; i < SIZE(k_down); i++)
 979           k_down[i] = 0;
 980 
 981         for(i=0; i < SIZE(key_down); i++)
 982           if(key_down[i]) {     /* skip this word if not a single bit on */
 983             k = i*BITS_PER_LONG;
 984             for(j=0; j<BITS_PER_LONG; j++,k++)
 985               if(test_bit(k, key_down)) {
 986                 sym = U(plain_map[k]);
 987                 if(KTYP(sym) == KT_SHIFT) {
 988                   val = KVAL(sym);
 989                   if (val == KVAL(K_CAPSSHIFT))
 990                     val = KVAL(K_SHIFT);
 991                   k_down[val]++;
 992                   shift_state |= (1<<val);
 993                 }
 994               }
 995           }
 996 }
 997 
 998 static void do_meta(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 999 {
1000         if (up_flag)
1001                 return;
1002 
1003         if (vc_kbd_mode(kbd, VC_META)) {
1004                 put_queue('\033');
1005                 put_queue(value);
1006         } else
1007                 put_queue(value | 0x80);
1008 }
1009 
1010 static void do_ascii(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1011 {
1012         int base;
1013 
1014         if (up_flag)
1015                 return;
1016 
1017         if (value < 10)    /* decimal input of code, while Alt depressed */
1018             base = 10;
1019         else {       /* hexadecimal input of code, while AltGr depressed */
1020             value -= 10;
1021             base = 16;
1022         }
1023 
1024         if (npadch == -1)
1025           npadch = value;
1026         else
1027           npadch = npadch * base + value;
1028 }
1029 
1030 static void do_lock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
1031 {
1032         if (up_flag || rep)
1033                 return;
1034         chg_vc_kbd_lock(kbd, value);
1035 }
1036 
1037 static void do_slock(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_slock(kbd, value);
1042 }
1043 
1044 /*
1045  * send_data sends a character to the keyboard and waits
1046  * for a acknowledge, possibly retrying if asked to. Returns
1047  * the success status.
1048  */
1049 static int send_data(unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
1050 {
1051         int retries = 3;
1052         int i;
1053 
1054         do {
1055                 kb_wait();
1056                 acknowledge = 0;
1057                 resend = 0;
1058                 reply_expected = 1;
1059                 outb_p(data, 0x60);
1060                 for(i=0; i<0x200000; i++) {
1061                         inb_p(0x64);            /* just as a delay */
1062                         if (acknowledge)
1063                                 return 1;
1064                         if (resend)
1065                                 break;
1066                 }
1067                 if (!resend)
1068                         return 0;
1069         } while (retries-- > 0);
1070         return 0;
1071 }
1072 
1073 /*
1074  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
1075  * or (ii) whatever pattern of lights people want to show using KDSETLED,
1076  * or (iii) specified bits of specified words in kernel memory.
1077  */
1078 
1079 static unsigned char ledstate = 0xff; /* undefined */
1080 static unsigned char ledioctl;
1081 
1082 unsigned char getledstate(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
1083     return ledstate;
1084 }
1085 
1086 void setledstate(struct kbd_struct *kbd, unsigned int led) {
     /* [previous][next][first][last][top][bottom][index][help] */
1087     if (!(led & ~7)) {
1088         ledioctl = led;
1089         kbd->ledmode = LED_SHOW_IOCTL;
1090     } else
1091         kbd->ledmode = LED_SHOW_FLAGS;
1092     set_leds();
1093 }
1094 
1095 static struct ledptr {
1096     unsigned int *addr;
1097     unsigned int mask;
1098     unsigned char valid:1;
1099 } ledptrs[3];
1100 
1101 void register_leds(int console, unsigned int led,
     /* [previous][next][first][last][top][bottom][index][help] */
1102                    unsigned int *addr, unsigned int mask) {
1103     struct kbd_struct *kbd = kbd_table + console;
1104     if (led < 3) {
1105         ledptrs[led].addr = addr;
1106         ledptrs[led].mask = mask;
1107         ledptrs[led].valid = 1;
1108         kbd->ledmode = LED_SHOW_MEM;
1109     } else
1110         kbd->ledmode = LED_SHOW_FLAGS;
1111 }
1112 
1113 static inline unsigned char getleds(void){
     /* [previous][next][first][last][top][bottom][index][help] */
1114     struct kbd_struct *kbd = kbd_table + fg_console;
1115     unsigned char leds;
1116 
1117     if (kbd->ledmode == LED_SHOW_IOCTL)
1118       return ledioctl;
1119     leds = kbd->ledflagstate;
1120     if (kbd->ledmode == LED_SHOW_MEM) {
1121         if (ledptrs[0].valid) {
1122             if (*ledptrs[0].addr & ledptrs[0].mask)
1123               leds |= 1;
1124             else
1125               leds &= ~1;
1126         }
1127         if (ledptrs[1].valid) {
1128             if (*ledptrs[1].addr & ledptrs[1].mask)
1129               leds |= 2;
1130             else
1131               leds &= ~2;
1132         }
1133         if (ledptrs[2].valid) {
1134             if (*ledptrs[2].addr & ledptrs[2].mask)
1135               leds |= 4;
1136             else
1137               leds &= ~4;
1138         }
1139     }
1140     return leds;
1141 }
1142 
1143 /*
1144  * This routine is the bottom half of the keyboard interrupt
1145  * routine, and runs with all interrupts enabled. It does
1146  * console changing, led setting and copy_to_cooked, which can
1147  * take a reasonably long time.
1148  *
1149  * Aside from timing (which isn't really that important for
1150  * keyboard interrupts as they happen often), using the software
1151  * interrupt routines for this thing allows us to easily mask
1152  * this when we don't want any of the above to happen. Not yet
1153  * used, but this allows for easy and efficient race-condition
1154  * prevention later on.
1155  */
1156 static void kbd_bh(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1157 {
1158         unsigned char leds = getleds();
1159 
1160         if (leds != ledstate) {
1161                 ledstate = leds;
1162                 if (!send_data(0xed) || !send_data(leds))
1163                         send_data(0xf4);        /* re-enable kbd if any errors */
1164         }
1165 }
1166 
1167 int kbd_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1168 {
1169         int i;
1170         struct kbd_struct kbd0;
1171         extern struct tty_driver console_driver;
1172 
1173         kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
1174         kbd0.ledmode = LED_SHOW_FLAGS;
1175         kbd0.lockstate = KBD_DEFLOCK;
1176         kbd0.slockstate = 0;
1177         kbd0.modeflags = KBD_DEFMODE;
1178         kbd0.kbdmode = VC_XLATE;
1179  
1180         for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
1181                 kbd_table[i] = kbd0;
1182 
1183         ttytab = console_driver.table;
1184 
1185         request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
1186         request_region(0x60,16,"kbd");
1187 #ifdef INIT_KBD
1188         initialize_kbd();
1189 #endif
1190         init_bh(KEYBOARD_BH, kbd_bh);
1191         mark_bh(KEYBOARD_BH);
1192         return 0;
1193 }
1194 
1195 #ifdef INIT_KBD
1196 /*
1197  * keyboard controller registers
1198  */
1199 #define KBD_STATUS_REG      (unsigned int) 0x64
1200 #define KBD_CNTL_REG        (unsigned int) 0x64
1201 #define KBD_DATA_REG        (unsigned int) 0x60
1202 /*
1203  * controller commands
1204  */
1205 #define KBD_READ_MODE       (unsigned int) 0x20
1206 #define KBD_WRITE_MODE      (unsigned int) 0x60
1207 #define KBD_SELF_TEST       (unsigned int) 0xAA
1208 #define KBD_SELF_TEST2      (unsigned int) 0xAB
1209 #define KBD_CNTL_ENABLE     (unsigned int) 0xAE
1210 /*
1211  * keyboard commands
1212  */
1213 #define KBD_ENABLE          (unsigned int) 0xF4
1214 #define KBD_DISABLE         (unsigned int) 0xF5
1215 #define KBD_RESET           (unsigned int) 0xFF
1216 /*
1217  * keyboard replies
1218  */
1219 #define KBD_ACK             (unsigned int) 0xFA
1220 #define KBD_POR             (unsigned int) 0xAA
1221 /*
1222  * status register bits
1223  */
1224 #define KBD_OBF             (unsigned int) 0x01
1225 #define KBD_IBF             (unsigned int) 0x02
1226 #define KBD_GTO             (unsigned int) 0x40
1227 #define KBD_PERR            (unsigned int) 0x80
1228 /*
1229  * keyboard controller mode register bits
1230  */
1231 #define KBD_EKI             (unsigned int) 0x01
1232 #define KBD_SYS             (unsigned int) 0x04
1233 #define KBD_DMS             (unsigned int) 0x20
1234 #define KBD_KCC             (unsigned int) 0x40
1235 
1236 #define TIMEOUT_CONST   500000
1237 
1238 static int kbd_wait_for_input(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1239 {
1240         int     n;
1241         int     status, data;
1242 
1243         n = TIMEOUT_CONST;
1244         do {
1245                 status = inb(KBD_STATUS_REG);
1246                 /*
1247                  * Wait for input data to become available.  This bit will
1248                  * then be cleared by the following read of the DATA
1249                  * register.
1250                  */
1251 
1252                 if (!(status & KBD_OBF))
1253                         continue;
1254 
1255                 data = inb(KBD_DATA_REG);
1256 
1257                 /*
1258                  * Check to see if a timeout error has occured.  This means
1259                  * that transmission was started but did not complete in the
1260                  * normal time cycle.  PERR is set when a parity error occured
1261                  * in the last transmission.
1262                  */
1263                 if (status & (KBD_GTO | KBD_PERR)) {
1264                         continue;
1265                 }
1266                 return (data & 0xff);
1267         } while (--n);
1268         return (-1);    /* timed-out if fell through to here... */
1269 }
1270 
1271 static void kbd_write(int address, int data)
     /* [previous][next][first][last][top][bottom][index][help] */
1272 {
1273         int status;
1274 
1275         do {
1276                 status = inb(KBD_STATUS_REG);  /* spin until input buffer empty*/
1277         } while (status & KBD_IBF);
1278         outb(data, address);               /* write out the data*/
1279 }
1280 
1281 static int initialize_kbd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1282 {
1283         unsigned long flags;
1284 
1285         save_flags(flags); cli();
1286 
1287         /* Flush any pending input. */
1288         while (kbd_wait_for_input() != -1)
1289                 continue;
1290 
1291         /*
1292          * Test the keyboard interface.
1293          * This seems to be the only way to get it going.
1294          * If the test is successful a x55 is placed in the input buffer.
1295          */
1296         kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
1297         if (kbd_wait_for_input() != 0x55) {
1298                 printk("initialize_kbd: keyboard failed self test.\n");
1299                 restore_flags(flags);
1300                 return(-1);
1301         }
1302 
1303         /*
1304          * Perform a keyboard interface test.  This causes the controller
1305          * to test the keyboard clock and data lines.  The results of the
1306          * test are placed in the input buffer.
1307          */
1308         kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
1309         if (kbd_wait_for_input() != 0x00) {
1310                 printk("initialize_kbd: keyboard failed self test 2.\n");
1311                 restore_flags(flags);
1312                 return(-1);
1313         }
1314 
1315         /* Enable the keyboard by allowing the keyboard clock to run. */
1316         kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
1317 
1318         /*
1319          * Reset keyboard. If the read times out
1320          * then the assumption is that no keyboard is
1321          * plugged into the machine.
1322          * This defaults the keyboard to scan-code set 2.
1323          */
1324         kbd_write(KBD_DATA_REG, KBD_RESET);
1325         if (kbd_wait_for_input() != KBD_ACK) {
1326                 printk("initialize_kbd: reset kbd failed, no ACK.\n");
1327                 restore_flags(flags);
1328                 return(-1);
1329         }
1330 
1331         if (kbd_wait_for_input() != KBD_POR) {
1332                 printk("initialize_kbd: reset kbd failed, not POR.\n");
1333                 restore_flags(flags);
1334                 return(-1);
1335         }
1336 
1337         /*
1338          * now do a DEFAULTS_DISABLE always
1339          */
1340         kbd_write(KBD_DATA_REG, KBD_DISABLE);
1341         if (kbd_wait_for_input() != KBD_ACK) {
1342                 printk("initialize_kbd: disable kbd failed, no ACK.\n");
1343                 restore_flags(flags);
1344                 return(-1);
1345         }
1346 
1347         /*
1348          * Enable keyboard interrupt, operate in "sys" mode,
1349          *  enable keyboard (by clearing the disable keyboard bit),
1350          *  disable mouse, do conversion of keycodes.
1351          */
1352         kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
1353         kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
1354 
1355         /*
1356          * now ENABLE the keyboard to set it scanning...
1357          */
1358         kbd_write(KBD_DATA_REG, KBD_ENABLE);
1359         if (kbd_wait_for_input() != KBD_ACK) {
1360                 printk("initialize_kbd: keyboard enable failed.\n");
1361                 restore_flags(flags);
1362                 return(-1);
1363         }
1364 
1365         restore_flags(flags);
1366 
1367         return (1);
1368 }
1369 #endif /* INIT_KBD */

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