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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  */
  8. #include <linux/errno.h>
  9. #include <linux/tty.h>
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/delay.h>
  13. #include <linux/kbd_ll.h>
  14. #include <asm/wbflush.h>
  15. #include <asm/dec/tc.h>
  16. #include <asm/dec/machtype.h>
  17. #include "zs.h"
  18. #include "lk201.h"
  19. /* Simple translation table for the SysRq keys */
  20. #ifdef CONFIG_MAGIC_SYSRQ
  21. /*
  22.  * Actually no translation at all, at least until we figure out
  23.  * how to define SysRq for LK201 and friends. --macro
  24.  */
  25. unsigned char lk201_sysrq_xlate[128];
  26. unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
  27. #endif
  28. #define KEYB_LINE 3
  29. static int __init lk201_init(struct dec_serial *);
  30. static void __init lk201_info(struct dec_serial *);
  31. static void lk201_kbd_rx_char(unsigned char, unsigned char);
  32. struct zs_hook lk201_kbdhook = {
  33. init_channel:   lk201_init,
  34. init_info:      lk201_info,
  35. rx_char:        NULL,
  36. poll_rx_char:   NULL,
  37. poll_tx_char:   NULL,
  38. cflags:         B4800 | CS8 | CSTOPB | CLOCAL
  39. };
  40. /*
  41.  * This is used during keyboard initialisation
  42.  */
  43. static unsigned char lk201_reset_string[] = {
  44. LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */
  45. LK_CMD_SET_DEFAULTS,
  46. LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
  47. LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
  48. LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
  49. LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
  50. LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
  51. LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
  52. LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
  53. LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
  54. LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
  55. LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
  56. LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
  57. LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
  58. LK_CMD_MODE(LK_MODE_DOWN, 13),
  59. LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
  60. LK_CMD_ENB_RPT,
  61. LK_CMD_DIS_KEYCLK,
  62. LK_CMD_RESUME,
  63. LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
  64. LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
  65. };
  66. static int __init lk201_reset(struct dec_serial *info)
  67. {
  68. int i;
  69. for (i = 0; i < sizeof(lk201_reset_string); i++)
  70. if (info->hook->poll_tx_char(info, lk201_reset_string[i])) {
  71. printk(__FUNCTION__" transmit timeoutn");
  72. return -EIO;
  73. }
  74. return 0;
  75. }
  76. void kbd_leds(unsigned char leds)
  77. {
  78. return;
  79. }
  80. int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  81. {
  82. return -EINVAL;
  83. }
  84. int kbd_getkeycode(unsigned int scancode)
  85. {
  86. return -EINVAL;
  87. }
  88. int kbd_translate(unsigned char scancode, unsigned char *keycode,
  89.   char raw_mode)
  90. {
  91. *keycode = scancode;
  92. return 1;
  93. }
  94. char kbd_unexpected_up(unsigned char keycode)
  95. {
  96. return 0x80;
  97. }
  98. static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
  99. {
  100. static int shift_state = 0;
  101. static int prev_scancode;
  102. unsigned char c = scancodeRemap[ch];
  103. if (!stat || stat == 4) {
  104. switch (ch) {
  105. case LK_KEY_ACK:
  106. break;
  107. case LK_KEY_LOCK:
  108. shift_state ^= LK_LOCK;
  109. handle_scancode(c, shift_state && LK_LOCK ? 1 : 0);
  110. break;
  111. case LK_KEY_SHIFT:
  112. shift_state ^= LK_SHIFT;
  113. handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0);
  114. break;
  115. case LK_KEY_CTRL:
  116. shift_state ^= LK_CTRL;
  117. handle_scancode(c, shift_state && LK_CTRL ? 1 : 0);
  118. break;
  119. case LK_KEY_COMP:
  120. shift_state ^= LK_COMP;
  121. handle_scancode(c, shift_state && LK_COMP ? 1 : 0);
  122. break;
  123. case LK_KEY_RELEASE:
  124. if (shift_state & LK_SHIFT)
  125. handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
  126. if (shift_state & LK_CTRL)
  127. handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
  128. if (shift_state & LK_COMP)
  129. handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
  130. if (shift_state & LK_LOCK)
  131. handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
  132. shift_state = 0;
  133. break;
  134. case LK_KEY_REPEAT:
  135. handle_scancode(prev_scancode, 1);
  136. break;
  137. default:
  138. prev_scancode = c;
  139. handle_scancode(c, 1);
  140. break;
  141. }
  142. } else
  143. printk("Error reading LKx01 keyboard: 0x%02xn", stat);
  144. }
  145. static void __init lk201_info(struct dec_serial *info)
  146. {
  147. }
  148. static int __init lk201_init(struct dec_serial *info)
  149. {
  150. unsigned int ch, id = 0;
  151. int result;
  152. printk("DECstation LK keyboard driver v0.04... ");
  153. result = lk201_reset(info);
  154. if (result)
  155. return result;
  156. mdelay(10);
  157. /*
  158.  * Detect whether there is an LK201 or an LK401
  159.  * The LK401 has ALT keys...
  160.  */
  161. info->hook->poll_tx_char(info, LK_CMD_REQ_ID);
  162. while ((ch = info->hook->poll_rx_char(info)) > 0)
  163. id = ch;
  164. switch (id) {
  165. case 1:
  166. printk("LK201 detectedn");
  167. break;
  168. case 2:
  169. printk("LK401 detectedn");
  170. break;
  171. default:
  172. printk("unknown keyboard, ID %d,n", id);
  173. printk("... please report to <linux-mips@oss.sgi.com>n");
  174. }
  175. /*
  176.  * now we're ready
  177.  */
  178. info->hook->rx_char = lk201_kbd_rx_char;
  179. return 0;
  180. }
  181. void __init kbd_init_hw(void)
  182. {
  183. extern int register_zs_hook(unsigned int, struct zs_hook *);
  184. extern int unregister_zs_hook(unsigned int);
  185. if (TURBOCHANNEL) {
  186. if (mips_machtype != MACH_DS5000_XX) {
  187. /*
  188.  * This is not a MAXINE, so:
  189.  *
  190.  * kbd_init_hw() is being called before
  191.  * rs_init() so just register the kbd hook
  192.  * and let zs_init do the rest :-)
  193.  */
  194. if (mips_machtype == MACH_DS5000_200)
  195. printk("LK201 Support for DS5000/200 not yet ready ...n");
  196. else
  197. if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
  198. unregister_zs_hook(KEYB_LINE);
  199. }
  200. } else {
  201. /*
  202.  * TODO: modify dz.c to allow similar hooks
  203.  * for LK201 handling on DS2100, DS3100, and DS5000/200
  204.  */
  205. printk("LK201 Support for DS3100 not yet ready ...n");
  206. }
  207. }