1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/config.h>
17#include <linux/sched.h>
18#include <linux/interrupt.h>
19#include <linux/tty.h>
20#include <linux/tty_flip.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/ptrace.h>
24#include <linux/signal.h>
25#include <linux/timer.h>
26#include <linux/random.h>
27#include <linux/ctype.h>
28#include <linux/init.h>
29#include <linux/kbd_ll.h>
30#include <linux/kbd_kern.h>
31#include <linux/delay.h>
32
33#include <asm/bitops.h>
34#include <asm/keyboard.h>
35#include <asm/irq.h>
36#include <asm/hardware.h>
37#include <asm/hardware/ioc.h>
38
39#include "../../char/busmouse.h"
40
41extern struct tasklet_struct keyboard_tasklet;
42extern void kbd_reset_kdown(void);
43
44#define VERSION 108
45
46#define KBD_REPORT_ERR
47#define KBD_REPORT_UNKN
48
49#include <asm/io.h>
50#include <asm/system.h>
51
52static char kbd_txval[4];
53static unsigned char kbd_txhead, kbd_txtail;
54#define KBD_INCTXPTR(ptr) ((ptr) = ((ptr) + 1) & 3)
55static int kbd_id = -1;
56static DECLARE_WAIT_QUEUE_HEAD(kbd_waitq);
57#ifdef CONFIG_KBDMOUSE
58static int mousedev;
59#endif
60
61
62
63
64#define HRST 0xff
65#define RAK1 0xfe
66#define RAK2 0xfd
67#define BACK 0x3f
68#define SMAK 0x33
69#define MACK 0x32
70#define SACK 0x31
71#define NACK 0x30
72#define RQMP 0x22
73#define PRST 0x21
74#define RQID 0x20
75
76#define UP_FLAG 1
77
78#ifdef CONFIG_MAGIC_SYSRQ
79unsigned char a5kkbd_sysrq_xlate[] =
80{
81 27, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0,
83 '`', '1', '2', '3', '4', '5', '6', '7',
84 '8', '9', '0', '-', '=', '£', 127, 0,
85 0, 0, 0, '/', '*', '#', 9, 'q',
86 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
87 'p', '[', ']', '\\', 22, 23, 25, '7',
88 '8', '9', '-', 0, 'a', 's', 'd', 'f',
89 'g', 'h', 'j', 'k', 'l', ';', '\'', 13,
90 '4', '5', '6', '+', 0, 0, 'z', 'x',
91 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
92 0, 0, '1', '2', '3', 0, 0, ' ',
93 0, 0, 0, 0, 0, '0', '.', 10,
94 0, 0, 0, 0, 0, 0, 0, 0,
95 0, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0,
97};
98#endif
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115static unsigned char scancode_2_colrow[256] = {
116 0x01, 0x42, 0x32, 0x33, 0x43, 0x56, 0x5a, 0x6c, 0x7c, 0x5c, 0x5b, 0x6b, 0x7b, 0x84, 0x70, 0x60,
117 0x11, 0x51, 0x62, 0x63, 0x44, 0x54, 0x55, 0x45, 0x46, 0x4a, 0x3c, 0x4b, 0x59, 0x49, 0x69, 0x79,
118 0x83, 0x40, 0x30, 0x3b, 0x39, 0x38, 0x31, 0x61, 0x72, 0x73, 0x64, 0x74, 0x75, 0x65, 0x66, 0x6a,
119 0x1c, 0x2c, 0x7a, 0x36, 0x48, 0x68, 0x78, 0x20, 0x2b, 0x29, 0x28, 0x81, 0x71, 0x22, 0x23, 0x34,
120 0x24, 0x25, 0x35, 0x26, 0x3a, 0x0c, 0x2a, 0x76, 0x10, 0x1b, 0x19, 0x18, 0x82, 0xff, 0x21, 0x12,
121 0x13, 0x14, 0x04, 0x05, 0x15, 0x16, 0x1a, 0x0a, 0x85, 0x77, 0x00, 0x0b, 0x09, 0x02, 0x80, 0x03,
122 0x87, 0x86, 0x06, 0x17, 0x27, 0x07, 0x37, 0x08, 0xff,
123};
124
125#define BITS_PER_SHORT (8*sizeof(unsigned short))
126static unsigned short ghost_down[128/BITS_PER_SHORT];
127
128static void a5kkbd_key(unsigned int keycode, unsigned int up_flag)
129{
130 unsigned int real_keycode;
131
132 if (keycode > 0x72) {
133#ifdef KBD_REPORT_UNKN
134 printk ("kbd: unknown scancode 0x%04x\n", keycode);
135#endif
136 return;
137 }
138 if (keycode >= 0x70) {
139#ifdef CONFIG_KBDMOUSE
140 if (mousedev >= 0)
141 switch (keycode) {
142 case 0x70:
143 busmouse_add_buttons(mousedev, 4, up_flag ? 4 : 0);
144 break;
145
146 case 0x71:
147 busmouse_add_buttons(mousedev, 2, up_flag ? 2 : 0);
148 break;
149
150 case 0x72:
151 busmouse_add_buttons(mousedev, 1, up_flag ? 1 : 0);
152 break;
153 }
154#endif
155 return;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 real_keycode = scancode_2_colrow[keycode];
178
179 if ((real_keycode & 0x80) == 0) {
180 int rr, kc = (real_keycode >> 4) & 7;
181 int cc;
182 unsigned short res, kdownkc;
183
184 kdownkc = ghost_down[kc] | (1 << (real_keycode & 15));
185
186 for (rr = 0; rr < 128/BITS_PER_SHORT; rr++)
187 if (rr != kc && (res = ghost_down[rr] & kdownkc)) {
188
189
190
191
192 for (cc = 0; res; res >>= 1)
193 cc += (res & 1);
194 if (cc > 1)
195 return;
196 }
197 if (up_flag)
198 clear_bit (real_keycode, ghost_down);
199 else
200 set_bit (real_keycode, ghost_down);
201 }
202
203 handle_scancode(keycode, !up_flag);
204}
205
206static inline void a5kkbd_sendbyte(unsigned char val)
207{
208 kbd_txval[kbd_txhead] = val;
209 KBD_INCTXPTR(kbd_txhead);
210 enable_irq(IRQ_KEYBOARDTX);
211}
212
213static inline void a5kkbd_reset(void)
214{
215 int i;
216
217 for (i = 0; i < NR_SCANCODES/BITS_PER_SHORT; i++)
218 ghost_down[i] = 0;
219
220 kbd_reset_kdown();
221}
222
223void a5kkbd_leds(unsigned char leds)
224{
225 leds = ((leds & (1<<VC_SCROLLOCK))?4:0) | ((leds & (1<<VC_NUMLOCK))?2:0) |
226 ((leds & (1<<VC_CAPSLOCK))?1:0);
227 a5kkbd_sendbyte(leds);
228}
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243#define KBD_INITRST 0
244#define KBD_RAK1 1
245#define KBD_RAK2 2
246#define KBD_ID 3
247#define KBD_IDLE 4
248#define KBD_KEYDOWN 5
249#define KBD_KEYUP 6
250#define KBD_MOUSE 7
251
252static int handle_rawcode(unsigned int keyval)
253{
254 static signed char kbd_mousedx = 0;
255 signed char kbd_mousedy;
256 static unsigned char kbd_state = KBD_INITRST;
257 static unsigned char kbd_keyhigh = 0;
258
259 if (keyval == HRST && kbd_state != KBD_INITRST && kbd_state != KBD_ID) {
260 a5kkbd_sendbyte (HRST);
261 a5kkbd_reset ();
262 kbd_state = KBD_INITRST;
263 } else switch(kbd_state) {
264 case KBD_INITRST:
265 if (keyval == HRST) {
266 a5kkbd_sendbyte (RAK1);
267 kbd_state = KBD_RAK1;
268 } else if (keyval == RAK1) {
269
270
271
272
273
274 printk(KERN_DEBUG "keyboard sent early RAK1 -- ignored\n");
275 } else
276 goto kbd_wontreset;
277 break;
278
279 case KBD_RAK1:
280 if (keyval == RAK1) {
281 a5kkbd_sendbyte (RAK2);
282 kbd_state = KBD_RAK2;
283 } else
284 goto kbd_wontreset;
285 break;
286
287 case KBD_RAK2:
288 if (keyval == RAK2) {
289 if (kbd_id == -1) {
290 a5kkbd_sendbyte (NACK);
291 a5kkbd_sendbyte (RQID);
292 kbd_state = KBD_ID;
293 } else {
294 a5kkbd_sendbyte (SMAK);
295 kbd_state = KBD_IDLE;
296 }
297 } else
298 goto kbd_wontreset;
299 break;
300
301 case KBD_ID:
302 if (keyval == HRST) {
303 kbd_id = -2;
304 a5kkbd_reset ();
305 a5kkbd_sendbyte (HRST);
306 kbd_state = KBD_INITRST;
307 wake_up (&kbd_waitq);
308 } else if ((keyval & 0xc0) == 0x80) {
309 kbd_id = keyval & 0x3f;
310 a5kkbd_sendbyte (SMAK);
311 kbd_state = KBD_IDLE;
312 wake_up (&kbd_waitq);
313 }
314 break;
315
316 case KBD_IDLE:
317 switch (keyval & 0xf0) {
318 default:
319 kbd_mousedx = keyval & 0x40 ? keyval|0x80 : keyval;
320 kbd_state = KBD_MOUSE;
321 a5kkbd_sendbyte (BACK);
322 break;
323
324 case 0x80:
325 case 0x90:
326 case 0xa0:
327 case 0xb0:
328 if (kbd_id == -1)
329 kbd_id = keyval & 0x3f;
330 break;
331
332 case 0xc0:
333 kbd_keyhigh = keyval;
334 kbd_state = KBD_KEYDOWN;
335 a5kkbd_sendbyte (BACK);
336 break;
337
338 case 0xd0:
339 kbd_keyhigh = keyval;
340 kbd_state = KBD_KEYUP;
341 a5kkbd_sendbyte (BACK);
342 break;
343
344 case 0xe0:
345 case 0xf0:
346 goto kbd_error;
347 }
348 break;
349
350 case KBD_KEYDOWN:
351 if ((keyval & 0xf0) != 0xc0)
352 goto kbd_error;
353 else {
354 kbd_state = KBD_IDLE;
355 a5kkbd_sendbyte (SMAK);
356 if (((kbd_keyhigh ^ keyval) & 0xf0) == 0)
357 a5kkbd_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), 0);
358 }
359 break;
360
361 case KBD_KEYUP:
362 if ((keyval & 0xf0) != 0xd0)
363 goto kbd_error;
364 else {
365 kbd_state = KBD_IDLE;
366 a5kkbd_sendbyte (SMAK);
367 if (((kbd_keyhigh ^ keyval) & 0xf0) == 0)
368 a5kkbd_key ((keyval & 0x0f) | ((kbd_keyhigh << 4) & 0xf0), UP_FLAG);
369 }
370 break;
371
372 case KBD_MOUSE:
373 if (keyval & 0x80)
374 goto kbd_error;
375 else {
376 kbd_state = KBD_IDLE;
377 a5kkbd_sendbyte (SMAK);
378 kbd_mousedy = (char)(keyval & 0x40 ? keyval | 0x80 : keyval);
379#ifdef CONFIG_KBDMOUSE
380 if (mousedev >= 0)
381 busmouse_add_movement(mousedev, (int)kbd_mousedx, (int)kbd_mousedy);
382#endif
383 }
384 }
385 return kbd_state == KBD_IDLE ? 1 : 0;
386
387kbd_wontreset:
388#ifdef KBD_REPORT_ERR
389 printk ("kbd: keyboard won't reset (kbdstate %d, keyval %02X)\n",
390 kbd_state, keyval);
391#endif
392 mdelay(1);
393 ioc_readb(IOC_KARTRX);
394 a5kkbd_sendbyte (HRST);
395 kbd_state = KBD_INITRST;
396 return 0;
397
398kbd_error:
399#ifdef KBD_REPORT_ERR
400 printk ("kbd: keyboard out of sync - resetting\n");
401#endif
402 a5kkbd_sendbyte (HRST);
403 kbd_state = KBD_INITRST;
404 return 0;
405}
406
407static void a5kkbd_rx(int irq, void *dev_id, struct pt_regs *regs)
408{
409 kbd_pt_regs = regs;
410 if (handle_rawcode(ioc_readb(IOC_KARTRX)))
411 tasklet_schedule(&keyboard_tasklet);
412}
413
414static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs)
415{
416 ioc_writeb (kbd_txval[kbd_txtail], IOC_KARTTX);
417 KBD_INCTXPTR(kbd_txtail);
418 if (kbd_txtail == kbd_txhead)
419 disable_irq(irq);
420}
421
422static int a5kkbd_setkeycode(unsigned int scancode, unsigned int keycode)
423{
424 return -EINVAL;
425}
426
427static int a5kkbd_getkeycode(unsigned int scancode)
428{
429 return -EINVAL;
430}
431
432static int a5kkbd_translate(unsigned char scancode, unsigned char *keycode, char rawmode)
433{
434 *keycode = scancode;
435 return 1;
436}
437
438static char a5kkbd_unexpected_up(unsigned char keycode)
439{
440 return 0200;
441}
442
443static int a5kkbd_rate(struct kbd_repeat *rep)
444{
445 return -EINVAL;
446}
447
448#ifdef CONFIG_KBDMOUSE
449static struct busmouse a5kkbd_mouse = {
450 6, "kbdmouse", NULL, NULL, NULL, 7
451};
452#endif
453
454struct kbd_ops_struct a5k_kbd_ops = {
455 k_setkeycode: a5kkbd_setkeycode,
456 k_getkeycode: a5kkbd_getkeycode,
457 k_translate: a5kkbd_translate,
458 k_unexpected_up: a5kkbd_unexpected_up,
459 k_leds: a5kkbd_leds,
460 k_rate: a5kkbd_rate,
461#ifdef CONFIG_MAGIC_SYSRQ
462 k_sysrq_xlate: a5kkbd_sysrq_xlate,
463 k_sysrq_key: 13,
464#endif
465};
466
467void __init a5kkbd_init_hw (void)
468{
469 if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0)
470 panic("Could not allocate keyboard transmit IRQ!");
471 (void)ioc_readb(IOC_KARTRX);
472 if (request_irq (IRQ_KEYBOARDRX, a5kkbd_rx, 0, "keyboard", NULL) != 0)
473 panic("Could not allocate keyboard receive IRQ!");
474
475 a5kkbd_sendbyte (HRST);
476
477
478 interruptible_sleep_on_timeout(&kbd_waitq, HZ);
479
480#ifdef CONFIG_KBDMOUSE
481 mousedev = register_busmouse(&a5kkbd_mouse);
482 if (mousedev < 0)
483 printk(KERN_ERR "Unable to register mouse driver\n");
484#endif
485
486 printk (KERN_INFO "Keyboard driver v%d.%02d. (", VERSION/100, VERSION%100);
487 if (kbd_id != -1)
488 printk ("id=%d ", kbd_id);
489 printk ("English)\n");
490}
491