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