2 * linux/arch/m68k/hp300/hil.c
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
6 * HP300 Human Interface Loop driver. This handles the keyboard and mouse.
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>
16 #include <asm/hwtest.h>
17 #include <asm/ptrace.h>
19 #include <asm/system.h>
21 #define HILBASE 0xf0428000
26 #define HIL_DATA_RDY 0x01
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)
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 */
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
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
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,
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,
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,
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,
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,
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,
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,
203 #undef shift_ctrl_map
211 #define hil_getlast(s,c) do { s = hil_last.s; c = hil_last.c; hil_last.valid = 0; } while (0)
214 unsigned char data
[16];
218 unsigned char curdev
= 0;
220 static void poll_finished(void)
222 switch (poll
.data
[0])
226 int down
= (poll
.data
[1] & 1) == 0;
227 unsigned char scode
= poll
.data
[1] >> 1;
230 printk("[%02x]", scode
);
232 handle_scancode(scode
, down
);
239 static inline void handle_status(unsigned char s
, unsigned char c
)
248 poll_finished(); /* just in case */
255 static inline void handle_data(unsigned char s
, unsigned char c
)
258 poll
.data
[poll
.ptr
++] = c
;
262 * Handle HIL interrupts.
265 static void hil_interrupt(int irq
, void *handle
, struct pt_regs
*regs
)
268 s
= hil_status(); c
= hil_read_data();
287 * Send a command to the HIL
290 static void hil_do(unsigned char cmd
, unsigned char *data
, unsigned int len
)
293 save_flags(flags
); cli();
298 hil_write_data(*(data
++));
300 restore_flags(flags
);
307 int __init
hp300_keyb_init(void)
309 unsigned char s
, c
, kbid
;
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
));
316 if (!hwreg_present((void *)(HILBASE
+ HIL_DATA
)))
317 return 1; /* maybe this can happen */
319 request_irq(HIL_IRQ
, hil_interrupt
, 0, "HIL", NULL
);
321 /* Turn on interrupts */
322 hil_do(HIL_INTON
, NULL
, 0);
324 /* Look for keyboards */
325 hil_do(HIL_READKBDSADR
, NULL
, 0);
326 while (!hil_last
.valid
) {
328 printk("HIL: timed out, assuming no keyboard present.\n");
335 printk("HIL: no keyboard present.\n");
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 */
342 hil_do(HIL_WRITEKBDSADR
, &c
, 1);