MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / tc / lk201.c
blobbfd602a6514b64a0f7ada482cd946e2a57333342
1 /*
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.
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>
18 #include "zs.h"
19 #include "lk201.h"
21 /* Simple translation table for the SysRq keys */
23 #ifdef CONFIG_MAGIC_SYSRQ
25 * Actually no translation at all, at least until we figure out
26 * how to define SysRq for LK201 and friends. --macro
28 unsigned char lk201_sysrq_xlate[128];
29 unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
30 #endif
32 #define KEYB_LINE 3
34 static int __init lk201_init(struct dec_serial *);
35 static void __init lk201_info(struct dec_serial *);
36 static void lk201_kbd_rx_char(unsigned char, unsigned char);
38 struct zs_hook lk201_kbdhook = {
39 .init_channel = lk201_init,
40 .init_info = lk201_info,
41 .cflags = B4800 | CS8 | CSTOPB | CLOCAL
45 * This is used during keyboard initialisation
47 static unsigned char lk201_reset_string[] = {
48 LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */
49 LK_CMD_SET_DEFAULTS,
50 LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
51 LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
52 LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
53 LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
54 LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
55 LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
56 LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
57 LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
58 LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
59 LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
60 LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
61 LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
62 LK_CMD_MODE(LK_MODE_DOWN, 13),
63 LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
64 LK_CMD_ENB_RPT,
65 LK_CMD_DIS_KEYCLK,
66 LK_CMD_RESUME,
67 LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
68 LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
71 static int __init lk201_reset(struct dec_serial *info)
73 int i;
75 for (i = 0; i < sizeof(lk201_reset_string); i++)
76 if (info->hook->poll_tx_char(info, lk201_reset_string[i])) {
77 printk("%s transmit timeout\n", __FUNCTION__);
78 return -EIO;
80 return 0;
83 void kbd_leds(unsigned char leds)
85 return;
88 int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
90 return -EINVAL;
93 int kbd_getkeycode(unsigned int scancode)
95 return -EINVAL;
98 int kbd_translate(unsigned char scancode, unsigned char *keycode,
99 char raw_mode)
101 *keycode = scancode;
102 return 1;
105 char kbd_unexpected_up(unsigned char keycode)
107 return 0x80;
110 static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
112 static int shift_state = 0;
113 static int prev_scancode;
114 unsigned char c = scancodeRemap[ch];
116 if (!stat || stat == 4) {
117 switch (ch) {
118 case LK_KEY_ACK:
119 break;
120 case LK_KEY_LOCK:
121 shift_state ^= LK_LOCK;
122 handle_scancode(c, shift_state && LK_LOCK ? 1 : 0);
123 break;
124 case LK_KEY_SHIFT:
125 shift_state ^= LK_SHIFT;
126 handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0);
127 break;
128 case LK_KEY_CTRL:
129 shift_state ^= LK_CTRL;
130 handle_scancode(c, shift_state && LK_CTRL ? 1 : 0);
131 break;
132 case LK_KEY_COMP:
133 shift_state ^= LK_COMP;
134 handle_scancode(c, shift_state && LK_COMP ? 1 : 0);
135 break;
136 case LK_KEY_RELEASE:
137 if (shift_state & LK_SHIFT)
138 handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
139 if (shift_state & LK_CTRL)
140 handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
141 if (shift_state & LK_COMP)
142 handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
143 if (shift_state & LK_LOCK)
144 handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
145 shift_state = 0;
146 break;
147 case LK_KEY_REPEAT:
148 handle_scancode(prev_scancode, 1);
149 break;
150 default:
151 prev_scancode = c;
152 handle_scancode(c, 1);
153 break;
155 } else
156 printk("Error reading LKx01 keyboard: 0x%02x\n", stat);
159 static void __init lk201_info(struct dec_serial *info)
163 static int __init lk201_init(struct dec_serial *info)
165 unsigned int ch, id = 0;
166 int result;
168 printk("DECstation LK keyboard driver v0.04... ");
170 result = lk201_reset(info);
171 if (result)
172 return result;
173 mdelay(10);
176 * Detect whether there is an LK201 or an LK401
177 * The LK401 has ALT keys...
179 info->hook->poll_tx_char(info, LK_CMD_REQ_ID);
180 while ((ch = info->hook->poll_rx_char(info)) > 0)
181 id = ch;
183 switch (id) {
184 case 1:
185 printk("LK201 detected\n");
186 break;
187 case 2:
188 printk("LK401 detected\n");
189 break;
190 default:
191 printk("unknown keyboard, ID %d,\n", id);
192 printk("... please report to <linux-mips@oss.sgi.com>\n");
196 * now we're ready
198 info->hook->rx_char = lk201_kbd_rx_char;
200 return 0;
203 void __init kbd_init_hw(void)
205 extern int register_zs_hook(unsigned int, struct zs_hook *);
206 extern int unregister_zs_hook(unsigned int);
208 if (TURBOCHANNEL) {
209 if (mips_machtype != MACH_DS5000_XX) {
211 * This is not a MAXINE, so:
213 * kbd_init_hw() is being called before
214 * rs_init() so just register the kbd hook
215 * and let zs_init do the rest :-)
217 if (mips_machtype == MACH_DS5000_200)
218 printk("LK201 Support for DS5000/200 not yet ready ...\n");
219 else
220 if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
221 unregister_zs_hook(KEYB_LINE);
223 } else {
225 * TODO: modify dz.c to allow similar hooks
226 * for LK201 handling on DS2100, DS3100, and DS5000/200
228 printk("LK201 Support for DS3100 not yet ready ...\n");