File: /usr/src/linux/drivers/acorn/char/keyb_arc.c

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     
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     
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     
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     
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     
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     
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     
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     
422     #ifdef CONFIG_KBDMOUSE
423     static struct busmouse a5kkbd_mouse = {
424     	6, "kbdmouse", NULL, NULL, NULL, 7
425     };
426     #endif
427     
428     void __init a5kkbd_init_hw (void)
429     {
430     	if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0)
431     		panic("Could not allocate keyboard transmit IRQ!");
432     	(void)ioc_readb(IOC_KARTRX);
433     	if (request_irq (IRQ_KEYBOARDRX, a5kkbd_rx, 0, "keyboard", NULL) != 0)
434     		panic("Could not allocate keyboard receive IRQ!");
435     
436     	a5kkbd_sendbyte (HRST);	/* send HRST (expect HRST) */
437     
438     	/* wait 1s for keyboard to initialise */
439     	interruptible_sleep_on_timeout(&kbd_waitq, HZ);
440     
441     #ifdef CONFIG_KBDMOUSE
442     	mousedev = register_busmouse(&a5kkbd_mouse);
443     	if (mousedev < 0)
444     		printk(KERN_ERR "Unable to register mouse driver\n");
445     #endif
446     
447     	printk (KERN_INFO "Keyboard driver v%d.%02d. (", VERSION/100, VERSION%100);
448     	if (kbd_id != -1)
449     	      printk ("id=%d ", kbd_id);
450     	printk ("English)\n");
451     }
452