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. alpha_kbd_init

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

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