home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / char / keyboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-03  |  20.6 KB  |  893 lines

  1. /*
  2.  * linux/kernel/chr_drv/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.  * Loadable keymaps by Risto Kankkunen, May 1993
  11.  * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
  12.  */
  13.  
  14. #define KEYBOARD_IRQ 1
  15.  
  16. #include <linux/sched.h>
  17. #include <linux/tty.h>
  18. #include <linux/mm.h>
  19. #include <linux/ptrace.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/config.h>
  22. #include <linux/signal.h>
  23. #include <linux/string.h>
  24.  
  25. #include <asm/bitops.h>
  26.  
  27. #include "kbd_kern.h"
  28. #include "diacr.h"
  29.  
  30. #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  31.  
  32. #define KBD_REPORT_ERR
  33. #define KBD_REPORT_UNKN
  34.  
  35. #ifndef KBD_DEFMODE
  36. #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
  37. #endif
  38.  
  39. #ifndef KBD_DEFLEDS
  40. /*
  41.  * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  42.  * is on. This seems a good reason to start with NumLock off.
  43.  */
  44. #define KBD_DEFLEDS 0
  45. #endif
  46.  
  47. #ifndef KBD_DEFLOCK
  48. #define KBD_DEFLOCK 0
  49. #endif
  50.  
  51. /*
  52.  * The default IO slowdown is doing 'inb()'s from 0x61, which should be
  53.  * safe. But as that is the keyboard controller chip address, we do our
  54.  * slowdowns here by doing short jumps: the keyboard controller should
  55.  * be able to keep up
  56.  */
  57. #define REALLY_SLOW_IO
  58. #define SLOW_IO_BY_JUMPING
  59. #include <asm/io.h>
  60. #include <asm/system.h>
  61.  
  62. extern void do_keyboard_interrupt(void);
  63. extern void ctrl_alt_del(void);
  64. extern void change_console(unsigned int new_console);
  65. extern void scrollback(int);
  66. extern void scrollfront(int);
  67.  
  68. #define fake_keyboard_interrupt() \
  69. __asm__ __volatile__("int $0x21")
  70.  
  71. unsigned char kbd_read_mask = 0x01;    /* modified by psaux.c */
  72.  
  73. /*
  74.  * global state includes the following, and various static variables
  75.  * in this module: prev_scancode, shift_state, diacr, npadch,
  76.  *   dead_key_next, last_console
  77.  */
  78.  
  79. /* shift state counters.. */
  80. static unsigned char k_down[NR_SHIFT] = {0, };
  81. /* keyboard key bitmap */
  82. static unsigned long key_down[8] = { 0, };
  83.  
  84. static int want_console = -1;
  85. static int last_console = 0;        /* last used VC */
  86. static int dead_key_next = 0;
  87. static int shift_state = 0;
  88. static int npadch = -1;                /* -1 or number assembled on pad */
  89. static unsigned char diacr = 0;
  90. static char rep = 0;            /* flag telling character repeat */
  91. struct kbd_struct kbd_table[NR_CONSOLES];
  92. static struct kbd_struct * kbd = kbd_table;
  93. static struct tty_struct * tty = NULL;
  94.  
  95. /* used only by send_data - set by keyboard_interrupt */
  96. static volatile unsigned char acknowledge = 0;
  97. static volatile unsigned char resend = 0;
  98.  
  99. typedef void (*k_hand)(unsigned char value, char up_flag);
  100. typedef void (k_handfn)(unsigned char value, char up_flag);
  101.  
  102. static k_handfn
  103.         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
  104.     do_meta, do_ascii, do_lock, do_lowercase;
  105.  
  106. static k_hand key_handler[] = {
  107.     do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
  108.     do_meta, do_ascii, do_lock, do_lowercase
  109. };
  110.  
  111. /* maximum values each key_handler can handle */
  112. const int max_vals[] = {
  113.     255, NR_FUNC - 1, 14, 17, 4, 255, 3, NR_SHIFT,
  114.     255, 9, 3, 255
  115. };
  116.  
  117. const int NR_TYPES = SIZE(max_vals);
  118.  
  119. static void put_queue(int);
  120. static unsigned char handle_diacr(unsigned char);
  121.  
  122. /* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
  123. static struct pt_regs * pt_regs;
  124.  
  125. static int got_break = 0;
  126.  
  127. static inline void kb_wait(void)
  128. {
  129.     int i;
  130.  
  131.     for (i=0; i<0x10000; i++)
  132.         if ((inb_p(0x64) & 0x02) == 0)
  133.             break;
  134. }
  135.  
  136. static inline void send_cmd(unsigned char c)
  137. {
  138.     kb_wait();
  139.     outb(c,0x64);
  140. }
  141.  
  142. /*
  143.  * Translation of escaped scancodes to keysyms.
  144.  * This should be user-settable.
  145.  */
  146. #define E0_BASE 96
  147.  
  148. #define E0_KPENTER (E0_BASE+0)
  149. #define E0_RCTRL   (E0_BASE+1)
  150. #define E0_KPSLASH (E0_BASE+2)
  151. #define E0_PRSCR   (E0_BASE+3)
  152. #define E0_RALT    (E0_BASE+4)
  153. #define E0_BREAK   (E0_BASE+5)  /* (control-pause) */
  154. #define E0_HOME    (E0_BASE+6)
  155. #define E0_UP      (E0_BASE+7)
  156. #define E0_PGUP    (E0_BASE+8)
  157. #define E0_LEFT    (E0_BASE+9)
  158. #define E0_RIGHT   (E0_BASE+10)
  159. #define E0_END     (E0_BASE+11)
  160. #define E0_DOWN    (E0_BASE+12)
  161. #define E0_PGDN    (E0_BASE+13)
  162. #define E0_INS     (E0_BASE+14)
  163. #define E0_DEL     (E0_BASE+15)
  164. /* BTC */
  165. #define E0_MACRO   (E0_BASE+16)
  166. /* LK450 */
  167. #define E0_F13     (E0_BASE+17)
  168. #define E0_F14     (E0_BASE+18)
  169. #define E0_HELP    (E0_BASE+19)
  170. #define E0_DO      (E0_BASE+20)
  171. #define E0_F17     (E0_BASE+21)
  172. #define E0_KPMINPLUS (E0_BASE+22)
  173.  
  174. #define E1_PAUSE   (E0_BASE+23)
  175.  
  176. static unsigned char e0_keys[128] = {
  177.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x00-0x07 */
  178.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x08-0x0f */
  179.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x10-0x17 */
  180.   0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,          /* 0x18-0x1f */
  181.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x20-0x27 */
  182.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x28-0x2f */
  183.   0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,          /* 0x30-0x37 */
  184.   E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,          /* 0x38-0x3f */
  185.   E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,          /* 0x40-0x47 */
  186.   E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
  187.   E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,          /* 0x50-0x57 */
  188.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x58-0x5f */
  189.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x60-0x67 */
  190.   0, 0, 0, 0, 0, 0, 0, E0_MACRO,              /* 0x68-0x6f */
  191.   0, 0, 0, 0, 0, 0, 0, 0,                  /* 0x70-0x77 */
  192.   0, 0, 0, 0, 0, 0, 0, 0                  /* 0x78-0x7f */
  193. };
  194.  
  195. static void keyboard_interrupt(int int_pt_regs)
  196. {
  197.     unsigned char scancode;
  198.     static unsigned int prev_scancode = 0;   /* remember E0, E1 */
  199.     char up_flag;                         /* 0 or 0200 */
  200.     char raw_mode;
  201.  
  202.     pt_regs = (struct pt_regs *) int_pt_regs;
  203.     send_cmd(0xAD);        /* disable keyboard */
  204.     kb_wait();
  205.     if ((inb_p(0x64) & kbd_read_mask) != 0x01)
  206.         goto end_kbd_intr;
  207.     scancode = inb(0x60);
  208.     mark_bh(KEYBOARD_BH);
  209.     if (scancode == 0xfa) {
  210.         acknowledge = 1;
  211.         goto end_kbd_intr;
  212.     } else if (scancode == 0xfe) {
  213.         resend = 1;
  214.         goto end_kbd_intr;
  215.     } else if (scancode == 0) {
  216. #ifdef KBD_REPORT_ERR
  217.             printk("keyboard buffer overflow\n");
  218. #endif
  219.         goto end_kbd_intr;
  220.     } else if (scancode == 0xff) {
  221. #ifdef KBD_REPORT_ERR
  222.             printk("keyboard error\n");
  223. #endif
  224.             prev_scancode = 0;
  225.             goto end_kbd_intr;
  226.     }
  227.     tty = TTY_TABLE(0);
  228.      kbd = kbd_table + fg_console;
  229.     if ((raw_mode = vc_kbd_mode(kbd,VC_RAW))) {
  230.          put_queue(scancode);
  231.         /* we do not return yet, because we want to maintain
  232.            the key_down array, so that we have the correct
  233.            values when finishing RAW mode or when changing VT's */
  234.      }
  235.     if (scancode == 0xe0 || scancode == 0xe1) {
  236.         prev_scancode = scancode;
  237.         goto end_kbd_intr;
  238.      }
  239.  
  240.      /*
  241.      *  Convert scancode to keysym, using prev_scancode.
  242.       */
  243.     up_flag = (scancode & 0200);
  244.      scancode &= 0x7f;
  245.   
  246.     if (prev_scancode) {
  247.       /*
  248.        * usually it will be 0xe0, but a Pause key generates
  249.        * e1 1d 45 e1 9d c5 when pressed, and nothing when released
  250.        */
  251.       if (prev_scancode != 0xe0) {
  252.           if (prev_scancode == 0xe1 && scancode == 0x1d) {
  253.           prev_scancode = 0x100;
  254.           goto end_kbd_intr;
  255.           } else if (prev_scancode == 0x100 && scancode == 0x45) {
  256.           scancode = E1_PAUSE;
  257.           prev_scancode = 0;
  258.           } else {
  259.           printk("keyboard: unknown e1 escape sequence\n");
  260.           prev_scancode = 0;
  261.           goto end_kbd_intr;
  262.           }
  263.       } else {
  264.           prev_scancode = 0;
  265.           /*
  266.            *  The keyboard maintains its own internal caps lock and
  267.            *  num lock statuses. In caps lock mode E0 AA precedes make
  268.            *  code and E0 2A follows break code. In num lock mode,
  269.            *  E0 2A precedes make code and E0 AA follows break code.
  270.            *  We do our own book-keeping, so we will just ignore these.
  271.            */
  272.           /*
  273.            *  For my keyboard there is no caps lock mode, but there are
  274.            *  both Shift-L and Shift-R modes. The former mode generates
  275.            *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
  276.            *  So, we should also ignore the latter. - aeb@cwi.nl
  277.            */
  278.           if (scancode == 0x2a || scancode == 0x36)
  279.         goto end_kbd_intr;
  280.  
  281.           if (e0_keys[scancode])
  282.         scancode = e0_keys[scancode];
  283.           else if (!raw_mode) {
  284. #ifdef KBD_REPORT_UNKN
  285.           printk("keyboard: unknown scancode e0 %02x\n", scancode);
  286. #endif
  287.           goto end_kbd_intr;
  288.           }
  289.       }
  290.     } else if (scancode >= E0_BASE && !raw_mode) {
  291. #ifdef KBD_REPORT_UNKN
  292.       printk("keyboard: scancode (%02x) not in range 00 - %2x\n",
  293.          scancode, E0_BASE - 1);
  294. #endif
  295.       goto end_kbd_intr;
  296.      }
  297.   
  298.     /*
  299.      * At this point the variable `scancode' contains the keysym.
  300.      * We keep track of the up/down status of the key, and
  301.      * return the keysym if in MEDIUMRAW mode.
  302.      * (Note: earlier kernels had a bug and did not pass the up/down
  303.      * bit to applications.)
  304.      */
  305.  
  306.     if (up_flag) {
  307.          clear_bit(scancode, key_down);
  308.         rep = 0;
  309.     } else
  310.          rep = set_bit(scancode, key_down);
  311.   
  312.     if (raw_mode)
  313.             goto end_kbd_intr;
  314.  
  315.      if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
  316.          put_queue(scancode + up_flag);
  317.         goto end_kbd_intr;
  318.      }
  319.   
  320.      /*
  321.      * Small change in philosophy: earlier we defined repetition by
  322.      *     rep = scancode == prev_keysym;
  323.      *     prev_keysym = scancode;
  324.      * but now by the fact that the depressed key was down already.
  325.      * Does this ever make a difference?
  326.      */
  327.  
  328.     /*
  329.       *  Repeat a key only if the input buffers are empty or the
  330.       *  characters get echoed locally. This makes key repeat usable
  331.       *  with slow applications and under heavy loads.
  332.      */
  333.     if (!rep || 
  334.         (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
  335.          (L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q)))))
  336.     {
  337.         u_short key_code;
  338.         u_char type;
  339.  
  340.         /* the XOR below used to be an OR */
  341.         int shift_final = shift_state ^ kbd->lockstate;
  342.  
  343.         key_code = key_map[shift_final][scancode];
  344.         type = KTYP(key_code);
  345.  
  346.         if (type == KT_LETTER) {
  347.             type = KT_LATIN;
  348.             if (vc_kbd_led(kbd,VC_CAPSLOCK))
  349.             key_code = key_map[shift_final ^ (1<<KG_SHIFT)][scancode];
  350.         }
  351.         (*key_handler[type])(key_code & 0xff, up_flag);
  352.     }
  353.  
  354. end_kbd_intr:
  355.     send_cmd(0xAE);         /* enable keyboard */
  356. }
  357.  
  358. static void put_queue(int ch)
  359. {
  360.     struct tty_queue *qp;
  361.  
  362.     wake_up(&keypress_wait);
  363.     if (!tty)
  364.         return;
  365.     qp = &tty->read_q;
  366.  
  367.     if (LEFT(qp)) {
  368.         qp->buf[qp->head] = ch;
  369.         INC(qp->head);
  370.     }
  371. }
  372.  
  373. static void puts_queue(char *cp)
  374. {
  375.     struct tty_queue *qp;
  376.     char ch;
  377.  
  378.     /* why interruptible here, plain wake_up above? */
  379.     wake_up_interruptible(&keypress_wait);
  380.     if (!tty)
  381.         return;
  382.     qp = &tty->read_q;
  383.  
  384.     while ((ch = *(cp++)) != 0) {
  385.         if (LEFT(qp)) {
  386.             qp->buf[qp->head] = ch;
  387.             INC(qp->head);
  388.         }
  389.     }
  390. }
  391.  
  392. static void applkey(int key, char mode)
  393. {
  394.     static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
  395.  
  396.     buf[1] = (mode ? 'O' : '[');
  397.     buf[2] = key;
  398.     puts_queue(buf);
  399. }
  400.  
  401. static void enter(void)
  402. {
  403.     put_queue(13);
  404.     if (vc_kbd_mode(kbd,VC_CRLF))
  405.         put_queue(10);
  406. }
  407.  
  408. static void caps_toggle(void)
  409. {
  410.     if (rep)
  411.         return;
  412.     chg_vc_kbd_led(kbd,VC_CAPSLOCK);
  413. }
  414.  
  415. static void caps_on(void)
  416. {
  417.     if (rep)
  418.         return;
  419.     set_vc_kbd_led(kbd,VC_CAPSLOCK);
  420. }
  421.  
  422. static void show_ptregs(void)
  423. {
  424.     if (!pt_regs)
  425.         return;
  426.     printk("\n");
  427.     printk("EIP: %04x:%08lx",0xffff & pt_regs->cs,pt_regs->eip);
  428.     if (pt_regs->cs & 3)
  429.         printk(" ESP: %04x:%08lx",0xffff & pt_regs->ss,pt_regs->esp);
  430.     printk(" EFLAGS: %08lx\n",pt_regs->eflags);
  431.     printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
  432.         pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
  433.     printk("ESI: %08lx EDI: %08lx EBP: %08lx",
  434.         pt_regs->esi, pt_regs->edi, pt_regs->ebp);
  435.     printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
  436.         0xffff & pt_regs->ds,0xffff & pt_regs->es,
  437.         0xffff & pt_regs->fs,0xffff & pt_regs->gs);
  438. }
  439.  
  440. static void hold(void)
  441. {
  442.     if (rep || !tty)
  443.         return;
  444.  
  445.     /*
  446.      * Note: SCROLLOCK wil be set (cleared) by stop_tty (start_tty);
  447.      * these routines are also activated by ^S/^Q.
  448.      * (And SCROLLOCK can also be set by the ioctl KDSETLED.)
  449.      */
  450.     if (tty->stopped)
  451.         start_tty(tty);
  452.     else
  453.         stop_tty(tty);
  454. }
  455.  
  456. #if 0
  457. /* unused at present - and the VC_PAUSE bit is not used anywhere either */
  458. static void pause(void)
  459. {
  460.     chg_vc_kbd_mode(kbd,VC_PAUSE);
  461. }
  462. #endif
  463.  
  464. static void num(void)
  465. {
  466.     if (vc_kbd_mode(kbd,VC_APPLIC)) {
  467.         applkey('P', 1);
  468.         return;
  469.     }
  470.     if (!rep)    /* no autorepeat for numlock, ChN */
  471.         chg_vc_kbd_led(kbd,VC_NUMLOCK);
  472. }
  473.  
  474. static void lastcons(void)
  475. {
  476.     /* pressing alt-printscreen switches to the last used console, ChN */
  477.     want_console = last_console;
  478. }
  479.  
  480. static void send_intr(void)
  481. {
  482.     got_break = 1;
  483. }
  484.  
  485. static void scrll_forw(void)
  486. {
  487.     scrollfront(0);
  488. }
  489.  
  490. static void scrll_back(void)
  491. {
  492.     scrollback(0);
  493. }
  494.  
  495. static void boot_it(void)
  496. {
  497.     ctrl_alt_del();
  498. }
  499.  
  500. static void compose(void)
  501. {
  502.         dead_key_next = 1;
  503. }
  504.  
  505. static void do_spec(unsigned char value, char up_flag)
  506. {
  507.     typedef void (*fnp)(void);
  508.     fnp fn_table[] = {
  509.         NULL,        enter,        show_ptregs,    show_mem,
  510.         show_state,    send_intr,    lastcons,    caps_toggle,
  511.         num,        hold,        scrll_forw,    scrll_back,
  512.         boot_it,    caps_on,        compose
  513.     };
  514.  
  515.     if (up_flag)
  516.         return;
  517.     if (value >= SIZE(fn_table))
  518.         return;
  519.     if (!fn_table[value])
  520.         return;
  521.     fn_table[value]();
  522. }
  523.  
  524. static void do_lowercase(unsigned char value, char up_flag)
  525. {
  526.         printk("keyboard.c: do_lowercase was called - impossible\n");
  527. }
  528.   
  529. static void do_self(unsigned char value, char up_flag)
  530. {
  531.     if (up_flag)
  532.         return;        /* no action, if this is a key release */
  533.  
  534.         if (diacr)
  535.                 value = handle_diacr(value);
  536.  
  537.         if (dead_key_next) {
  538.                 dead_key_next = 0;
  539.                 diacr = value;
  540.                 return;
  541.         }
  542.  
  543.     put_queue(value);
  544. }
  545.  
  546. #define A_GRAVE  '`'
  547. #define A_ACUTE  '\''
  548. #define A_CFLEX  '^'
  549. #define A_TILDE  '~'
  550. #define A_DIAER  '"'
  551. static unsigned char ret_diacr[] =
  552.         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
  553.  
  554. /* If a dead key pressed twice, output a character corresponding to it,    */
  555. /* otherwise just remember the dead key.                */
  556.  
  557. static void do_dead(unsigned char value, char up_flag)
  558. {
  559.     if (up_flag)
  560.         return;
  561.  
  562.         value = ret_diacr[value];
  563.         if (diacr == value) {   /* pressed twice */
  564.                 diacr = 0;
  565.                 put_queue(value);
  566.                 return;
  567.         }
  568.     diacr = value;
  569. }
  570.  
  571.  
  572. /* If space is pressed, return the character corresponding the pending    */
  573. /* dead key, otherwise try to combine the two.                */
  574.  
  575. unsigned char handle_diacr(unsigned char ch)
  576. {
  577.         int d = diacr;
  578.         int i;
  579.  
  580.         diacr = 0;
  581.         if (ch == ' ')
  582.                 return d;
  583.  
  584.         for (i = 0; i < accent_table_size; i++)
  585.           if(accent_table[i].diacr == d && accent_table[i].base == ch)
  586.             return accent_table[i].result;
  587.  
  588.         put_queue(d);
  589.         return ch;
  590. }
  591.  
  592. static void do_cons(unsigned char value, char up_flag)
  593. {
  594.     if (up_flag)
  595.         return;
  596.     want_console = value;
  597. }
  598.  
  599. static void do_fn(unsigned char value, char up_flag)
  600. {
  601.     if (up_flag)
  602.         return;
  603.     if (value < SIZE(func_table))
  604.             puts_queue(func_table[value]);
  605.     else
  606.             printk("do_fn called with value=%d\n", value);
  607. }
  608.  
  609. static void do_pad(unsigned char value, char up_flag)
  610. {
  611.     static char *pad_chars = "0123456789+-*/\015,.?";
  612.     static char *app_map = "pqrstuvwxylSRQMnn?";
  613.  
  614.     if (up_flag)
  615.         return;        /* no action, if this is a key release */
  616.  
  617.     /* kludge... shift forces cursor/number keys */
  618.     if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
  619.         applkey(app_map[value], 1);
  620.         return;
  621.     }
  622.  
  623.     if (!vc_kbd_led(kbd,VC_NUMLOCK))
  624.         switch (value) {
  625.             case KVAL(K_PCOMMA):
  626.             case KVAL(K_PDOT):
  627.                 do_fn(KVAL(K_REMOVE), 0);
  628.                 return;
  629.             case KVAL(K_P0):
  630.                 do_fn(KVAL(K_INSERT), 0);
  631.                 return;
  632.             case KVAL(K_P1):
  633.                 do_fn(KVAL(K_SELECT), 0);
  634.                 return;
  635.             case KVAL(K_P2):
  636.                 do_cur(KVAL(K_DOWN), 0);
  637.                 return;
  638.             case KVAL(K_P3):
  639.                 do_fn(KVAL(K_PGDN), 0);
  640.                 return;
  641.             case KVAL(K_P4):
  642.                 do_cur(KVAL(K_LEFT), 0);
  643.                 return;
  644.             case KVAL(K_P6):
  645.                 do_cur(KVAL(K_RIGHT), 0);
  646.                 return;
  647.             case KVAL(K_P7):
  648.                 do_fn(KVAL(K_FIND), 0);
  649.                 return;
  650.             case KVAL(K_P8):
  651.                 do_cur(KVAL(K_UP), 0);
  652.                 return;
  653.             case KVAL(K_P9):
  654.                 do_fn(KVAL(K_PGUP), 0);
  655.                 return;
  656.             case KVAL(K_P5):
  657.                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
  658.                 return;
  659.         }
  660.  
  661.     put_queue(pad_chars[value]);
  662.     if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
  663.         put_queue(10);
  664. }
  665.  
  666. static void do_cur(unsigned char value, char up_flag)
  667. {
  668.     static char *cur_chars = "BDCA";
  669.     if (up_flag)
  670.         return;
  671.  
  672.     applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
  673. }
  674.  
  675. static void do_shift(unsigned char value, char up_flag)
  676. {
  677.     int old_state = shift_state;
  678.  
  679.     if (rep)
  680.         return;
  681.  
  682.     /* kludge... */
  683.     if (value == KVAL(K_CAPSSHIFT)) {
  684.         value = KVAL(K_SHIFT);
  685.         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
  686.     }
  687.  
  688.     if (up_flag) {
  689.             /* handle the case that two shift or control
  690.            keys are depressed simultaneously */
  691.         if (k_down[value])
  692.             k_down[value]--;
  693.     } else
  694.         k_down[value]++;
  695.  
  696.     if (k_down[value])
  697.         shift_state |= (1 << value);
  698.     else
  699.         shift_state &= ~ (1 << value);
  700.  
  701.     /* kludge */
  702.     if (up_flag && shift_state != old_state && npadch != -1) {
  703.         put_queue(npadch);
  704.         npadch = -1;
  705.     }
  706. }
  707.  
  708. /* called after returning from RAW mode or when changing consoles -
  709.    recompute k_down[] and shift_state from key_down[] */
  710. void compute_shiftstate(void)
  711. {
  712.         int i, j, k, sym, val;
  713.  
  714.         shift_state = 0;
  715.     for(i=0; i < SIZE(k_down); i++)
  716.       k_down[i] = 0;
  717.  
  718.     for(i=0; i < SIZE(key_down); i++)
  719.       if(key_down[i]) {    /* skip this word if not a single bit on */
  720.         k = (i<<5);
  721.         for(j=0; j<32; j++,k++)
  722.           if(test_bit(k, key_down)) {
  723.         sym = key_map[0][k];
  724.         if(KTYP(sym) == KT_SHIFT) {
  725.           val = KVAL(sym);
  726.           k_down[val]++;
  727.           shift_state |= (1<<val);
  728.             }
  729.           }
  730.       }
  731. }
  732.  
  733. static void do_meta(unsigned char value, char up_flag)
  734. {
  735.     if (up_flag)
  736.         return;
  737.  
  738.     if (vc_kbd_mode(kbd, VC_META)) {
  739.         put_queue('\033');
  740.         put_queue(value);
  741.     } else
  742.         put_queue(value | 0x80);
  743. }
  744.  
  745. static void do_ascii(unsigned char value, char up_flag)
  746. {
  747.     if (up_flag)
  748.         return;
  749.  
  750.     if (npadch == -1)
  751.             npadch = value;
  752.     else
  753.             npadch = (npadch * 10 + value) % 1000;
  754. }
  755.  
  756. static void do_lock(unsigned char value, char up_flag)
  757. {
  758.     if (up_flag || rep)
  759.         return;
  760.     chg_vc_kbd_lock(kbd, value);
  761. }
  762.  
  763. /*
  764.  * send_data sends a character to the keyboard and waits
  765.  * for a acknowledge, possibly retrying if asked to. Returns
  766.  * the success status.
  767.  */
  768. static int send_data(unsigned char data)
  769. {
  770.     int retries = 3;
  771.     int i;
  772.  
  773.     do {
  774.         kb_wait();
  775.         acknowledge = 0;
  776.         resend = 0;
  777.         outb_p(data, 0x60);
  778.         for(i=0; i<0x20000; i++) {
  779.             inb_p(0x64);        /* just as a delay */
  780.             if (acknowledge)
  781.                 return 1;
  782.             if (resend)
  783.                 break;
  784.         }
  785.         if (!resend)
  786.             return 0;
  787.     } while (retries-- > 0);
  788.     return 0;
  789. }
  790.  
  791. /*
  792.  * This routine is the bottom half of the keyboard interrupt
  793.  * routine, and runs with all interrupts enabled. It does
  794.  * console changing, led setting and copy_to_cooked, which can
  795.  * take a reasonably long time.
  796.  *
  797.  * Aside from timing (which isn't really that important for
  798.  * keyboard interrupts as they happen often), using the software
  799.  * interrupt routines for this thing allows us to easily mask
  800.  * this when we don't want any of the above to happen. Not yet
  801.  * used, but this allows for easy and efficient race-condition
  802.  * prevention later on.
  803.  */
  804. static void kbd_bh(void * unused)
  805. {
  806.     static unsigned char old_leds = 0xff;
  807.     unsigned char leds = kbd_table[fg_console].ledstate;
  808.  
  809.     if (leds != old_leds) {
  810.         old_leds = leds;
  811.         if (!send_data(0xed) || !send_data(leds))
  812.             send_data(0xf4);    /* re-enable kbd if any errors */
  813.     }
  814.     if (want_console >= 0) {
  815.         if (want_console != fg_console) {
  816.             last_console = fg_console;
  817.             change_console(want_console);
  818.         }
  819.         want_console = -1;
  820.     }
  821.     if (got_break) {
  822.         if (tty && !I_IGNBRK(tty)) {
  823.             if (I_BRKINT(tty)) {
  824.                 flush_input(tty);
  825.                 flush_output(tty);
  826.                 if (tty->pgrp > 0)
  827.                     kill_pg(tty->pgrp, SIGINT, 1);
  828.             } else {
  829.                 cli();
  830.                 if (LEFT(&tty->read_q) >= 2) {
  831.                     set_bit(tty->read_q.head,
  832.                         &tty->readq_flags);
  833.                     put_queue(TTY_BREAK);
  834.                     put_queue(0);
  835.                 }
  836.                 sti();
  837.             }
  838.         }
  839.         got_break = 0;
  840.     }
  841.     do_keyboard_interrupt();
  842.     cli();
  843.     if ((inb_p(0x64) & kbd_read_mask) == 0x01)
  844.         fake_keyboard_interrupt();
  845.     sti();
  846. }
  847.  
  848. long no_idt[2] = {0, 0};
  849.  
  850. /*
  851.  * This routine reboots the machine by asking the keyboard
  852.  * controller to pulse the reset-line low. We try that for a while,
  853.  * and if it doesn't work, we do some other stupid things.
  854.  */
  855. void hard_reset_now(void)
  856. {
  857.     int i, j;
  858.     extern unsigned long pg0[1024];
  859.  
  860.     sti();
  861. /* rebooting needs to touch the page at absolute addr 0 */
  862.     pg0[0] = 7;
  863.     *((unsigned short *)0x472) = 0x1234;
  864.     for (;;) {
  865.         for (i=0; i<100; i++) {
  866.             kb_wait();
  867.             for(j = 0; j < 100000 ; j++)
  868.                 /* nothing */;
  869.             outb(0xfe,0x64);     /* pulse reset low */
  870.         }
  871.         __asm__("\tlidt _no_idt");
  872.     }
  873. }
  874.  
  875. unsigned long kbd_init(unsigned long kmem_start)
  876. {
  877.     int i;
  878.     struct kbd_struct * kbd;
  879.  
  880.     kbd = kbd_table + 0;
  881.     for (i = 0 ; i < NR_CONSOLES ; i++,kbd++) {
  882.         kbd->ledstate = KBD_DEFLEDS;
  883.         kbd->default_ledstate = KBD_DEFLEDS;
  884.         kbd->lockstate = KBD_DEFLOCK;
  885.         kbd->modeflags = KBD_DEFMODE;
  886.     }
  887.  
  888.     bh_base[KEYBOARD_BH].routine = kbd_bh;
  889.     request_irq(KEYBOARD_IRQ,keyboard_interrupt);
  890.     mark_bh(KEYBOARD_BH);
  891.     return kmem_start;
  892. }
  893.