Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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