lk201.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

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.  * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
  8.  * Copyright (C) 2001, 2002  Maciej W. Rozycki <macro@ds2.pg.gda.pl>
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/errno.h>
  12. #include <linux/sched.h>
  13. #include <linux/tty.h>
  14. #include <linux/kernel.h>
  15. #include <linux/init.h>
  16. #include <linux/delay.h>
  17. #include <linux/kbd_ll.h>
  18. #include <linux/kbd_kern.h>
  19. #include <linux/vt_kern.h>
  20. #include <asm/keyboard.h>
  21. #include <asm/dec/tc.h>
  22. #include <asm/dec/machtype.h>
  23. #include "zs.h"
  24. #include "lk201.h"
  25. /* Simple translation table for the SysRq keys */
  26. #ifdef CONFIG_MAGIC_SYSRQ
  27. /*
  28.  * Actually no translation at all, at least until we figure out
  29.  * how to define SysRq for LK201 and friends. --macro
  30.  */
  31. unsigned char lk201_sysrq_xlate[128];
  32. unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
  33. unsigned char kbd_sysrq_key = -1;
  34. #endif
  35. #define KEYB_LINE 3
  36. static int __init lk201_init(struct dec_serial *);
  37. static void __init lk201_info(struct dec_serial *);
  38. static void lk201_kbd_rx_char(unsigned char, unsigned char);
  39. struct zs_hook lk201_kbdhook = {
  40. init_channel: lk201_init,
  41. init_info: lk201_info,
  42. rx_char: NULL,
  43. poll_rx_char: NULL,
  44. poll_tx_char: NULL,
  45. cflags: B4800 | CS8 | CSTOPB | CLOCAL
  46. };
  47. /*
  48.  * This is used during keyboard initialisation
  49.  */
  50. static unsigned char lk201_reset_string[] = {
  51. LK_CMD_SET_DEFAULTS,
  52. LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
  53. LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
  54. LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
  55. LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
  56. LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
  57. LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
  58. LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
  59. LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
  60. LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
  61. LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
  62. LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
  63. LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
  64. LK_CMD_MODE(LK_MODE_DOWN, 13),
  65. LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
  66. LK_CMD_DIS_KEYCLK,
  67. LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
  68. };
  69. static struct dec_serial* lk201kbd_info;
  70. static int lk201_send(struct dec_serial *info, unsigned char ch)
  71. {
  72. if (info->hook->poll_tx_char(info, ch)) {
  73. printk(KERN_ERR "lk201: transmit timeoutn");
  74. return -EIO;
  75. }
  76. return 0;
  77. }
  78. static inline int lk201_get_id(struct dec_serial *info)
  79. {
  80. return lk201_send(info, LK_CMD_REQ_ID);
  81. }
  82. static int lk201_reset(struct dec_serial *info)
  83. {
  84. int i, r;
  85. for (i = 0; i < sizeof(lk201_reset_string); i++) {
  86. r = lk201_send(info, lk201_reset_string[i]);
  87. if (r < 0)
  88. return r;
  89. }
  90. return 0;
  91. }
  92. static void lk201_report(unsigned char id[6])
  93. {
  94. char *report = "lk201: keyboard attached, ";
  95. switch (id[2]) {
  96. case LK_STAT_PWRUP_OK:
  97. printk(KERN_INFO "%sself-test OKn", report);
  98. break;
  99. case LK_STAT_PWRUP_KDOWN:
  100. /* The keyboard will resend the power-up ID
  101.    after all keys are released, so we don't
  102.    bother handling the error specially.  Still
  103.    there may be a short-circuit inside.
  104.  */
  105. printk(KERN_ERR "%skey down (stuck?), code: 0x%02xn",
  106.        report, id[3]);
  107. break;
  108. case LK_STAT_PWRUP_ERROR:
  109. printk(KERN_ERR "%sself-test failuren", report);
  110. break;
  111. default:
  112. printk(KERN_ERR "%sunknown error: 0x%02xn",
  113.        report, id[2]);
  114. }
  115. }
  116. static void lk201_id(unsigned char id[6])
  117. {
  118. /*
  119.  * Report whether there is an LK201 or an LK401
  120.  * The LK401 has ALT keys...
  121.  */
  122. switch (id[4]) {
  123. case 1:
  124. printk(KERN_INFO "lk201: LK201 detectedn");
  125. break;
  126. case 2:
  127. printk(KERN_INFO "lk201: LK401 detectedn");
  128. break;
  129. default:
  130. printk(KERN_WARNING
  131.        "lk201: unknown keyboard detected, ID %dn", id[4]);
  132. printk(KERN_WARNING "lk201: ... please report to "
  133.        "<linux-mips@oss.sgi.com>n");
  134. }
  135. }
  136. #define DEFAULT_KEYB_REP_DELAY (250/5) /* [5ms] */
  137. #define DEFAULT_KEYB_REP_RATE 30 /* [cps] */
  138. static struct kbd_repeat kbdrate = {
  139. DEFAULT_KEYB_REP_DELAY,
  140. DEFAULT_KEYB_REP_RATE
  141. };
  142. static void parse_kbd_rate(struct kbd_repeat *r)
  143. {
  144. if (r->delay <= 0)
  145. r->delay = kbdrate.delay;
  146. if (r->rate <= 0)
  147. r->rate = kbdrate.rate;
  148. if (r->delay < 5)
  149. r->delay = 5;
  150. if (r->delay > 630)
  151. r->delay = 630;
  152. if (r->rate < 12)
  153. r->rate = 12;
  154. if (r->rate > 127)
  155. r->rate = 127;
  156. if (r->rate == 125)
  157. r->rate = 124;
  158. }
  159. static int write_kbd_rate(struct kbd_repeat *rep)
  160. {
  161. struct dec_serial* info = lk201kbd_info;
  162. int delay, rate;
  163. int i;
  164. delay = rep->delay / 5;
  165. rate = rep->rate;
  166. for (i = 0; i < 4; i++) {
  167. if (info->hook->poll_tx_char(info, LK_CMD_RPT_RATE(i)))
  168. return 1;
  169. if (info->hook->poll_tx_char(info, LK_PARAM_DELAY(delay)))
  170. return 1;
  171. if (info->hook->poll_tx_char(info, LK_PARAM_RATE(rate)))
  172. return 1;
  173. }
  174. return 0;
  175. }
  176. static int lk201kbd_rate(struct kbd_repeat *rep)
  177. {
  178. if (rep == NULL)
  179. return -EINVAL;
  180. parse_kbd_rate(rep);
  181. if (write_kbd_rate(rep)) {
  182. memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
  183. return -EIO;
  184. }
  185. memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
  186. return 0;
  187. }
  188. static void lk201kd_mksound(unsigned int hz, unsigned int ticks)
  189. {
  190. struct dec_serial* info = lk201kbd_info;
  191. if (!ticks)
  192. return;
  193. /*
  194.  * Can't set frequency and we "approximate"
  195.  * duration by volume. ;-)
  196.  */
  197. ticks /= HZ / 32;
  198. if (ticks > 7)
  199. ticks = 7;
  200. ticks = 7 - ticks;
  201. if (info->hook->poll_tx_char(info, LK_CMD_ENB_BELL))
  202. return;
  203. if (info->hook->poll_tx_char(info, LK_PARAM_VOLUME(ticks)))
  204. return;
  205. if (info->hook->poll_tx_char(info, LK_CMD_BELL))
  206. return;
  207. }
  208. void kbd_leds(unsigned char leds)
  209. {
  210. struct dec_serial* info = lk201kbd_info;
  211. unsigned char l = 0;
  212. if (!info) /* FIXME */
  213. return;
  214. /* FIXME -- Only Hold and Lock LEDs for now. --macro */
  215. if (leds & LED_SCR)
  216. l |= LK_LED_HOLD;
  217. if (leds & LED_CAP)
  218. l |= LK_LED_LOCK;
  219. if (info->hook->poll_tx_char(info, LK_CMD_LEDS_ON))
  220. return;
  221. if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(l)))
  222. return;
  223. if (info->hook->poll_tx_char(info, LK_CMD_LEDS_OFF))
  224. return;
  225. if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(~l)))
  226. return;
  227. }
  228. int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  229. {
  230. return -EINVAL;
  231. }
  232. int kbd_getkeycode(unsigned int scancode)
  233. {
  234. return -EINVAL;
  235. }
  236. int kbd_translate(unsigned char scancode, unsigned char *keycode,
  237.   char raw_mode)
  238. {
  239. *keycode = scancode;
  240. return 1;
  241. }
  242. char kbd_unexpected_up(unsigned char keycode)
  243. {
  244. return 0x80;
  245. }
  246. static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
  247. {
  248. static unsigned char id[6];
  249. static int id_i;
  250. static int shift_state = 0;
  251. static int prev_scancode;
  252. unsigned char c = scancodeRemap[ch];
  253. if (stat && stat != 4) {
  254. printk(KERN_ERR "lk201: keyboard receive error: 0x%02xn",
  255.        stat);
  256. return;
  257. }
  258. /* Assume this is a power-up ID. */
  259. if (ch == LK_STAT_PWRUP_ID && !id_i) {
  260. id[id_i++] = ch;
  261. return;
  262. }
  263. /* Handle the power-up sequence. */
  264. if (id_i) {
  265. id[id_i++] = ch;
  266. if (id_i == 4) {
  267. /* OK, the power-up concluded. */
  268. lk201_report(id);
  269. if (id[2] == LK_STAT_PWRUP_OK)
  270. lk201_get_id(lk201kbd_info);
  271. else {
  272. id_i = 0;
  273. printk(KERN_ERR "lk201: keyboard power-up "
  274.        "error, skipping initializationn");
  275. }
  276. } else if (id_i == 6) {
  277. /* We got the ID; report it and start an operation. */
  278. id_i = 0;
  279. lk201_id(id);
  280. lk201_reset(lk201kbd_info);
  281. }
  282. return;
  283. }
  284. /* Everything else is a scancode/status response. */
  285. id_i = 0;
  286. switch (ch) {
  287. case LK_STAT_RESUME_ERR:
  288. case LK_STAT_ERROR:
  289. case LK_STAT_INHIBIT_ACK:
  290. case LK_STAT_TEST_ACK:
  291. case LK_STAT_MODE_KEYDOWN:
  292. case LK_STAT_MODE_ACK:
  293. break;
  294. case LK_KEY_LOCK:
  295. shift_state ^= LK_LOCK;
  296. handle_scancode(c, shift_state && LK_LOCK ? 1 : 0);
  297. break;
  298. case LK_KEY_SHIFT:
  299. shift_state ^= LK_SHIFT;
  300. handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0);
  301. break;
  302. case LK_KEY_CTRL:
  303. shift_state ^= LK_CTRL;
  304. handle_scancode(c, shift_state && LK_CTRL ? 1 : 0);
  305. break;
  306. case LK_KEY_COMP:
  307. shift_state ^= LK_COMP;
  308. handle_scancode(c, shift_state && LK_COMP ? 1 : 0);
  309. break;
  310. case LK_KEY_RELEASE:
  311. if (shift_state & LK_SHIFT)
  312. handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
  313. if (shift_state & LK_CTRL)
  314. handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
  315. if (shift_state & LK_COMP)
  316. handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
  317. if (shift_state & LK_LOCK)
  318. handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
  319. shift_state = 0;
  320. break;
  321. case LK_KEY_REPEAT:
  322. handle_scancode(prev_scancode, 1);
  323. break;
  324. default:
  325. prev_scancode = c;
  326. handle_scancode(c, 1);
  327. break;
  328. }
  329. tasklet_schedule(&keyboard_tasklet);
  330. }
  331. static void __init lk201_info(struct dec_serial *info)
  332. {
  333. }
  334. static int __init lk201_init(struct dec_serial *info)
  335. {
  336. /* First install handlers. */
  337. lk201kbd_info = info;
  338. kbd_rate = lk201kbd_rate;
  339. kd_mksound = lk201kd_mksound;
  340. info->hook->rx_char = lk201_kbd_rx_char;
  341. /* Then just issue a reset -- the handlers will do the rest. */
  342. lk201_send(info, LK_CMD_POWER_UP);
  343. return 0;
  344. }
  345. void __init kbd_init_hw(void)
  346. {
  347. extern int register_zs_hook(unsigned int, struct zs_hook *);
  348. extern int unregister_zs_hook(unsigned int);
  349. /* Maxine uses LK501 at the Access.Bus. */
  350. if (mips_machtype == MACH_DS5000_XX)
  351. return;
  352. printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.n");
  353. if (TURBOCHANNEL) {
  354. /*
  355.  * kbd_init_hw() is being called before
  356.  * rs_init() so just register the kbd hook
  357.  * and let zs_init do the rest :-)
  358.  */
  359. if (mips_machtype == MACH_DS5000_200)
  360. printk(KERN_ERR "lk201: support for DS5000/200 "
  361.        "not yet ready.n");
  362. else
  363. if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
  364. unregister_zs_hook(KEYB_LINE);
  365. } else {
  366. /*
  367.  * TODO: modify dz.c to allow similar hooks
  368.  * for LK201 handling on DS2100, DS3100, and DS5000/200
  369.  */
  370. printk(KERN_ERR "lk201: support for DS3100 not yet ready.n");
  371. }
  372. }