q40_keyb.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/char/q40_keyb.c
  3.  *
  4.  */
  5. #include <linux/config.h>
  6. #include <linux/spinlock.h>
  7. #include <linux/sched.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/tty.h>
  10. #include <linux/mm.h>
  11. #include <linux/keyboard.h>
  12. #include <linux/signal.h>
  13. #include <linux/ioport.h>
  14. #include <linux/init.h>
  15. #include <linux/kbd_ll.h>
  16. #include <linux/kbd_kern.h>
  17. #include <linux/delay.h>
  18. #include <linux/sysrq.h>
  19. #include <linux/random.h>
  20. #include <linux/poll.h>
  21. #include <linux/miscdevice.h>
  22. #include <linux/slab.h>
  23. #include <asm/keyboard.h>
  24. #include <asm/bitops.h>
  25. #include <asm/io.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/q40_master.h>
  28. #include <asm/irq.h>
  29. #include <asm/q40ints.h>
  30. /* Some configuration switches are present in the include file... */
  31. #define KBD_REPORT_ERR
  32. /* Simple translation table for the SysRq keys */
  33. #define SYSRQ_KEY 0x54
  34. #ifdef CONFIG_MAGIC_SYSRQ
  35. unsigned char q40kbd_sysrq_xlate[128] =
  36. "00331234567890-=177t" /* 0x00 - 0x0f */
  37. "qwertyuiop[]r00as" /* 0x10 - 0x1f */
  38. "dfghjkl;'`00\zxcv" /* 0x20 - 0x2f */
  39. "bnm,./00*00 00201202203204205" /* 0x30 - 0x3f */
  40. "2062072102112120000789-456+1" /* 0x40 - 0x4f */
  41. "230177000021321400000000000000000000" /* 0x50 - 0x5f */
  42. "r00/"; /* 0x60 - 0x6f */
  43. #endif
  44. /* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/
  45. /* 0x00 means not a valid entry or no conversion known                    */
  46. unsigned static char q40cl[256] =
  47. {/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
  48.  0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00,     /* 0x00 - 0x0f */
  49.  0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00,     /* 0x10 - 0x1f */
  50.  0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00,     /* 0x20 - 0x2f  'f' is at 0x2b, what is 0x28 ???*/
  51.  0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00,     /* 0x30 - 0x3f */
  52.  0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00,     /* 0x40 - 0x4f */
  53.  0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00,     /* 0x50 - 0x5f*/
  54.  0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f */
  55.  0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00,     /* 0x70 - 0x7f */
  56.  0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f  0x84/0x37 is SySrq*/
  57.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f */
  58.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf */
  59.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf */
  60.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf */
  61.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf */
  62.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef */
  63.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xf0 - 0xff */
  64. };
  65. /* another table, AT 0xe0 codes to PC 0xe0 codes, 
  66.    0xff special entry for SysRq - DROPPED right now  */
  67. static unsigned char q40ecl[]=
  68. {/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
  69.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x00 - 0x0f*/
  70.  0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x10 - 0x1f */
  71.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x20 - 0x2f*/
  72.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x30 - 0x3f*/
  73.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00,     /* 0x40 - 0x4f*/
  74.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,     /* 0x50 - 0x5f*/
  75.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f*/
  76.  0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00,     /* 0x70 - 0x7f*/
  77.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f*/
  78.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f*/
  79.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf*/
  80.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf*/
  81.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf*/
  82.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf*/
  83.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef*/
  84.  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00      /* 0xf0 - 0xff*/
  85. };
  86. static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
  87. /*
  88.  * Translation of escaped scancodes to keycodes.
  89.  * This is now user-settable.
  90.  * The keycodes 1-88,96-111,119 are fairly standard, and
  91.  * should probably not be changed - changing might confuse X.
  92.  * X also interprets scancode 0x5d (KEY_Begin).
  93.  *
  94.  * For 1-88 keycode equals scancode.
  95.  */
  96. #define E0_KPENTER 96
  97. #define E0_RCTRL   97
  98. #define E0_KPSLASH 98
  99. #define E0_PRSCR   99
  100. #define E0_RALT    100
  101. #define E0_BREAK   101  /* (control-pause) */
  102. #define E0_HOME    102
  103. #define E0_UP      103
  104. #define E0_PGUP    104
  105. #define E0_LEFT    105
  106. #define E0_RIGHT   106
  107. #define E0_END     107
  108. #define E0_DOWN    108
  109. #define E0_PGDN    109
  110. #define E0_INS     110
  111. #define E0_DEL     111
  112. #define E1_PAUSE   119
  113. /*
  114.  * The keycodes below are randomly located in 89-95,112-118,120-127.
  115.  * They could be thrown away (and all occurrences below replaced by 0),
  116.  * but that would force many users to use the `setkeycodes' utility, where
  117.  * they needed not before. It does not matter that there are duplicates, as
  118.  * long as no duplication occurs for any single keyboard.
  119.  */
  120. #define SC_LIM 89
  121. #define FOCUS_PF1 85           /* actual code! */
  122. #define FOCUS_PF2 89
  123. #define FOCUS_PF3 90
  124. #define FOCUS_PF4 91
  125. #define FOCUS_PF5 92
  126. #define FOCUS_PF6 93
  127. #define FOCUS_PF7 94
  128. #define FOCUS_PF8 95
  129. #define FOCUS_PF9 120
  130. #define FOCUS_PF10 121
  131. #define FOCUS_PF11 122
  132. #define FOCUS_PF12 123
  133. #define JAP_86     124
  134. /* tfj@olivia.ping.dk:
  135.  * The four keys are located over the numeric keypad, and are
  136.  * labelled A1-A4. It's an rc930 keyboard, from
  137.  * Regnecentralen/RC International, Now ICL.
  138.  * Scancodes: 59, 5a, 5b, 5c.
  139.  */
  140. #define RGN1 124
  141. #define RGN2 125
  142. #define RGN3 126
  143. #define RGN4 127
  144. static unsigned char high_keys[128 - SC_LIM] = {
  145.   RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
  146.   0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
  147.   0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
  148.   0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
  149.   FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
  150.   FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
  151. };
  152. /* BTC */
  153. #define E0_MACRO   112
  154. /* LK450 */
  155. #define E0_F13     113
  156. #define E0_F14     114
  157. #define E0_HELP    115
  158. #define E0_DO      116
  159. #define E0_F17     117
  160. #define E0_KPMINPLUS 118
  161. /*
  162.  * My OmniKey generates e0 4c for  the "OMNI" key and the
  163.  * right alt key does nada. [kkoller@nyx10.cs.du.edu]
  164.  */
  165. #define E0_OK 124
  166. /*
  167.  * New microsoft keyboard is rumoured to have
  168.  * e0 5b (left window button), e0 5c (right window button),
  169.  * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
  170.  * [or: Windows_L, Windows_R, TaskMan]
  171.  */
  172. #define E0_MSLW 125
  173. #define E0_MSRW 126
  174. #define E0_MSTM 127
  175. /* this can be changed using setkeys : */
  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, E0_OK, 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, E0_MSLW, E0_MSRW, E0_MSTM, 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. static unsigned int prev_scancode = 0;   /* remember E0, E1 */
  195. int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  196. {
  197. if (scancode < SC_LIM || scancode > 255 || keycode > 127)
  198.   return -EINVAL;
  199. if (scancode < 128)
  200.   high_keys[scancode - SC_LIM] = keycode;
  201. else
  202.   e0_keys[scancode - 128] = keycode;
  203. return 0;
  204. }
  205. int q40kbd_getkeycode(unsigned int scancode)
  206. {
  207. return
  208.   (scancode < SC_LIM || scancode > 255) ? -EINVAL :
  209.   (scancode < 128) ? high_keys[scancode - SC_LIM] :
  210.     e0_keys[scancode - 128];
  211. }
  212. #define disable_keyboard()
  213. #define enable_keyboard()
  214. int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
  215.     char raw_mode)
  216. {
  217.    if (scancode == 0xe0 || scancode == 0xe1) {
  218. prev_scancode = scancode;
  219. return 0;
  220.   }
  221. if (prev_scancode) {
  222.   /*
  223.    * usually it will be 0xe0, but a Pause key generates
  224.    * e1 1d 45 e1 9d c5 when pressed, and nothing when released
  225.    */
  226.   if (prev_scancode != 0xe0) {
  227.       if (prev_scancode == 0xe1 && scancode == 0x1d) {
  228.   prev_scancode = 0x100;
  229.   return 0;
  230.       } else if (prev_scancode == 0x100 && scancode == 0x45) {
  231.   *keycode = E1_PAUSE;
  232.   prev_scancode = 0;
  233.       } else {
  234. #ifdef KBD_REPORT_UNKN
  235.   if (!raw_mode)
  236.     printk(KERN_INFO "keyboard: unknown e1 escape sequencen");
  237. #endif
  238.   prev_scancode = 0;
  239.   return 0;
  240.       }
  241.   } else {
  242.       prev_scancode = 0;
  243.       /*
  244.        *  The keyboard maintains its own internal caps lock and
  245.        *  num lock statuses. In caps lock mode E0 AA precedes make
  246.        *  code and E0 2A follows break code. In num lock mode,
  247.        *  E0 2A precedes make code and E0 AA follows break code.
  248.        *  We do our own book-keeping, so we will just ignore these.
  249.        */
  250.       /*
  251.        *  For my keyboard there is no caps lock mode, but there are
  252.        *  both Shift-L and Shift-R modes. The former mode generates
  253.        *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
  254.        *  So, we should also ignore the latter. - aeb@cwi.nl
  255.        */
  256.       if (scancode == 0x2a || scancode == 0x36)
  257. return 0;
  258.       if (e0_keys[scancode])
  259. *keycode = e0_keys[scancode];
  260.       else {
  261. #ifdef KBD_REPORT_UNKN
  262.   if (!raw_mode)
  263.     printk(KERN_INFO "keyboard: unknown scancode e0 %02xn",
  264.    scancode);
  265. #endif
  266.   return 0;
  267.       }
  268.   }
  269. } else if (scancode >= SC_LIM) {
  270.     /* This happens with the FOCUS 9000 keyboard
  271.        Its keys PF1..PF12 are reported to generate
  272.        55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
  273.        Moreover, unless repeated, they do not generate
  274.        key-down events, so we have to zero up_flag below */
  275.     /* Also, Japanese 86/106 keyboards are reported to
  276.        generate 0x73 and 0x7d for  - and  | respectively. */
  277.     /* Also, some Brazilian keyboard is reported to produce
  278.        0x73 and 0x7e for  ? and KP-dot, respectively. */
  279.   *keycode = high_keys[scancode - SC_LIM];
  280.   if (!*keycode) {
  281.       if (!raw_mode) {
  282. #ifdef KBD_REPORT_UNKN
  283.   printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
  284.  " - ignoredn", scancode);
  285. #endif
  286.       }
  287.       return 0;
  288.   }
  289.   } else
  290.   *keycode = scancode;
  291.   return 1;
  292. }
  293. char q40kbd_unexpected_up(unsigned char keycode)
  294. {
  295. /* unexpected, but this can happen: maybe this was a key release for a
  296.    FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
  297. if (keycode >= SC_LIM || keycode == 85)
  298.     return 0;
  299. else
  300.     return 0200;
  301. }
  302. static int keyup=0;
  303. static int qprev=0;
  304. static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  305. {
  306. unsigned char status;
  307. spin_lock(&kbd_controller_lock);
  308. kbd_pt_regs = regs;
  309. status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
  310. if (status ) 
  311.   {
  312.     unsigned char scancode,qcode;
  313.     
  314.     qcode = master_inb(KEYCODE_REG);
  315.     
  316.     if (qcode != 0xf0)
  317.       {
  318. if (qcode == 0xe0)
  319.   {
  320.     qprev=0xe0;
  321.     handle_scancode(qprev , 1);
  322.     goto exit;
  323.   }
  324. scancode=qprev ? q40ecl[qcode] : q40cl[qcode];
  325. #if 0
  326. /* next line is last resort to hanlde some oddities */
  327. if (qprev && !scancode) scancode=q40cl[qcode];
  328. #endif
  329. qprev=0;
  330. if (!scancode)
  331.   {
  332.     printk("unknown scancode %xn",qcode);
  333.     goto exit;
  334.   }
  335. if (scancode==0xff)  /* SySrq */
  336.   scancode=SYSRQ_KEY;
  337. handle_scancode(scancode, ! keyup );
  338. keyup=0;
  339. tasklet_schedule(&keyboard_tasklet);
  340.       }
  341.     else
  342.       keyup=1;
  343.   }
  344. exit:
  345. spin_unlock(&kbd_controller_lock);
  346. master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
  347. }
  348. #define KBD_NO_DATA (-1) /* No data */
  349. #define KBD_BAD_DATA (-2) /* Parity or other error */
  350. static int __init kbd_read_input(void)
  351. {
  352. int retval = KBD_NO_DATA;
  353. unsigned char status;
  354. status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
  355. if (status) {
  356. unsigned char data = master_inb(KEYCODE_REG);
  357. retval = data;
  358. master_outb(-1,KEYBOARD_UNLOCK_REG);
  359. }
  360. return retval;
  361. }
  362. extern void q40kbd_leds(unsigned char leds)
  363. { /* nothing can be done */ }
  364. static void __init kbd_clear_input(void)
  365. {
  366. int maxread = 100; /* Random number */
  367. do {
  368. if (kbd_read_input() == KBD_NO_DATA)
  369. break;
  370. } while (--maxread);
  371. }
  372. void __init q40kbd_init_hw(void)
  373. {
  374. #if 0
  375. /* Get the keyboard controller registers (incomplete decode) */
  376. request_region(0x60, 16, "keyboard");
  377. #endif
  378. /* Flush any pending input. */
  379. kbd_clear_input();
  380. /* Ok, finally allocate the IRQ, and off we go.. */
  381. request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL);
  382. master_outb(-1,KEYBOARD_UNLOCK_REG);
  383. master_outb(1,KEY_IRQ_ENABLE_REG);
  384. }