1 |
1275 |
phoenix |
/*
|
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 |
|
|
|
35 |
|
|
/* Simple translation table for the SysRq keys */
|
36 |
|
|
|
37 |
|
|
#define SYSRQ_KEY 0x54
|
38 |
|
|
|
39 |
|
|
#ifdef CONFIG_MAGIC_SYSRQ
|
40 |
|
|
unsigned char q40kbd_sysrq_xlate[128] =
|
41 |
|
|
"\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
|
42 |
|
|
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
|
43 |
|
|
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
|
44 |
|
|
"bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
|
45 |
|
|
"\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
|
46 |
|
|
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
|
47 |
|
|
"\r\000/"; /* 0x60 - 0x6f */
|
48 |
|
|
#endif
|
49 |
|
|
|
50 |
|
|
/* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/
|
51 |
|
|
/* 0x00 means not a valid entry or no conversion known */
|
52 |
|
|
|
53 |
|
|
unsigned static char q40cl[256] =
|
54 |
|
|
{/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
|
55 |
|
|
0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00, /* 0x00 - 0x0f */
|
56 |
|
|
0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00, /* 0x10 - 0x1f */
|
57 |
|
|
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 ???*/
|
58 |
|
|
0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00, /* 0x30 - 0x3f */
|
59 |
|
|
0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00, /* 0x40 - 0x4f */
|
60 |
|
|
0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00, /* 0x50 - 0x5f*/
|
61 |
|
|
0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f */
|
62 |
|
|
0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00, /* 0x70 - 0x7f */
|
63 |
|
|
0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f 0x84/0x37 is SySrq*/
|
64 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f */
|
65 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf */
|
66 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf */
|
67 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf */
|
68 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf */
|
69 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef */
|
70 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf0 - 0xff */
|
71 |
|
|
};
|
72 |
|
|
|
73 |
|
|
/* another table, AT 0xe0 codes to PC 0xe0 codes,
|
74 |
|
|
0xff special entry for SysRq - DROPPED right now */
|
75 |
|
|
static unsigned char q40ecl[]=
|
76 |
|
|
{/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
|
77 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x00 - 0x0f*/
|
78 |
|
|
0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x10 - 0x1f */
|
79 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x20 - 0x2f*/
|
80 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x30 - 0x3f*/
|
81 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00, /* 0x40 - 0x4f*/
|
82 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00, /* 0x50 - 0x5f*/
|
83 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f*/
|
84 |
|
|
0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00, /* 0x70 - 0x7f*/
|
85 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f*/
|
86 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f*/
|
87 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf*/
|
88 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf*/
|
89 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf*/
|
90 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf*/
|
91 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef*/
|
92 |
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 0xf0 - 0xff*/
|
93 |
|
|
};
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
|
97 |
|
|
|
98 |
|
|
|
99 |
|
|
/*
|
100 |
|
|
* Translation of escaped scancodes to keycodes.
|
101 |
|
|
* This is now user-settable.
|
102 |
|
|
* The keycodes 1-88,96-111,119 are fairly standard, and
|
103 |
|
|
* should probably not be changed - changing might confuse X.
|
104 |
|
|
* X also interprets scancode 0x5d (KEY_Begin).
|
105 |
|
|
*
|
106 |
|
|
* For 1-88 keycode equals scancode.
|
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 /* (control-pause) */
|
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 |
|
|
* The keycodes below are randomly located in 89-95,112-118,120-127.
|
130 |
|
|
* They could be thrown away (and all occurrences below replaced by 0),
|
131 |
|
|
* but that would force many users to use the `setkeycodes' utility, where
|
132 |
|
|
* they needed not before. It does not matter that there are duplicates, as
|
133 |
|
|
* long as no duplication occurs for any single keyboard.
|
134 |
|
|
*/
|
135 |
|
|
#define SC_LIM 89
|
136 |
|
|
|
137 |
|
|
#define FOCUS_PF1 85 /* actual code! */
|
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 |
|
|
/* tfj@olivia.ping.dk:
|
152 |
|
|
* The four keys are located over the numeric keypad, and are
|
153 |
|
|
* labelled A1-A4. It's an rc930 keyboard, from
|
154 |
|
|
* Regnecentralen/RC International, Now ICL.
|
155 |
|
|
* Scancodes: 59, 5a, 5b, 5c.
|
156 |
|
|
*/
|
157 |
|
|
#define RGN1 124
|
158 |
|
|
#define RGN2 125
|
159 |
|
|
#define RGN3 126
|
160 |
|
|
#define RGN4 127
|
161 |
|
|
|
162 |
|
|
static unsigned char high_keys[128 - SC_LIM] = {
|
163 |
|
|
RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
|
164 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
|
165 |
|
|
0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
|
166 |
|
|
0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
|
167 |
|
|
FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
|
168 |
|
|
FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
|
169 |
|
|
};
|
170 |
|
|
|
171 |
|
|
/* BTC */
|
172 |
|
|
#define E0_MACRO 112
|
173 |
|
|
/* LK450 */
|
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 |
|
|
* My OmniKey generates e0 4c for the "OMNI" key and the
|
182 |
|
|
* right alt key does nada. [kkoller@nyx10.cs.du.edu]
|
183 |
|
|
*/
|
184 |
|
|
#define E0_OK 124
|
185 |
|
|
/*
|
186 |
|
|
* New microsoft keyboard is rumoured to have
|
187 |
|
|
* e0 5b (left window button), e0 5c (right window button),
|
188 |
|
|
* e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
|
189 |
|
|
* [or: Windows_L, Windows_R, TaskMan]
|
190 |
|
|
*/
|
191 |
|
|
#define E0_MSLW 125
|
192 |
|
|
#define E0_MSRW 126
|
193 |
|
|
#define E0_MSTM 127
|
194 |
|
|
|
195 |
|
|
/* this can be changed using setkeys : */
|
196 |
|
|
static unsigned char e0_keys[128] = {
|
197 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
|
198 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
|
199 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
|
200 |
|
|
0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
|
201 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
|
202 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
|
203 |
|
|
0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
|
204 |
|
|
E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
|
205 |
|
|
E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
|
206 |
|
|
E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
|
207 |
|
|
E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
|
208 |
|
|
0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
|
209 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
|
210 |
|
|
0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
|
211 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
|
212 |
|
|
0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
|
213 |
|
|
};
|
214 |
|
|
|
215 |
|
|
|
216 |
|
|
int 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 |
|
|
|
227 |
|
|
int 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 |
|
|
|
242 |
|
|
int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
|
243 |
|
|
char raw_mode)
|
244 |
|
|
{
|
245 |
|
|
static int prev_scancode;
|
246 |
|
|
|
247 |
|
|
/* special prefix scancodes.. */
|
248 |
|
|
if (scancode == 0xe0 || scancode == 0xe1) {
|
249 |
|
|
prev_scancode = scancode;
|
250 |
|
|
return 0;
|
251 |
|
|
}
|
252 |
|
|
|
253 |
|
|
/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
|
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 |
|
|
* usually it will be 0xe0, but a Pause key generates
|
264 |
|
|
* e1 1d 45 e1 9d c5 when pressed, and nothing when released
|
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 |
|
|
* The keyboard maintains its own internal caps lock and
|
285 |
|
|
* num lock statuses. In caps lock mode E0 AA precedes make
|
286 |
|
|
* code and E0 2A follows break code. In num lock mode,
|
287 |
|
|
* E0 2A precedes make code and E0 AA follows break code.
|
288 |
|
|
* We do our own book-keeping, so we will just ignore these.
|
289 |
|
|
*/
|
290 |
|
|
/*
|
291 |
|
|
* For my keyboard there is no caps lock mode, but there are
|
292 |
|
|
* both Shift-L and Shift-R modes. The former mode generates
|
293 |
|
|
* E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
|
294 |
|
|
* So, we should also ignore the latter. - aeb@cwi.nl
|
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 |
|
|
/* This happens with the FOCUS 9000 keyboard
|
312 |
|
|
Its keys PF1..PF12 are reported to generate
|
313 |
|
|
55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
|
314 |
|
|
Moreover, unless repeated, they do not generate
|
315 |
|
|
key-down events, so we have to zero up_flag below */
|
316 |
|
|
/* Also, Japanese 86/106 keyboards are reported to
|
317 |
|
|
generate 0x73 and 0x7d for \ - and \ | respectively. */
|
318 |
|
|
/* Also, some Brazilian keyboard is reported to produce
|
319 |
|
|
0x73 and 0x7e for \ ? and KP-dot, respectively. */
|
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 |
|
|
|
337 |
|
|
char q40kbd_unexpected_up(unsigned char keycode)
|
338 |
|
|
{
|
339 |
|
|
/* unexpected, but this can happen: maybe this was a key release for a
|
340 |
|
|
FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
|
341 |
|
|
if (keycode >= SC_LIM || keycode == 85)
|
342 |
|
|
return 0;
|
343 |
|
|
else
|
344 |
|
|
return 0200;
|
345 |
|
|
}
|
346 |
|
|
|
347 |
|
|
static int keyup=0;
|
348 |
|
|
static int qprev=0;
|
349 |
|
|
|
350 |
|
|
static 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 |
|
|
/* next line is last resort to hanlde some oddities */
|
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) /* SySrq */
|
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 |
|
|
}
|
394 |
|
|
exit:
|
395 |
|
|
spin_unlock(&kbd_controller_lock);
|
396 |
|
|
master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
|
397 |
|
|
}
|
398 |
|
|
|
399 |
|
|
|
400 |
|
|
#define KBD_NO_DATA (-1) /* No data */
|
401 |
|
|
#define KBD_BAD_DATA (-2) /* Parity or other error */
|
402 |
|
|
|
403 |
|
|
static 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 |
|
|
|
419 |
|
|
static void __init kbd_clear_input(void)
|
420 |
|
|
{
|
421 |
|
|
int maxread = 100; /* Random number */
|
422 |
|
|
|
423 |
|
|
do {
|
424 |
|
|
if (q40kbd_read_input() == KBD_NO_DATA)
|
425 |
|
|
break;
|
426 |
|
|
} while (--maxread);
|
427 |
|
|
}
|
428 |
|
|
|
429 |
|
|
|
430 |
|
|
int __init q40kbd_init_hw(void)
|
431 |
|
|
{
|
432 |
|
|
|
433 |
|
|
/* Flush any pending input. */
|
434 |
|
|
kbd_clear_input();
|
435 |
|
|
|
436 |
|
|
/* Ok, finally allocate the IRQ, and off we go.. */
|
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 |
|
|
|