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

1     /*
2      *  linux/drivers/acorn/char/keyb_ps2.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      *  Keyboard driver for RiscPC ARM Linux.
11      *
12      *  Note!!! This driver talks directly to the keyboard.
13      */
14     #include <linux/config.h>
15     #include <linux/sched.h>
16     #include <linux/interrupt.h>
17     #include <linux/tty.h>
18     #include <linux/tty_flip.h>
19     #include <linux/mm.h>
20     #include <linux/slab.h>
21     #include <linux/ptrace.h>
22     #include <linux/signal.h>
23     #include <linux/timer.h>
24     #include <linux/random.h>
25     #include <linux/ctype.h>
26     #include <linux/kbd_ll.h>
27     #include <linux/delay.h>
28     #include <linux/init.h>
29     
30     #include <asm/bitops.h>
31     #include <asm/irq.h>
32     #include <asm/hardware.h>
33     #include <asm/io.h>
34     #include <asm/hardware/iomd.h>
35     #include <asm/system.h>
36     
37     extern struct tasklet_struct keyboard_tasklet;
38     extern void kbd_reset_kdown(void);
39     int kbd_read_mask;
40     
41     #define TX_DONE 0
42     #define TX_SENT 1
43     #define TX_SEND 2
44     
45     static volatile int tx_state;
46     
47     #define VERSION 100
48     
49     #define KBD_REPORT_ERR
50     #define KBD_REPORT_UNKN
51     
52     #define KBD_ESCAPEE0	0xe0		/* in */
53     #define KBD_ESCAPEE1	0xe1		/* in */
54     
55     #define ESCE0(x)	(0xe000|(x))
56     #define ESCE1(x)	(0xe100|(x))
57     
58     #define KBD_BAT		0xaa		/* in */
59     #define KBD_SETLEDS	0xed		/* out */
60     #define KBD_ECHO	0xee		/* in/out */
61     #define KBD_BREAK	0xf0		/* in */
62     #define KBD_TYPRATEDLY	0xf3		/* out */
63     #define KBD_SCANENABLE	0xf4		/* out */
64     #define KBD_DEFDISABLE	0xf5		/* out */
65     #define KBD_DEFAULT	0xf6		/* out */
66     #define KBD_ACK		0xfa		/* in */
67     #define KBD_DIAGFAIL	0xfd		/* in */
68     #define KBD_RESEND	0xfe		/* in/out */
69     #define KBD_RESET	0xff		/* out */
70     
71     #define CODE_BREAK	1
72     #define CODE_ESCAPEE0	2
73     #define CODE_ESCAPEE1	4
74     #define CODE_ESCAPE12	8
75     
76     #define K_NONE		0x7f
77     #define K_ESC		0x00
78     #define K_F1		0x01
79     #define K_F2		0x02
80     #define K_F3		0x03
81     #define K_F4		0x04
82     #define K_F5		0x05
83     #define K_F6		0x06
84     #define K_F7		0x07
85     #define K_F8		0x08
86     #define K_F9		0x09
87     #define K_F10		0x0a
88     #define K_F11		0x0b
89     #define K_F12		0x0c
90     #define K_PRNT		0x0d
91     #define K_SCRL		0x0e
92     #define K_BRK		0x0f
93     #define K_AGR		0x10
94     #define K_1		0x11
95     #define K_2		0x12
96     #define K_3		0x13
97     #define K_4		0x14
98     #define K_5		0x15
99     #define K_6		0x16
100     #define K_7		0x17
101     #define K_8		0x18
102     #define K_9		0x19
103     #define K_0		0x1a
104     #define K_MINS		0x1b
105     #define K_EQLS		0x1c
106     #define K_BKSP		0x1e
107     #define K_INS		0x1f
108     #define K_HOME		0x20
109     #define K_PGUP		0x21
110     #define K_NUML		0x22
111     #define KP_SLH		0x23
112     #define KP_STR		0x24
113     #define KP_MNS		0x3a
114     #define K_TAB		0x26
115     #define K_Q		0x27
116     #define K_W		0x28
117     #define K_E		0x29
118     #define K_R		0x2a
119     #define K_T		0x2b
120     #define K_Y		0x2c
121     #define K_U		0x2d
122     #define K_I		0x2e
123     #define K_O		0x2f
124     #define K_P		0x30
125     #define K_LSBK		0x31
126     #define K_RSBK		0x32
127     #define K_ENTR		0x47
128     #define K_DEL		0x34
129     #define K_END		0x35
130     #define K_PGDN		0x36
131     #define KP_7		0x37
132     #define KP_8		0x38
133     #define KP_9		0x39
134     #define KP_PLS		0x4b
135     #define K_CAPS		0x5d
136     #define K_A		0x3c
137     #define K_S		0x3d
138     #define K_D		0x3e
139     #define K_F		0x3f
140     #define K_G		0x40
141     #define K_H		0x41
142     #define K_J		0x42
143     #define K_K		0x43
144     #define K_L		0x44
145     #define K_SEMI		0x45
146     #define K_SQOT		0x46
147     #define K_HASH		0x1d
148     #define KP_4		0x48
149     #define KP_5		0x49
150     #define KP_6		0x4a
151     #define K_LSFT		0x4c
152     #define K_BSLH		0x33
153     #define K_Z		0x4e
154     #define K_X		0x4f
155     #define K_C		0x50
156     #define K_V		0x51
157     #define K_B		0x52
158     #define K_N		0x53
159     #define K_M		0x54
160     #define K_COMA		0x55
161     #define K_DOT		0x56
162     #define K_FSLH		0x57
163     #define K_RSFT		0x58
164     #define K_UP		0x59
165     #define KP_1		0x5a
166     #define KP_2		0x5b
167     #define KP_3		0x5c
168     #define KP_ENT		0x67
169     #define K_LCTL		0x3b
170     #define K_LALT		0x5e
171     #define K_SPCE		0x5f
172     #define K_RALT		0x60
173     #define K_RCTL		0x61
174     #define K_LEFT		0x62
175     #define K_DOWN		0x63
176     #define K_RGHT		0x64
177     #define KP_0		0x65
178     #define KP_DOT		0x66
179     
180     static unsigned char keycode_translate[256] =
181     {
182     /* 00 */  K_NONE, K_F9  , K_NONE, K_F5  , K_F3  , K_F1  , K_F2  , K_F12 ,
183     /* 08 */  K_NONE, K_F10 , K_F8  , K_F6  , K_F4  , K_TAB , K_AGR , K_NONE,
184     /* 10 */  K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q   , K_1   , K_NONE,
185     /* 18 */  K_NONE, K_NONE, K_Z   , K_S   , K_A   , K_W   , K_2   , K_NONE,
186     /* 20 */  K_NONE, K_C   , K_X   , K_D   , K_E   , K_4   , K_3   , K_NONE,
187     /* 28 */  K_NONE, K_SPCE, K_V   , K_F   , K_T   , K_R   , K_5   , K_NONE,
188     /* 30 */  K_NONE, K_N   , K_B   , K_H   , K_G   , K_Y   , K_6   , K_NONE,
189     /* 38 */  K_NONE, K_NONE, K_M   , K_J   , K_U   , K_7   , K_8   , K_NONE,
190     /* 40 */  K_NONE, K_COMA, K_K   , K_I   , K_O   , K_0   , K_9   , K_NONE,
191     /* 48 */  K_NONE, K_DOT , K_FSLH, K_L   , K_SEMI, K_P   , K_MINS, K_NONE,
192     /* 50 */  K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
193     /* 58 */  K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE,
194     /* 60 */  K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
195     /* 68 */  K_NONE, KP_1  , K_NONE, KP_4  , KP_7  , K_NONE, K_NONE, K_NONE,
196     /* 70 */  KP_0  , KP_DOT, KP_2  , KP_5  , KP_6  , KP_8  , K_ESC , K_NUML,
197     /* 78 */  K_F11 , KP_PLS, KP_3  , KP_MNS, KP_STR, KP_9  , K_SCRL, K_NONE,
198     	  K_NONE, K_NONE, K_NONE, K_F7  , K_NONE, K_NONE, K_NONE, K_NONE,
199     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
200     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
201     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
202     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
203     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
204     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
205     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
206     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
207     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
208     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
209     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
210     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
211     	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE
212     };
213     
214     #ifdef CONFIG_MAGIC_SYSRQ
215     unsigned char ps2kbd_sysrq_xlate[] = 
216     {
217         27,    0,    0,    0,    0,    0,    0,    0,
218          0,    0,    0,    0,    0,    0,    0,    0,
219        '`',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
220        '8',  '9',  '0',  '-',  '=',  '£',  127,    0,
221          0,    0,    0,  '/',  '*',  '#',    9,  'q',
222        'w',  'e',  'r',  't',  'y',  'u',  'i',  'o',
223        'p',  '[',  ']', '\\',  22,    23,   25,  '7',
224        '8',  '9',  '-',    0,  'a',  's',  'd',  'f',
225        'g',  'h',  'j',  'k',  'l',  ';', '\'',   13,
226        '4',  '5',  '6',  '+',    0,    0,  'z',  'x',
227        'c',  'v',  'b',  'n',  'm',  ',',  '.',  '/',
228          0,    0,  '1',  '2',  '3',    0,    0,  ' ',
229          0,    0,    0,    0,    0,  '0',  '.',   10,
230          0,    0,    0,    0,    0,    0,    0,    0,
231          0,    0,    0,    0,    0,    0,    0,    0,
232          0,    0,    0,    0,    0,    0,    0,    0,
233     };
234     #endif
235     
236     static inline void ps2kbd_key(unsigned int keycode, unsigned int up_flag)
237     {
238     	handle_scancode(keycode, !up_flag);
239     }
240     
241     static inline void ps2kbd_sendbyte(unsigned char val)
242     {
243     	int tries = 3, timeout = 1000;
244     
245     	tx_state = TX_SEND;
246     
247     	do {
248     		switch (tx_state) {
249     		case TX_SEND:
250     			tx_state = TX_SENT;
251     			timeout = 1000;
252     			tries --;
253     
254     			while(!(iomd_readb(IOMD_KCTRL) & (1 << 7)));
255     			iomd_writeb(val, IOMD_KARTTX);
256     			break;
257     
258     		case TX_SENT:
259     			udelay(1000);
260     			if (--timeout == 0) {
261     				printk(KERN_ERR "Keyboard timeout\n");
262     				tx_state = TX_DONE;
263     			}
264     			break;
265     
266     		case TX_DONE:
267     			break;
268     		}
269     	} while (tries > 0 && tx_state != TX_DONE);
270     }
271     
272     static unsigned char status;
273     static unsigned char ncodes;
274     static unsigned char bi;
275     static unsigned char buffer[4];
276     
277     static inline void ps2kbd_reset(void)
278     {
279     	status = 0;
280     	kbd_reset_kdown();
281     }
282     
283     static void handle_rawcode(int keyval)
284     {
285     	int keysym;
286     
287     	if (keyval > 0x83) {
288     		switch (keyval) {
289     		case KBD_ESCAPEE0:
290     			ncodes = 2;
291     			bi = 0;
292     			break;
293     
294     		case KBD_ESCAPEE1:
295     			ncodes = 3;
296     			bi = 0;
297     			break;
298     
299     		case KBD_ACK:
300     			tx_state = TX_DONE;
301     			return;
302     
303     		case KBD_RESEND:
304     			tx_state = TX_SEND;
305     			return;
306     
307     		case KBD_BREAK:
308     			status |= CODE_BREAK;
309     			return;
310     
311     		default:
312     			return;
313     		}
314     	}
315     
316     	if (ncodes) {
317     		buffer[bi++] = keyval;
318     		ncodes -= 1;
319     		if (ncodes)
320     			return;
321     		keysym = K_NONE;
322     		switch (buffer[0] << 8 | buffer[1]) {
323     		case ESCE0(0x11): keysym = K_RALT; break;
324     		case ESCE0(0x14): keysym = K_RCTL; break;
325     		/*
326     		 * take care of MS extra keys (actually
327     		 * 0x7d - 0x7f, but last one is already K_NONE
328     		 */
329     		case ESCE0(0x1f): keysym = 124;    break;
330     		case ESCE0(0x27): keysym = 125;    break;
331     		case ESCE0(0x2f): keysym = 126;    break;
332     		case ESCE0(0x4a): keysym = KP_SLH; break;
333     		case ESCE0(0x5a): keysym = KP_ENT; break;
334     		case ESCE0(0x69): keysym = K_END;  break;
335     		case ESCE0(0x6b): keysym = K_LEFT; break;
336     		case ESCE0(0x6c): keysym = K_HOME; break;
337     		case ESCE0(0x70): keysym = K_INS;  break;
338     		case ESCE0(0x71): keysym = K_DEL;  break;
339     		case ESCE0(0x72): keysym = K_DOWN; break;
340     		case ESCE0(0x74): keysym = K_RGHT; break;
341     		case ESCE0(0x75): keysym = K_UP;   break;
342     		case ESCE0(0x7a): keysym = K_PGDN; break;
343     		case ESCE0(0x7c): keysym = K_PRNT; break;
344     		case ESCE0(0x7d): keysym = K_PGUP; break;
345     		case ESCE1(0x14):
346     			if (buffer[2] == 0x77)
347     				keysym = K_BRK;
348     			break;
349     		case ESCE0(0x12):		/* ignore escaped shift key */
350     			status = 0;
351     			return;
352     		}
353     	} else {
354     		bi = 0;
355     		keysym = keycode_translate[keyval];
356     	}
357     
358     	if (keysym != K_NONE)
359     		ps2kbd_key(keysym, status & CODE_BREAK);
360     	status = 0;
361     }
362     
363     void ps2kbd_leds(unsigned int leds)
364     {
365     	ps2kbd_sendbyte(KBD_SETLEDS);
366     	ps2kbd_sendbyte(leds);
367     	ps2kbd_sendbyte(KBD_SCANENABLE);
368     }
369     
370     static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
371     {
372     	kbd_pt_regs = regs;
373     
374     	while (iomd_readb(IOMD_KCTRL) & (1 << 5))
375     		handle_rawcode(iomd_readb(IOMD_KARTRX));
376     	tasklet_schedule(&keyboard_tasklet);
377     }
378     
379     static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
380     {
381     }
382     
383     int __init ps2kbd_init_hw(void)
384     {
385     	/* Reset the keyboard state machine. */
386     	iomd_writeb(0, IOMD_KCTRL);
387     	iomd_writeb(8, IOMD_KCTRL);
388     	iomd_readb(IOMD_KARTRX);
389     
390     	if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
391     		panic("Could not allocate keyboard receive IRQ!");
392     	if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
393     		panic("Could not allocate keyboard transmit IRQ!");
394     
395     	return 0;
396     }
397