File: /usr/src/linux/arch/m68k/hp300/hil.c

1     /*
2      *  linux/arch/m68k/hp300/hil.c
3      *
4      *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5      *
6      *  HP300 Human Interface Loop driver.  This handles the keyboard and mouse.
7      */
8     
9     #include <linux/stddef.h>
10     #include <linux/kernel.h>
11     #include <linux/sched.h>
12     #include <linux/init.h>
13     #include <linux/keyboard.h>
14     #include <linux/kbd_ll.h>
15     #include <asm/io.h>
16     #include <asm/hwtest.h>
17     #include <asm/ptrace.h>
18     #include <asm/irq.h>
19     #include <asm/system.h>
20     
21     #define HILBASE			0xf0428000
22     #define HIL_DATA			0x1
23     #define HIL_CMD			0x3
24     
25     #define	HIL_BUSY		0x02
26     #define	HIL_DATA_RDY		0x01
27     
28     #define hil_busy()		(readb(HILBASE + HIL_CMD) & HIL_BUSY)
29     #define hil_data_available()	(readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
30     #define hil_status()		(readb(HILBASE + HIL_CMD))
31     #define hil_command(x)		do { writeb((x), HILBASE + HIL_CMD); } while (0)
32     #define hil_read_data()		(readb(HILBASE + HIL_DATA))
33     #define hil_write_data(x)	do { writeb((x), HILBASE + HIL_DATA); } while (0)
34     
35     #define	HIL_SETARD		0xA0		/* set auto-repeat delay */
36     #define	HIL_SETARR		0xA2		/* set auto-repeat rate */
37     #define	HIL_SETTONE		0xA3		/* set tone generator */
38     #define	HIL_CNMT		0xB2		/* clear nmi */
39     #define	HIL_INTON		0x5C		/* Turn on interrupts. */
40     #define	HIL_INTOFF		0x5D		/* Turn off interrupts. */
41     #define	HIL_TRIGGER		0xC5		/* trigger command */
42     #define	HIL_STARTCMD		0xE0		/* start loop command */
43     #define	HIL_TIMEOUT		0xFE		/* timeout */
44     #define	HIL_READTIME		0x13		/* Read real time register */
45     
46     #define	HIL_READBUSY		0x02		/* internal "busy" register */
47     #define	HIL_READKBDLANG		0x12		/* read keyboard language code */
48     #define	HIL_READKBDSADR	 	0xF9
49     #define	HIL_WRITEKBDSADR 	0xE9
50     #define	HIL_READLPSTAT  	0xFA
51     #define	HIL_WRITELPSTAT 	0xEA
52     #define	HIL_READLPCTRL  	0xFB
53     #define	HIL_WRITELPCTRL 	0xEB
54     
55     #define HIL_IRQ			1
56     
57     #define plain_map		hp_plain_map
58     #define shift_map		hp_shift_map
59     #define altgr_map		hp_altgr_map
60     #define ctrl_map		hp_ctrl_map
61     #define shift_ctrl_map		hp_shift_ctrl_map
62     #define alt_map			hp_alt_map
63     #define ctrl_alt_map		hp_ctrl_alt_map
64     
65     u_short plain_map[NR_KEYS] = {
66     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
67     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
68     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
69     	0xfb62,	0xfb76,	0xfb63,	0xfb78,	0xfb7a,	0xf200,	0xf200,	0xf01b,
70     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
71     	0xfb68,	0xfb67,	0xfb66,	0xfb64,	0xfb73,	0xfb61,	0xf200,	0xf207,
72     	0xfb75,	0xfb79,	0xfb74,	0xfb72,	0xfb65,	0xfb77,	0xfb71,	0xf009,
73     	0xf037,	0xf036,	0xf035,	0xf034,	0xf033,	0xf032,	0xf031,	0xf060,
74     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
75     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
76     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
77     	0xf038,	0xf039,	0xf030,	0xf02d,	0xf03d,	0xf008,	0xf200,	0xf200,
78     	0xfb69,	0xfb6f,	0xfb70,	0xf05b,	0xf05d,	0xf05c,	0xf200,	0xf200,
79     	0xfb6a,	0xfb6b,	0xfb6c,	0xf03b,	0xf027,	0xf201,	0xf200,	0xf200,
80     	0xfb6d,	0xf02c,	0xf02e,	0xf02f,	0xf200,	0xf200,	0xf200,	0xf200,
81     	0xfb6e,	0xf020,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
82     };
83     
84     u_short shift_map[NR_KEYS] = {
85     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
86     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
87     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
88     	0xfb42,	0xfb56,	0xfb43,	0xfb58,	0xfb5a,	0xf200,	0xf200,	0xf07f,
89     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
90     	0xfb48,	0xfb47,	0xfb46,	0xfb44,	0xfb53,	0xfb41,	0xf200,	0xf207,
91     	0xfb55,	0xfb59,	0xfb54,	0xfb52,	0xfb45,	0xfb57,	0xfb51,	0xf009,
92     	0xf026,	0xf05e,	0xf025,	0xf024,	0xf023,	0xf040,	0xf021,	0xf07e,
93     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
94     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
95     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
96     	0xf02a,	0xf028,	0xf029,	0xf05f,	0xf02b,	0xf200,	0xf200,	0xf200,
97     	0xfb49,	0xfb4f,	0xfb50,	0xf07b,	0xf07d,	0xf07c,	0xf200,	0xf200,
98     	0xfb4a,	0xfb4b,	0xfb4c,	0xf03a,	0xf022,	0xf201,	0xf200,	0xf200,
99     	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf200,	0xf200,	0xf200,	0xf200,
100     	0xfb4e,	0xf020,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
101     };
102     
103     u_short altgr_map[NR_KEYS] = {
104     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
105     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
106     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
107     	0xfb62,	0xfb76,	0xfb63,	0xfb78,	0xfb7a,	0xf200,	0xf200,	0xf200,
108     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
109     	0xfb68,	0xfb67,	0xfb66,	0xfb64,	0xfb73,	0xfb61,	0xf200,	0xf207,
110     	0xfb75,	0xfb79,	0xfb74,	0xfb72,	0xfb65,	0xfb77,	0xfb71,	0xf200,
111     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf040,	0xf021,	0xf200,
112     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
113     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
114     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
115     	0xf02a,	0xf05b,	0xf05d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
116     	0xfb69,	0xfb6f,	0xfb70,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
117     	0xfb6a,	0xfb6b,	0xfb6c,	0xf200,	0xf200,	0xf201,	0xf200,	0xf200,
118     	0xfb6d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
119     	0xfb6e,	0xf200,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
120     };
121     
122     u_short ctrl_map[NR_KEYS] = {
123     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
124     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
125     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
126     	0xf002,	0xf016,	0xf003,	0xf018,	0xf01a,	0xf200,	0xf200,	0xf200,
127     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
128     	0xf008,	0xf007,	0xf006,	0xf004,	0xf013,	0xf001,	0xf200,	0xf207,
129     	0xf015,	0xf019,	0xf014,	0xf012,	0xf005,	0xf017,	0xf011,	0xf200,
130     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf000,
131     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
132     	0xf200,	0xf503,	0xf502,	0xf501,	0xf500,	0xf200,	0xf200,	0xf200,
133     	0xf200,	0xf504,	0xf505,	0xf506,	0xf507,	0xf200,	0xf200,	0xf200,
134     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
135     	0xf009,	0xf00f,	0xf010,	0xf200,	0xf200,	0xf01c,	0xf200,	0xf200,
136     	0xf00a,	0xf00b,	0xf00c,	0xf200,	0xf007,	0xf201,	0xf200,	0xf200,
137     	0xf00d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
138     	0xf00e,	0xf200,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
139     };
140     
141     u_short shift_ctrl_map[NR_KEYS] = {
142     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
143     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
144     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
145     	0xf002,	0xf016,	0xf003,	0xf018,	0xf01a,	0xf200,	0xf200,	0xf200,
146     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
147     	0xf008,	0xf007,	0xf006,	0xf004,	0xf013,	0xf001,	0xf200,	0xf207,
148     	0xf015,	0xf019,	0xf014,	0xf012,	0xf005,	0xf017,	0xf011,	0xf200,
149     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
150     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
151     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
152     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
153     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
154     	0xf009,	0xf00f,	0xf010,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
155     	0xf00a,	0xf00b,	0xf00c,	0xf200,	0xf200,	0xf201,	0xf200,	0xf200,
156     	0xf00d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
157     	0xf00e,	0xf200,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
158     };
159     
160     u_short alt_map[NR_KEYS] = {
161     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
162     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
163     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
164     	0xf862,	0xf876,	0xf863,	0xf878,	0xf87a,	0xf200,	0xf200,	0xf200,
165     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
166     	0xf868,	0xf867,	0xf866,	0xf864,	0xf873,	0xf861,	0xf200,	0xf207,
167     	0xf875,	0xf879,	0xf874,	0xf872,	0xf865,	0xf877,	0xf871,	0xf809,
168     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf860,
169     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
170     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
171     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
172     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
173     	0xf869,	0xf86f,	0xf870,	0xf200,	0xf200,	0xf85c,	0xf200,	0xf200,
174     	0xf86a,	0xf86b,	0xf86c,	0xf83b,	0xf827,	0xf201,	0xf200,	0xf200,
175     	0xf86d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
176     	0xf86e,	0xf200,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
177     };
178     
179     u_short ctrl_alt_map[NR_KEYS] = {
180     	0xf200,	0xf200,	0xf703,	0xf703,	0xf700,	0xf700,	0xf702,	0xf200,
181     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
182     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
183     	0xf802,	0xf816,	0xf803,	0xf818,	0xf81a,	0xf200,	0xf200,	0xf200,
184     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
185     	0xf808,	0xf807,	0xf806,	0xf804,	0xf813,	0xf801,	0xf200,	0xf207,
186     	0xf815,	0xf819,	0xf814,	0xf812,	0xf805,	0xf817,	0xf811,	0xf200,
187     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
188     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
189     	0xf200,	0xf103,	0xf102,	0xf101,	0xf100,	0xf200,	0xf200,	0xf200,
190     	0xf200,	0xf104,	0xf105,	0xf106,	0xf107,	0xf200,	0xf200,	0xf200,
191     	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
192     	0xf809,	0xf80f,	0xf810,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
193     	0xf80a,	0xf80b,	0xf80c,	0xf200,	0xf200,	0xf201,	0xf200,	0xf200,
194     	0xf80d,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
195     	0xf80e,	0xf200,	0xf200,	0xf200,	0xf601,	0xf600,	0xf603,	0xf602,
196     };
197     
198     #undef plain_map
199     #undef ctrl_alt_map
200     #undef shift_map
201     #undef altgr_map
202     #undef ctrl_map
203     #undef shift_ctrl_map
204     #undef alt_map
205     
206     struct {
207       unsigned char s, c;
208       int valid;
209     } hil_last;
210     
211     #define hil_getlast(s,c)  do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0)
212     
213     struct {
214       unsigned char data[16];
215       unsigned int ptr;
216     } poll;
217     
218     unsigned char curdev = 0;
219     
220     static void poll_finished(void)
221     {
222       switch (poll.data[0])
223       {
224       case 0x40:
225         {
226           int down = (poll.data[1] & 1) == 0;
227           unsigned char scode = poll.data[1] >> 1;
228     #if 0
229           if (down)
230     	printk("[%02x]", scode);
231     #endif
232           handle_scancode(scode, down);
233         }
234         break;
235       }
236       curdev = 0;
237     }
238     
239     static inline void handle_status(unsigned char s, unsigned char c)
240     {
241       if (c & 0x8) {
242         /* End of block */
243         if (c & 0x10)
244           poll_finished();
245       } else {
246         if (c & 0x10) {
247           if (curdev)
248     	poll_finished();		/* just in case */
249           curdev = c & 7;
250           poll.ptr = 0;
251         }
252       }
253     }
254     
255     static inline void handle_data(unsigned char s, unsigned char c)
256     {
257       if (curdev)
258         poll.data[poll.ptr++] = c;
259     }
260     
261     /* 
262      * Handle HIL interrupts.
263      */
264     
265     static void hil_interrupt(int irq, void *handle, struct pt_regs *regs)
266     {
267       unsigned char s, c;
268       s = hil_status(); c = hil_read_data();
269       switch (s >> 4)
270       {
271       case 0x5:
272         handle_status(s, c);
273         break;
274       case 0x6:
275         handle_data(s, c);
276         break;
277       case 0x4:
278         hil_last.s = s;
279         hil_last.c = c;
280         mb();
281         hil_last.valid = 1;
282         break;
283       }
284     }
285     
286     /*
287      * Send a command to the HIL
288      */
289     
290     static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
291     {
292       unsigned long flags;
293       save_flags(flags); cli();
294       while (hil_busy());
295       hil_command(cmd);
296       while (len--) {
297         while (hil_busy());
298         hil_write_data(*(data++));
299       }
300       restore_flags(flags);
301     }
302     
303     /*
304      * Initialise HIL. 
305      */
306     
307     int __init hp300_keyb_init(void)
308     {
309       unsigned char s, c, kbid;
310       unsigned int n = 0;
311     
312       memcpy(key_maps[0], hp_plain_map, sizeof(plain_map));
313       memcpy(key_maps[1], hp_shift_map, sizeof(plain_map));
314       memcpy(key_maps[4], hp_ctrl_map, sizeof(plain_map));
315     
316       if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
317         return 1;		/* maybe this can happen */
318     
319       request_irq(HIL_IRQ, hil_interrupt, 0, "HIL", NULL);
320     
321       /* Turn on interrupts */
322       hil_do(HIL_INTON, NULL, 0);
323     
324       /* Look for keyboards */
325       hil_do(HIL_READKBDSADR, NULL, 0);
326       while (!hil_last.valid) {
327         if (n++ > 100000) {
328           printk("HIL: timed out, assuming no keyboard present.\n");
329           return 1;
330         }
331         mb();
332       }
333       hil_getlast(s, c);
334       if (c == 0) {
335         printk("HIL: no keyboard present.\n");
336         return 1;
337       }
338       for (kbid = 0; (kbid < 8) && ((c & (1<<kbid)) == 0); kbid++);
339       printk("HIL: keyboard found at id %d\n", kbid);
340       /* set it to raw mode */
341       c = 0;
342       hil_do(HIL_WRITEKBDSADR, &c, 1);
343       return 0;
344     }
345