setup enviroment for compilation
[linux-2.4.21-pre4.git] / drivers / tc / lk201.c
1 /*
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de>
8  * Copyright (C) 2001, 2002  Maciej W. Rozycki <macro@ds2.pg.gda.pl>
9  */
10
11 #include <linux/config.h>
12
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/tty.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/kbd_ll.h>
20 #include <linux/kbd_kern.h>
21 #include <linux/vt_kern.h>
22
23 #include <asm/keyboard.h>
24 #include <asm/dec/tc.h>
25 #include <asm/dec/machtype.h>
26
27 #include "zs.h"
28 #include "lk201.h"
29
30 /* Simple translation table for the SysRq keys */
31
32 #ifdef CONFIG_MAGIC_SYSRQ
33 /*
34  * Actually no translation at all, at least until we figure out
35  * how to define SysRq for LK201 and friends. --macro
36  */
37 unsigned char lk201_sysrq_xlate[128];
38 unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate;
39
40 unsigned char kbd_sysrq_key = -1;
41 #endif
42
43 #define KEYB_LINE       3
44
45 static int __init lk201_init(struct dec_serial *);
46 static void __init lk201_info(struct dec_serial *);
47 static void lk201_kbd_rx_char(unsigned char, unsigned char);
48
49 struct zs_hook lk201_kbdhook = {
50         init_channel:   lk201_init,
51         init_info:      lk201_info,
52         rx_char:        NULL,
53         poll_rx_char:   NULL,
54         poll_tx_char:   NULL,
55         cflags:         B4800 | CS8 | CSTOPB | CLOCAL
56 };
57
58 /*
59  * This is used during keyboard initialisation
60  */
61 static unsigned char lk201_reset_string[] = {
62         LK_CMD_SET_DEFAULTS,
63         LK_CMD_MODE(LK_MODE_RPT_DOWN, 1),
64         LK_CMD_MODE(LK_MODE_RPT_DOWN, 2),
65         LK_CMD_MODE(LK_MODE_RPT_DOWN, 3),
66         LK_CMD_MODE(LK_MODE_RPT_DOWN, 4),
67         LK_CMD_MODE(LK_MODE_DOWN_UP, 5),
68         LK_CMD_MODE(LK_MODE_DOWN_UP, 6),
69         LK_CMD_MODE(LK_MODE_RPT_DOWN, 7),
70         LK_CMD_MODE(LK_MODE_RPT_DOWN, 8),
71         LK_CMD_MODE(LK_MODE_RPT_DOWN, 9),
72         LK_CMD_MODE(LK_MODE_RPT_DOWN, 10),
73         LK_CMD_MODE(LK_MODE_RPT_DOWN, 11),
74         LK_CMD_MODE(LK_MODE_RPT_DOWN, 12),
75         LK_CMD_MODE(LK_MODE_DOWN, 13),
76         LK_CMD_MODE(LK_MODE_RPT_DOWN, 14),
77         LK_CMD_DIS_KEYCLK,
78         LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
79 };
80
81 static struct dec_serial* lk201kbd_info;
82
83 static int lk201_send(struct dec_serial *info, unsigned char ch)
84 {
85         if (info->hook->poll_tx_char(info, ch)) {
86                 printk(KERN_ERR "lk201: transmit timeout\n");
87                 return -EIO;
88         }
89         return 0;
90 }
91
92 static inline int lk201_get_id(struct dec_serial *info)
93 {
94         return lk201_send(info, LK_CMD_REQ_ID);
95 }
96
97 static int lk201_reset(struct dec_serial *info)
98 {
99         int i, r;
100
101         for (i = 0; i < sizeof(lk201_reset_string); i++) {
102                 r = lk201_send(info, lk201_reset_string[i]);
103                 if (r < 0)
104                         return r;
105         }
106         return 0;
107 }
108
109 static void lk201_report(unsigned char id[6])
110 {
111         char *report = "lk201: keyboard attached, ";
112
113         switch (id[2]) {
114         case LK_STAT_PWRUP_OK:
115                 printk(KERN_INFO "%sself-test OK\n", report);
116                 break;
117         case LK_STAT_PWRUP_KDOWN:
118                 /* The keyboard will resend the power-up ID
119                    after all keys are released, so we don't
120                    bother handling the error specially.  Still
121                    there may be a short-circuit inside.
122                  */
123                 printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n",
124                        report, id[3]);
125                 break;
126         case LK_STAT_PWRUP_ERROR:
127                 printk(KERN_ERR "%sself-test failure\n", report);
128                 break;
129         default:
130                 printk(KERN_ERR "%sunknown error: 0x%02x\n",
131                        report, id[2]);
132         }
133 }
134
135 static void lk201_id(unsigned char id[6])
136 {
137         /*
138          * Report whether there is an LK201 or an LK401
139          * The LK401 has ALT keys...
140          */
141         switch (id[4]) {
142         case 1:
143                 printk(KERN_INFO "lk201: LK201 detected\n");
144                 break;
145         case 2:
146                 printk(KERN_INFO "lk201: LK401 detected\n");
147                 break;
148         default:
149                 printk(KERN_WARNING
150                        "lk201: unknown keyboard detected, ID %d\n", id[4]);
151                 printk(KERN_WARNING "lk201: ... please report to "
152                        "<linux-mips@oss.sgi.com>\n");
153         }
154 }
155
156 #define DEFAULT_KEYB_REP_DELAY  (250/5) /* [5ms] */
157 #define DEFAULT_KEYB_REP_RATE   30      /* [cps] */
158
159 static struct kbd_repeat kbdrate = {
160         DEFAULT_KEYB_REP_DELAY,
161         DEFAULT_KEYB_REP_RATE
162 };
163
164 static void parse_kbd_rate(struct kbd_repeat *r)
165 {
166         if (r->delay <= 0)
167                 r->delay = kbdrate.delay;
168         if (r->rate <= 0)
169                 r->rate = kbdrate.rate;
170
171         if (r->delay < 5)
172                 r->delay = 5;
173         if (r->delay > 630)
174                 r->delay = 630;
175         if (r->rate < 12)
176                 r->rate = 12;
177         if (r->rate > 127)
178                 r->rate = 127;
179         if (r->rate == 125)
180                 r->rate = 124;
181 }
182
183 static int write_kbd_rate(struct kbd_repeat *rep)
184 {
185         struct dec_serial* info = lk201kbd_info;
186         int delay, rate;
187         int i;
188
189         delay = rep->delay / 5;
190         rate = rep->rate;
191         for (i = 0; i < 4; i++) {
192                 if (info->hook->poll_tx_char(info, LK_CMD_RPT_RATE(i)))
193                         return 1;
194                 if (info->hook->poll_tx_char(info, LK_PARAM_DELAY(delay)))
195                         return 1;
196                 if (info->hook->poll_tx_char(info, LK_PARAM_RATE(rate)))
197                         return 1;
198         }
199         return 0;
200 }
201
202 static int lk201kbd_rate(struct kbd_repeat *rep)
203 {
204         if (rep == NULL)
205                 return -EINVAL;
206
207         parse_kbd_rate(rep);
208
209         if (write_kbd_rate(rep)) {
210                 memcpy(rep, &kbdrate, sizeof(struct kbd_repeat));
211                 return -EIO;
212         }
213
214         memcpy(&kbdrate, rep, sizeof(struct kbd_repeat));
215
216         return 0;
217 }
218
219 static void lk201kd_mksound(unsigned int hz, unsigned int ticks)
220 {
221         struct dec_serial* info = lk201kbd_info;
222
223         if (!ticks)
224                 return;
225
226         /*
227          * Can't set frequency and we "approximate"
228          * duration by volume. ;-)
229          */
230         ticks /= HZ / 32;
231         if (ticks > 7)
232                 ticks = 7;
233         ticks = 7 - ticks;
234
235         if (info->hook->poll_tx_char(info, LK_CMD_ENB_BELL))
236                 return;
237         if (info->hook->poll_tx_char(info, LK_PARAM_VOLUME(ticks)))
238                 return;
239         if (info->hook->poll_tx_char(info, LK_CMD_BELL))
240                 return;
241 }
242
243 void kbd_leds(unsigned char leds)
244 {
245         struct dec_serial* info = lk201kbd_info;
246         unsigned char l = 0;
247
248         if (!info)              /* FIXME */
249                 return;
250
251         /* FIXME -- Only Hold and Lock LEDs for now. --macro */
252         if (leds & LED_SCR)
253                 l |= LK_LED_HOLD;
254         if (leds & LED_CAP)
255                 l |= LK_LED_LOCK;
256
257         if (info->hook->poll_tx_char(info, LK_CMD_LEDS_ON))
258                 return;
259         if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(l)))
260                 return;
261         if (info->hook->poll_tx_char(info, LK_CMD_LEDS_OFF))
262                 return;
263         if (info->hook->poll_tx_char(info, LK_PARAM_LED_MASK(~l)))
264                 return;
265 }
266
267 int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
268 {
269         return -EINVAL;
270 }
271
272 int kbd_getkeycode(unsigned int scancode)
273 {
274         return -EINVAL;
275 }
276
277 int kbd_translate(unsigned char scancode, unsigned char *keycode,
278                   char raw_mode)
279 {
280         *keycode = scancode;
281         return 1;
282 }
283
284 char kbd_unexpected_up(unsigned char keycode)
285 {
286         return 0x80;
287 }
288
289 static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat)
290 {
291         static unsigned char id[6];
292         static int id_i;
293
294         static int shift_state = 0;
295         static int prev_scancode;
296         unsigned char c = scancodeRemap[ch];
297
298         if (stat && stat != 4) {
299                 printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n",
300                        stat);
301                 return;
302         }
303
304         /* Assume this is a power-up ID. */
305         if (ch == LK_STAT_PWRUP_ID && !id_i) {
306                 id[id_i++] = ch;
307                 return;
308         }
309
310         /* Handle the power-up sequence. */
311         if (id_i) {
312                 id[id_i++] = ch;
313                 if (id_i == 4) {
314                         /* OK, the power-up concluded. */
315                         lk201_report(id);
316                         if (id[2] == LK_STAT_PWRUP_OK)
317                                 lk201_get_id(lk201kbd_info);
318                         else {
319                                 id_i = 0;
320                                 printk(KERN_ERR "lk201: keyboard power-up "
321                                        "error, skipping initialization\n");
322                         }
323                 } else if (id_i == 6) {
324                         /* We got the ID; report it and start an operation. */
325                         id_i = 0;
326                         lk201_id(id);
327                         lk201_reset(lk201kbd_info);
328                 }
329                 return;
330         }
331
332         /* Everything else is a scancode/status response. */
333         id_i = 0;
334         switch (ch) {
335         case LK_STAT_RESUME_ERR:
336         case LK_STAT_ERROR:
337         case LK_STAT_INHIBIT_ACK:
338         case LK_STAT_TEST_ACK:
339         case LK_STAT_MODE_KEYDOWN:
340         case LK_STAT_MODE_ACK:
341                 break;
342         case LK_KEY_LOCK:
343                 shift_state ^= LK_LOCK;
344                 handle_scancode(c, shift_state && LK_LOCK ? 1 : 0);
345                 break;
346         case LK_KEY_SHIFT:
347                 shift_state ^= LK_SHIFT;
348                 handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0);
349                 break;
350         case LK_KEY_CTRL:
351                 shift_state ^= LK_CTRL;
352                 handle_scancode(c, shift_state && LK_CTRL ? 1 : 0);
353                 break;
354         case LK_KEY_COMP:
355                 shift_state ^= LK_COMP;
356                 handle_scancode(c, shift_state && LK_COMP ? 1 : 0);
357                 break;
358         case LK_KEY_RELEASE:
359                 if (shift_state & LK_SHIFT)
360                         handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0);
361                 if (shift_state & LK_CTRL)
362                         handle_scancode(scancodeRemap[LK_KEY_CTRL], 0);
363                 if (shift_state & LK_COMP)
364                         handle_scancode(scancodeRemap[LK_KEY_COMP], 0);
365                 if (shift_state & LK_LOCK)
366                         handle_scancode(scancodeRemap[LK_KEY_LOCK], 0);
367                 shift_state = 0;
368                 break;
369         case LK_KEY_REPEAT:
370                 handle_scancode(prev_scancode, 1);
371                 break;
372         default:
373                 prev_scancode = c;
374                 handle_scancode(c, 1);
375                 break;
376         }
377         tasklet_schedule(&keyboard_tasklet);
378 }
379
380 static void __init lk201_info(struct dec_serial *info)
381 {
382 }
383
384 static int __init lk201_init(struct dec_serial *info)
385 {
386         /* First install handlers. */
387         lk201kbd_info = info;
388         kbd_rate = lk201kbd_rate;
389         kd_mksound = lk201kd_mksound;
390
391         info->hook->rx_char = lk201_kbd_rx_char;
392
393         /* Then just issue a reset -- the handlers will do the rest. */
394         lk201_send(info, LK_CMD_POWER_UP);
395
396         return 0;
397 }
398
399 void __init kbd_init_hw(void)
400 {
401         extern int register_zs_hook(unsigned int, struct zs_hook *);
402         extern int unregister_zs_hook(unsigned int);
403
404         /* Maxine uses LK501 at the Access.Bus. */
405         if (mips_machtype == MACH_DS5000_XX)
406                 return;
407
408         printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n");
409
410         if (TURBOCHANNEL) {
411                 /*
412                  * kbd_init_hw() is being called before
413                  * rs_init() so just register the kbd hook
414                  * and let zs_init do the rest :-)
415                  */
416                 if (mips_machtype == MACH_DS5000_200)
417                         printk(KERN_ERR "lk201: support for DS5000/200 "
418                                "not yet ready.\n");
419                 else
420                         if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook))
421                                 unregister_zs_hook(KEYB_LINE);
422         } else {
423                 /*
424                  * TODO: modify dz.c to allow similar hooks
425                  * for LK201 handling on DS2100, DS3100, and DS5000/200
426                  */
427                 printk(KERN_ERR "lk201: support for DS3100 not yet ready.\n");
428         }
429 }