Import 2.3.13
[davej-history.git] / drivers / char / q40_keyb.c
blobea9d7438f3b7b2989346bc377410561285137f68
1 /*
2 * linux/drivers/char/q40_keyb.c
4 */
6 #include <linux/config.h>
8 #include <asm/spinlock.h>
9 #include <linux/sched.h>
10 #include <linux/interrupt.h>
11 #include <linux/tty.h>
12 #include <linux/mm.h>
13 #include <linux/signal.h>
14 #include <linux/ioport.h>
15 #include <linux/init.h>
16 #include <linux/kbd_ll.h>
17 #include <linux/delay.h>
18 #include <linux/sysrq.h>
19 #include <linux/random.h>
20 #include <linux/poll.h>
21 #include <linux/miscdevice.h>
22 #include <linux/malloc.h>
24 #include <asm/keyboard.h>
25 #include <asm/bitops.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/q40_master.h>
29 #include <asm/irq.h>
30 #include <asm/q40ints.h>
32 /* Some configuration switches are present in the include file... */
34 #define KBD_REPORT_ERR
36 /* Simple translation table for the SysRq keys */
38 #define SYSRQ_KEY 0x54
40 #ifdef CONFIG_MAGIC_SYSRQ
41 unsigned char q40kbd_sysrq_xlate[128] =
42 "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
43 "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
44 "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
45 "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
46 "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
47 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
48 "\r\000/"; /* 0x60 - 0x6f */
49 #endif
51 /* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/
52 /* 0x00 means not a valid entry or no conversion known */
54 unsigned static char q40cl[256] =
55 {/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
56 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00, /* 0x00 - 0x0f */
57 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00, /* 0x10 - 0x1f */
58 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00, /* 0x20 - 0x2f 'f' is at 0x2b, what is 0x28 ???*/
59 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00, /* 0x30 - 0x3f */
60 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00, /* 0x40 - 0x4f */
61 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00, /* 0x50 - 0x5f*/
62 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f */
63 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00, /* 0x70 - 0x7f */
64 0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f 0x84/0x37 is SySrq*/
65 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f */
66 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf */
67 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf */
68 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf */
69 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf */
70 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef */
71 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf0 - 0xff */
74 /* another table, AT 0xe0 codes to PC 0xe0 codes,
75 0xff special entry for SysRq - DROPPED right now */
76 static unsigned char q40ecl[]=
77 {/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
78 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x00 - 0x0f*/
79 0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x10 - 0x1f */
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x20 - 0x2f*/
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x30 - 0x3f*/
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00, /* 0x40 - 0x4f*/
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00, /* 0x50 - 0x5f*/
84 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f*/
85 0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00, /* 0x70 - 0x7f*/
86 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f*/
87 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f*/
88 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf*/
89 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf*/
90 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf*/
91 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf*/
92 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef*/
93 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 0xf0 - 0xff*/
97 spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
101 * Translation of escaped scancodes to keycodes.
102 * This is now user-settable.
103 * The keycodes 1-88,96-111,119 are fairly standard, and
104 * should probably not be changed - changing might confuse X.
105 * X also interprets scancode 0x5d (KEY_Begin).
107 * For 1-88 keycode equals scancode.
110 #define E0_KPENTER 96
111 #define E0_RCTRL 97
112 #define E0_KPSLASH 98
113 #define E0_PRSCR 99
114 #define E0_RALT 100
115 #define E0_BREAK 101 /* (control-pause) */
116 #define E0_HOME 102
117 #define E0_UP 103
118 #define E0_PGUP 104
119 #define E0_LEFT 105
120 #define E0_RIGHT 106
121 #define E0_END 107
122 #define E0_DOWN 108
123 #define E0_PGDN 109
124 #define E0_INS 110
125 #define E0_DEL 111
127 #define E1_PAUSE 119
130 * The keycodes below are randomly located in 89-95,112-118,120-127.
131 * They could be thrown away (and all occurrences below replaced by 0),
132 * but that would force many users to use the `setkeycodes' utility, where
133 * they needed not before. It does not matter that there are duplicates, as
134 * long as no duplication occurs for any single keyboard.
136 #define SC_LIM 89
138 #define FOCUS_PF1 85 /* actual code! */
139 #define FOCUS_PF2 89
140 #define FOCUS_PF3 90
141 #define FOCUS_PF4 91
142 #define FOCUS_PF5 92
143 #define FOCUS_PF6 93
144 #define FOCUS_PF7 94
145 #define FOCUS_PF8 95
146 #define FOCUS_PF9 120
147 #define FOCUS_PF10 121
148 #define FOCUS_PF11 122
149 #define FOCUS_PF12 123
151 #define JAP_86 124
152 /* tfj@olivia.ping.dk:
153 * The four keys are located over the numeric keypad, and are
154 * labelled A1-A4. It's an rc930 keyboard, from
155 * Regnecentralen/RC International, Now ICL.
156 * Scancodes: 59, 5a, 5b, 5c.
158 #define RGN1 124
159 #define RGN2 125
160 #define RGN3 126
161 #define RGN4 127
163 static unsigned char high_keys[128 - SC_LIM] = {
164 RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
165 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
166 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
167 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
168 FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
169 FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
172 /* BTC */
173 #define E0_MACRO 112
174 /* LK450 */
175 #define E0_F13 113
176 #define E0_F14 114
177 #define E0_HELP 115
178 #define E0_DO 116
179 #define E0_F17 117
180 #define E0_KPMINPLUS 118
182 * My OmniKey generates e0 4c for the "OMNI" key and the
183 * right alt key does nada. [kkoller@nyx10.cs.du.edu]
185 #define E0_OK 124
187 * New microsoft keyboard is rumoured to have
188 * e0 5b (left window button), e0 5c (right window button),
189 * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
190 * [or: Windows_L, Windows_R, TaskMan]
192 #define E0_MSLW 125
193 #define E0_MSRW 126
194 #define E0_MSTM 127
196 /* this can be changed using setkeys : */
197 static unsigned char e0_keys[128] = {
198 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
199 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
200 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
201 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
202 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
203 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
204 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
205 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
206 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
207 E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
208 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
209 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
210 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
211 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
212 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
213 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
216 static unsigned int prev_scancode = 0; /* remember E0, E1 */
218 int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode)
220 if (scancode < SC_LIM || scancode > 255 || keycode > 127)
221 return -EINVAL;
222 if (scancode < 128)
223 high_keys[scancode - SC_LIM] = keycode;
224 else
225 e0_keys[scancode - 128] = keycode;
226 return 0;
229 int q40kbd_getkeycode(unsigned int scancode)
231 return
232 (scancode < SC_LIM || scancode > 255) ? -EINVAL :
233 (scancode < 128) ? high_keys[scancode - SC_LIM] :
234 e0_keys[scancode - 128];
238 #define disable_keyboard()
239 #define enable_keyboard()
243 int q40kbd_pretranslate(unsigned char scancode, char raw_mode)
245 if (scancode == 0xff) {
246 /* in scancode mode 1, my ESC key generates 0xff */
247 /* the calculator keys on a FOCUS 9000 generate 0xff */
248 #ifndef KBD_IS_FOCUS_9000
249 #ifdef KBD_REPORT_ERR
250 if (!raw_mode)
251 printk(KERN_DEBUG "Keyboard error\n");
252 #endif
253 #endif
254 prev_scancode = 0;
255 return 0;
258 if (scancode == 0xe0 || scancode == 0xe1) {
259 prev_scancode = scancode;
260 return 0;
262 return 1;
265 int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
266 char raw_mode)
268 /*printk("translate ...\n");*/
269 if (prev_scancode) {
271 * usually it will be 0xe0, but a Pause key generates
272 * e1 1d 45 e1 9d c5 when pressed, and nothing when released
274 if (prev_scancode != 0xe0) {
275 if (prev_scancode == 0xe1 && scancode == 0x1d) {
276 prev_scancode = 0x100;
277 return 0;
278 } else if (prev_scancode == 0x100 && scancode == 0x45) {
279 *keycode = E1_PAUSE;
280 prev_scancode = 0;
281 } else {
282 #ifdef KBD_REPORT_UNKN
283 if (!raw_mode)
284 printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
285 #endif
286 prev_scancode = 0;
287 return 0;
289 } else {
290 prev_scancode = 0;
292 * The keyboard maintains its own internal caps lock and
293 * num lock statuses. In caps lock mode E0 AA precedes make
294 * code and E0 2A follows break code. In num lock mode,
295 * E0 2A precedes make code and E0 AA follows break code.
296 * We do our own book-keeping, so we will just ignore these.
299 * For my keyboard there is no caps lock mode, but there are
300 * both Shift-L and Shift-R modes. The former mode generates
301 * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
302 * So, we should also ignore the latter. - aeb@cwi.nl
304 if (scancode == 0x2a || scancode == 0x36)
305 return 0;
307 if (e0_keys[scancode])
308 *keycode = e0_keys[scancode];
309 else {
310 #ifdef KBD_REPORT_UNKN
311 if (!raw_mode)
312 printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
313 scancode);
314 #endif
315 return 0;
318 } else if (scancode >= SC_LIM) {
319 /* This happens with the FOCUS 9000 keyboard
320 Its keys PF1..PF12 are reported to generate
321 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
322 Moreover, unless repeated, they do not generate
323 key-down events, so we have to zero up_flag below */
324 /* Also, Japanese 86/106 keyboards are reported to
325 generate 0x73 and 0x7d for \ - and \ | respectively. */
326 /* Also, some Brazilian keyboard is reported to produce
327 0x73 and 0x7e for \ ? and KP-dot, respectively. */
329 *keycode = high_keys[scancode - SC_LIM];
331 if (!*keycode) {
332 if (!raw_mode) {
333 #ifdef KBD_REPORT_UNKN
334 printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
335 " - ignored\n", scancode);
336 #endif
338 return 0;
340 } else
341 *keycode = scancode;
342 return 1;
345 char q40kbd_unexpected_up(unsigned char keycode)
347 /* unexpected, but this can happen: maybe this was a key release for a
348 FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
349 if (keycode >= SC_LIM || keycode == 85)
350 return 0;
351 else
352 return 0200;
355 static int keyup=0;
356 static int qprev=0;
358 static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
360 unsigned long flags;
361 unsigned char status;
363 disable_keyboard();
364 spin_lock_irqsave(&kbd_controller_lock, flags);
365 kbd_pt_regs = regs;
367 status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
368 if (status )
370 unsigned char scancode,qcode;
372 qcode = master_inb(KEYCODE_REG);
374 if (qcode != 0xf0)
376 if (qcode == 0xe0)
378 qprev=0xe0;
379 handle_scancode(qprev);
380 goto exit;
383 scancode=qprev ? q40ecl[qcode] : q40cl[qcode];
384 #if 0
385 /* next line is last resort to hanlde some oddities */
386 if (qprev && !scancode) scancode=q40cl[qcode];
387 #endif
388 qprev=0;
389 if (!scancode)
391 printk("unknown scancode %x\n",qcode);
392 goto exit;
394 if (scancode==0xff) /* SySrq */
395 scancode=SYSRQ_KEY;
397 handle_scancode(scancode | (keyup ? 0200 : 0));
398 keyup=0;
399 mark_bh(KEYBOARD_BH);
402 else
403 keyup=1;
405 exit:
406 spin_unlock_irqrestore(&kbd_controller_lock, flags);
407 master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
408 enable_keyboard();
414 #ifdef CONFIG_MAGIC_SYSRQ
415 int kbd_is_sysrq(unsigned char keycode)
417 return( keycode == SYSRQ_KEY );
419 #endif /* CONFIG_MAGIC_SYSRQ */
424 #define KBD_NO_DATA (-1) /* No data */
425 #define KBD_BAD_DATA (-2) /* Parity or other error */
427 static int __init kbd_read_input(void)
429 int retval = KBD_NO_DATA;
430 unsigned char status;
432 status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
433 if (status) {
434 unsigned char data = master_inb(KEYCODE_REG);
436 retval = data;
437 master_outb(-1,KEYBOARD_UNLOCK_REG);
439 return retval;
442 extern void q40kbd_leds(unsigned char leds)
443 { /* nothing can be done */ }
445 static void __init kbd_clear_input(void)
447 int maxread = 100; /* Random number */
449 do {
450 if (kbd_read_input() == KBD_NO_DATA)
451 break;
452 } while (--maxread);
456 void __init q40kbd_init_hw(void)
458 #if 0
459 /* Get the keyboard controller registers (incomplete decode) */
460 request_region(0x60, 16, "keyboard");
461 #endif
462 /* Flush any pending input. */
463 kbd_clear_input();
465 /* Ok, finally allocate the IRQ, and off we go.. */
466 request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL);
467 master_outb(-1,KEYBOARD_UNLOCK_REG);
468 master_outb(1,KEY_IRQ_ENABLE_REG);