1
2
3
4
5
6#include <linux/config.h>
7
8#include <linux/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/keyboard.h>
14#include <linux/signal.h>
15#include <linux/ioport.h>
16#include <linux/init.h>
17#include <linux/kbd_ll.h>
18#include <linux/kbd_kern.h>
19#include <linux/delay.h>
20#include <linux/sysrq.h>
21#include <linux/random.h>
22#include <linux/poll.h>
23#include <linux/miscdevice.h>
24#include <linux/slab.h>
25
26#include <asm/keyboard.h>
27#include <asm/bitops.h>
28#include <asm/io.h>
29#include <asm/uaccess.h>
30#include <asm/q40_master.h>
31#include <asm/irq.h>
32#include <asm/q40ints.h>
33
34
35
36
37#define SYSRQ_KEY 0x54
38
39#ifdef CONFIG_MAGIC_SYSRQ
40unsigned char q40kbd_sysrq_xlate[128] =
41 "\000\0331234567890-=\177\t"
42 "qwertyuiop[]\r\000as"
43 "dfghjkl;'`\000\\zxcv"
44 "bnm,./\000*\000 \000\201\202\203\204\205"
45 "\206\207\210\211\212\000\000789-456+1"
46 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000"
47 "\r\000/";
48#endif
49
50
51
52
53unsigned static char q40cl[256] =
54{
55 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00,
56 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00,
57 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00,
58 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00,
59 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00,
60 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00,
61 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,
62 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00,
63 0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
64 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
65 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
66 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
67 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
68 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
69 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
71};
72
73
74
75static unsigned char q40ecl[]=
76{
77 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
78 0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,
84 0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00,
85 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
87 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
88 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
91 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
92 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
93};
94
95
96static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
97
98
99
100
101
102
103
104
105
106
107
108
109#define E0_KPENTER 96
110#define E0_RCTRL 97
111#define E0_KPSLASH 98
112#define E0_PRSCR 99
113#define E0_RALT 100
114#define E0_BREAK 101
115#define E0_HOME 102
116#define E0_UP 103
117#define E0_PGUP 104
118#define E0_LEFT 105
119#define E0_RIGHT 106
120#define E0_END 107
121#define E0_DOWN 108
122#define E0_PGDN 109
123#define E0_INS 110
124#define E0_DEL 111
125
126#define E1_PAUSE 119
127
128
129
130
131
132
133
134
135#define SC_LIM 89
136
137#define FOCUS_PF1 85
138#define FOCUS_PF2 89
139#define FOCUS_PF3 90
140#define FOCUS_PF4 91
141#define FOCUS_PF5 92
142#define FOCUS_PF6 93
143#define FOCUS_PF7 94
144#define FOCUS_PF8 95
145#define FOCUS_PF9 120
146#define FOCUS_PF10 121
147#define FOCUS_PF11 122
148#define FOCUS_PF12 123
149
150#define JAP_86 124
151
152
153
154
155
156
157#define RGN1 124
158#define RGN2 125
159#define RGN3 126
160#define RGN4 127
161
162static unsigned char high_keys[128 - SC_LIM] = {
163 RGN1, RGN2, RGN3, RGN4, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,
166 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,
167 FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,
168 FOCUS_PF8, JAP_86, FOCUS_PF10, 0
169};
170
171
172#define E0_MACRO 112
173
174#define E0_F13 113
175#define E0_F14 114
176#define E0_HELP 115
177#define E0_DO 116
178#define E0_F17 117
179#define E0_KPMINPLUS 118
180
181
182
183
184#define E0_OK 124
185
186
187
188
189
190
191#define E0_MSLW 125
192#define E0_MSRW 126
193#define E0_MSTM 127
194
195
196static unsigned char e0_keys[128] = {
197 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,
204 E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,
205 E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,
206 E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
207 E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,
208 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,
209 0, 0, 0, 0, 0, 0, 0, 0,
210 0, 0, 0, 0, 0, 0, 0, E0_MACRO,
211 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0
213};
214
215
216int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode)
217{
218 if (scancode < SC_LIM || scancode > 255 || keycode > 127)
219 return -EINVAL;
220 if (scancode < 128)
221 high_keys[scancode - SC_LIM] = keycode;
222 else
223 e0_keys[scancode - 128] = keycode;
224 return 0;
225}
226
227int q40kbd_getkeycode(unsigned int scancode)
228{
229 return
230 (scancode < SC_LIM || scancode > 255) ? -EINVAL :
231 (scancode < 128) ? high_keys[scancode - SC_LIM] :
232 e0_keys[scancode - 128];
233}
234
235
236#define disable_keyboard()
237#define enable_keyboard()
238
239
240
241
242int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
243 char raw_mode)
244{
245 static int prev_scancode;
246
247
248 if (scancode == 0xe0 || scancode == 0xe1) {
249 prev_scancode = scancode;
250 return 0;
251 }
252
253
254 if (scancode == 0x00 || scancode == 0xff) {
255 prev_scancode = 0;
256 return 0;
257 }
258
259 scancode &= 0x7f;
260
261 if (prev_scancode) {
262
263
264
265
266 if (prev_scancode != 0xe0) {
267 if (prev_scancode == 0xe1 && scancode == 0x1d) {
268 prev_scancode = 0x100;
269 return 0;
270 } else if (prev_scancode == 0x100 && scancode == 0x45) {
271 *keycode = E1_PAUSE;
272 prev_scancode = 0;
273 } else {
274#ifdef KBD_REPORT_UNKN
275 if (!raw_mode)
276 printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
277#endif
278 prev_scancode = 0;
279 return 0;
280 }
281 } else {
282 prev_scancode = 0;
283
284
285
286
287
288
289
290
291
292
293
294
295
296 if (scancode == 0x2a || scancode == 0x36)
297 return 0;
298
299 if (e0_keys[scancode])
300 *keycode = e0_keys[scancode];
301 else {
302#ifdef KBD_REPORT_UNKN
303 if (!raw_mode)
304 printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
305 scancode);
306#endif
307 return 0;
308 }
309 }
310 } else if (scancode >= SC_LIM) {
311
312
313
314
315
316
317
318
319
320
321 *keycode = high_keys[scancode - SC_LIM];
322
323 if (!*keycode) {
324 if (!raw_mode) {
325#ifdef KBD_REPORT_UNKN
326 printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
327 " - ignored\n", scancode);
328#endif
329 }
330 return 0;
331 }
332 } else
333 *keycode = scancode;
334 return 1;
335}
336
337char q40kbd_unexpected_up(unsigned char keycode)
338{
339
340
341 if (keycode >= SC_LIM || keycode == 85)
342 return 0;
343 else
344 return 0200;
345}
346
347static int keyup=0;
348static int qprev=0;
349
350static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
351{
352 unsigned char status;
353
354 spin_lock(&kbd_controller_lock);
355 kbd_pt_regs = regs;
356
357 status = Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
358 if (status )
359 {
360 unsigned char scancode,qcode;
361
362 qcode = master_inb(KEYCODE_REG);
363
364 if (qcode != 0xf0)
365 {
366 if (qcode == 0xe0)
367 {
368 qprev=0xe0;
369 handle_scancode(qprev , 1);
370 goto exit;
371 }
372
373 scancode=qprev ? q40ecl[qcode] : q40cl[qcode];
374#if 0
375
376 if (qprev && !scancode) scancode=q40cl[qcode];
377#endif
378 qprev=0;
379 if (!scancode)
380 {
381 printk("unknown scancode %x\n",qcode);
382 goto exit;
383 }
384 if (scancode==0xff)
385 scancode=SYSRQ_KEY;
386
387 handle_scancode(scancode, ! keyup );
388 keyup=0;
389 tasklet_schedule(&keyboard_tasklet);
390 }
391 else
392 keyup=1;
393 }
394exit:
395 spin_unlock(&kbd_controller_lock);
396 master_outb(-1,KEYBOARD_UNLOCK_REG);
397}
398
399
400#define KBD_NO_DATA (-1)
401#define KBD_BAD_DATA (-2)
402
403static int __init q40kbd_read_input(void)
404{
405 int retval = KBD_NO_DATA;
406 unsigned char status;
407
408 status = Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
409 if (status) {
410 unsigned char data = master_inb(KEYCODE_REG);
411
412 retval = data;
413 master_outb(-1,KEYBOARD_UNLOCK_REG);
414 }
415 return retval;
416}
417
418
419static void __init kbd_clear_input(void)
420{
421 int maxread = 100;
422
423 do {
424 if (q40kbd_read_input() == KBD_NO_DATA)
425 break;
426 } while (--maxread);
427}
428
429
430int __init q40kbd_init_hw(void)
431{
432
433
434 kbd_clear_input();
435
436
437 request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL);
438 master_outb(-1,KEYBOARD_UNLOCK_REG);
439 master_outb(1,KEY_IRQ_ENABLE_REG);
440
441 return 0;
442}
443
444