1 /*
2 * linux/drivers/acorn/char/keyb_arc.c
3 *
4 * Copyright (C) 2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Acorn keyboard driver for ARM Linux.
11 *
12 * The Acorn keyboard appears to have a ***very*** buggy reset protocol -
13 * every reset behaves differently. We try to get round this by attempting
14 * a few things...
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
41 extern struct tasklet_struct keyboard_tasklet;
42 extern 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
52 static char kbd_txval[4];
53 static unsigned char kbd_txhead, kbd_txtail;
54 #define KBD_INCTXPTR(ptr) ((ptr) = ((ptr) + 1) & 3)
55 static int kbd_id = -1;
56 static DECLARE_WAIT_QUEUE_HEAD(kbd_waitq);
57 #ifdef CONFIG_KBDMOUSE
58 static int mousedev;
59 #endif
60
61 /*
62 * Protocol codes to send the keyboard.
63 */
64 #define HRST 0xff /* reset keyboard */
65 #define RAK1 0xfe /* reset response */
66 #define RAK2 0xfd /* reset response */
67 #define BACK 0x3f /* Ack for first keyboard pair */
68 #define SMAK 0x33 /* Last data byte ack (key scanning + mouse movement scanning) */
69 #define MACK 0x32 /* Last data byte ack (mouse movement scanning) */
70 #define SACK 0x31 /* Last data byte ack (key scanning) */
71 #define NACK 0x30 /* Last data byte ack (no scanning, mouse data) */
72 #define RQMP 0x22 /* Request mouse data */
73 #define PRST 0x21 /* nothing */
74 #define RQID 0x20 /* Request ID */
75
76 #define UP_FLAG 1
77
78 #ifdef CONFIG_MAGIC_SYSRQ
79 unsigned 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 * This array converts the scancode that we get from the keyboard to the
102 * real rows/columns on the A5000 keyboard. This might be keyboard specific...
103 *
104 * It is these values that we use to maintain the key down array. That way, we
105 * should pick up on the ghost key presses (which is what happens when you press
106 * three keys, and the keyboard thinks you have pressed four!)
107 *
108 * Row 8 (0x80+c) is actually a column with one key per row. It is isolated from
109 * the other keys, and can't cause these problems (its used for shift, ctrl, alt etc).
110 *
111 * Illegal scancodes are denoted by an 0xff (in other words, we don't know about
112 * them, and can't process them for ghosts). This does however, cause problems with
113 * autorepeat processing...
114 */
115 static 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))
126 static unsigned short ghost_down[128/BITS_PER_SHORT];
127
a5kkbd_key(unsigned int keycode,unsigned int up_flag)128 static 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: /* Left mouse button */
143 busmouse_add_buttons(mousedev, 4, up_flag ? 4 : 0);
144 break;
145
146 case 0x71: /* Middle mouse button */
147 busmouse_add_buttons(mousedev, 2, up_flag ? 2 : 0);
148 break;
149
150 case 0x72:/* Right mouse button */
151 busmouse_add_buttons(mousedev, 1, up_flag ? 1 : 0);
152 break;
153 }
154 #endif
155 return;
156 }
157
158 /*
159 * We have to work out if we accept this key press as a real key, or
160 * if it is a ghost. IE. If you press three keys, the keyboard will think
161 * that you've pressed a fourth: (@ = key down, # = ghost)
162 *
163 * 0 1 2 3 4 5 6 7
164 * | | | | | | | |
165 * 0-+-+-+-+-+-+-+-+-
166 * | | | | | | | |
167 * 1-+-@-+-+-+-@-+-+-
168 * | | | | | | | |
169 * 2-+-+-+-+-+-+-+-+-
170 * | | | | | | | |
171 * 3-+-@-+-+-+-#-+-+-
172 * | | | | | | | |
173 *
174 * This is what happens when you have a matrix keyboard...
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 * we have found a second row with at least one key pressed in the
190 * same column.
191 */
192 for (cc = 0; res; res >>= 1)
193 cc += (res & 1);
194 if (cc > 1)
195 return; /* ignore it */
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
a5kkbd_sendbyte(unsigned char val)206 static 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
a5kkbd_reset(void)213 static 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
a5kkbd_leds(unsigned char leds)223 void 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 /* Keyboard states:
231 * 0 initial reset condition, receive HRST, send RRAK1
232 * 1 Sent RAK1, wait for RAK1, send RRAK2
233 * 2 Sent RAK2, wait for RAK2, send SMAK or RQID
234 * 3 Sent RQID, expect KBID, send SMAK
235 * 4 Sent SMAK, wait for anything
236 * 5 Wait for second keyboard nibble for key pressed
237 * 6 Wait for second keyboard nibble for key released
238 * 7 Wait for second part of mouse data
239 *
240 * This function returns 1 when we successfully enter the IDLE state
241 * (and hence need to do some keyboard processing).
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
handle_rawcode(unsigned int keyval)252 static 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: /* hard reset - sent HRST */
265 if (keyval == HRST) {
266 a5kkbd_sendbyte (RAK1);
267 kbd_state = KBD_RAK1;
268 } else if (keyval == RAK1) {
269 /* Some A5000 keyboards are very fussy and don't follow Acorn's
270 * specs - this appears to fix them, but them it might stop
271 * them from being initialised.
272 * fix by Philip Blundell
273 */
274 printk(KERN_DEBUG "keyboard sent early RAK1 -- ignored\n");
275 } else
276 goto kbd_wontreset;
277 break;
278
279 case KBD_RAK1: /* sent RAK1 - expect RAK1 and send RAK2 */
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: /* Sent RAK2 - expect RAK2 and send either RQID or SMAK */
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: /* Sent RQID - expect KBID */
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: /* Send SMAK, ready for any reply */
317 switch (keyval & 0xf0) {
318 default: /* 0x00 - 0x7f */
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
387 kbd_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
398 kbd_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
a5kkbd_rx(int irq,void * dev_id,struct pt_regs * regs)407 static 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
a5kkbd_tx(int irq,void * dev_id,struct pt_regs * regs)414 static 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
a5kkbd_setkeycode(unsigned int scancode,unsigned int keycode)422 static int a5kkbd_setkeycode(unsigned int scancode, unsigned int keycode)
423 {
424 return -EINVAL;
425 }
426
a5kkbd_getkeycode(unsigned int scancode)427 static int a5kkbd_getkeycode(unsigned int scancode)
428 {
429 return -EINVAL;
430 }
431
a5kkbd_translate(unsigned char scancode,unsigned char * keycode,char rawmode)432 static int a5kkbd_translate(unsigned char scancode, unsigned char *keycode, char rawmode)
433 {
434 *keycode = scancode;
435 return 1;
436 }
437
a5kkbd_unexpected_up(unsigned char keycode)438 static char a5kkbd_unexpected_up(unsigned char keycode)
439 {
440 return 0200;
441 }
442
a5kkbd_rate(struct kbd_repeat * rep)443 static int a5kkbd_rate(struct kbd_repeat *rep)
444 {
445 return -EINVAL;
446 }
447
448 #ifdef CONFIG_KBDMOUSE
449 static struct busmouse a5kkbd_mouse = {
450 6, "kbdmouse", NULL, NULL, NULL, 7
451 };
452 #endif
453
454 struct 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
a5kkbd_init_hw(void)467 void __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); /* send HRST (expect HRST) */
476
477 /* wait 1s for keyboard to initialise */
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