File: /usr/src/linux/drivers/char/q40_keyb.c

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