more debug output
[linux-2.4.git] / 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()              (in_8(HILBASE + HIL_CMD) & HIL_BUSY)
29 #define hil_data_available()    (in_8(HILBASE + HIL_CMD) & HIL_DATA_RDY)
30 #define hil_status()            (in_8(HILBASE + HIL_CMD))
31 #define hil_command(x)          out_8(HILBASE + HIL_CMD, (x))
32 #define hil_read_data()         (in_8(HILBASE + HIL_DATA))
33 #define hil_write_data(x)       out_8(HILBASE + HIL_DATA, (x))
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 }