MPSAFE - TTY & related drivers
[dragonfly.git] / sys / dev / misc / kbd / atkbd.c
1 /*-
2  * (MPSAFE)
3  *
4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer as
12  *    the first lines of this file unmodified.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/dev/kbd/atkbd.c,v 1.25.2.4 2002/04/08 19:21:38 asmodai Exp $
29  * $DragonFly: src/sys/dev/misc/kbd/atkbd.c,v 1.14 2007/04/22 10:43:00 y0netan1 Exp $
30  */
31
32 #include "opt_kbd.h"
33 #include "opt_atkbd.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/bus.h>
39 #include <sys/proc.h>
40 #include <sys/malloc.h>
41 #include <sys/thread2.h>
42
43 #ifdef __i386__
44 #include <machine/md_var.h>
45 #include <machine/psl.h>
46 #include <machine/vm86.h>
47 #include <machine/pc/bios.h>
48
49 #include <vm/vm.h>
50 #include <vm/pmap.h>
51 #endif /* __i386__ */
52
53 #include <sys/kbio.h>
54 #include "kbdreg.h"
55 #include "atkbdreg.h"
56 #include "atkbdcreg.h"
57
58 #include <bus/isa/isareg.h>
59
60 #if 0
61 #define lwkt_gettoken(x)
62 #define lwkt_reltoken(x)
63 #endif
64
65 static timeout_t        atkbd_timeout;
66
67 int
68 atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
69 {
70         keyboard_switch_t *sw;
71         int args[2];
72         int error;
73
74         lwkt_gettoken(&tty_token);
75         sw = kbd_get_switch(ATKBD_DRIVER_NAME);
76         if (sw == NULL) {
77                 lwkt_reltoken(&tty_token);
78                 return ENXIO;
79         }
80
81         args[0] = ctlr;
82         args[1] = irq;
83         error = (*sw->probe)(unit, args, flags);
84
85         lwkt_reltoken(&tty_token);
86
87         if (error)
88                 return error;
89         return 0;
90 }
91
92 int
93 atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
94 {
95         keyboard_switch_t *sw;
96         int args[2];
97         int error;
98
99         lwkt_gettoken(&tty_token);
100
101         sw = kbd_get_switch(ATKBD_DRIVER_NAME);
102         if (sw == NULL) {
103                 lwkt_reltoken(&tty_token);
104                 return ENXIO;
105         }
106
107         /* reset, initialize and enable the device */
108         args[0] = ctlr;
109         args[1] = irq;
110         *kbd = NULL;
111         error = (*sw->probe)(unit, args, flags);
112         if (error) {
113                 lwkt_reltoken(&tty_token);
114                 return error;
115         }
116         error = (*sw->init)(unit, kbd, args, flags);
117         if (error) {
118                 lwkt_reltoken(&tty_token);
119                 return error;
120         }
121         (*sw->enable)(*kbd);
122
123 #ifdef KBD_INSTALL_CDEV
124         /* attach a virtual keyboard cdev */
125         error = kbd_attach(*kbd);
126         if (error) {
127                 lwkt_reltoken(&tty_token);
128                 return error;
129         }
130 #endif
131
132         /*
133          * This is a kludge to compensate for lost keyboard interrupts.
134          * A similar code used to be in syscons. See below. XXX
135          */
136         atkbd_timeout(*kbd);
137
138         if (bootverbose)
139                 (*sw->diag)(*kbd, bootverbose);
140
141         lwkt_reltoken(&tty_token);
142         return 0;
143 }
144
145 static void
146 atkbd_timeout(void *arg)
147 {
148         keyboard_t *kbd;
149
150         /*
151          * The original text of the following comments are extracted 
152          * from syscons.c (1.287)
153          * 
154          * With release 2.1 of the Xaccel server, the keyboard is left
155          * hanging pretty often. Apparently an interrupt from the
156          * keyboard is lost, and I don't know why (yet).
157          * This ugly hack calls the low-level interrupt routine if input
158          * is ready for the keyboard and conveniently hides the problem. XXX
159          *
160          * Try removing anything stuck in the keyboard controller; whether
161          * it's a keyboard scan code or mouse data. The low-level
162          * interrupt routine doesn't read the mouse data directly, 
163          * but the keyboard controller driver will, as a side effect.
164          */
165         /*
166          * And here is bde's original comment about this:
167          *
168          * This is necessary to handle edge triggered interrupts - if we
169          * returned when our IRQ is high due to unserviced input, then there
170          * would be no more keyboard IRQs until the keyboard is reset by
171          * external powers.
172          *
173          * The keyboard apparently unwedges the irq in most cases.
174          */
175         crit_enter();
176         lwkt_gettoken(&tty_token);
177         kbd = (keyboard_t *)arg;
178         if (kbd_lock(kbd, TRUE)) {
179                 /*
180                  * We have seen the lock flag is not set. Let's reset
181                  * the flag early, otherwise the LED update routine fails
182                  * which may want the lock during the interrupt routine.
183                  */
184                 kbd_lock(kbd, FALSE);
185                 if (kbd_check_char(kbd))
186                         kbd_intr(kbd, NULL);
187         }
188         callout_reset(&kbd->kb_atkbd_timeout_ch, hz / 10, atkbd_timeout, arg);
189         lwkt_reltoken(&tty_token);
190         crit_exit();
191 }
192
193 /* LOW-LEVEL */
194
195 #include <machine/limits.h>
196 #include <machine/clock.h>
197
198 #define ATKBD_DEFAULT   0
199
200 typedef struct atkbd_state {
201         KBDC            kbdc;           /* keyboard controller */
202         int             ks_mode;        /* input mode (K_XLATE,K_RAW,K_CODE) */
203         int             ks_flags;       /* flags */
204 #define COMPOSE         (1 << 0)
205         int             ks_polling;
206         int             ks_state;       /* shift/lock key state */
207         int             ks_accents;     /* accent key index (> 0) */
208         u_int           ks_composed_char; /* composed char code (> 0) */
209         u_char          ks_prefix;      /* AT scan code prefix */
210 } atkbd_state_t;
211
212 /* keyboard driver declaration */
213 static int              atkbd_configure(int flags);
214 static kbd_probe_t      atkbd_probe;
215 static kbd_init_t       atkbd_init;
216 static kbd_term_t       atkbd_term;
217 static kbd_intr_t       atkbd_intr;
218 static kbd_test_if_t    atkbd_test_if;
219 static kbd_enable_t     atkbd_enable;
220 static kbd_disable_t    atkbd_disable;
221 static kbd_read_t       atkbd_read;
222 static kbd_check_t      atkbd_check;
223 static kbd_read_char_t  atkbd_read_char;
224 static kbd_check_char_t atkbd_check_char;
225 static kbd_ioctl_t      atkbd_ioctl;
226 static kbd_lock_t       atkbd_lock;
227 static kbd_clear_state_t atkbd_clear_state;
228 static kbd_get_state_t  atkbd_get_state;
229 static kbd_set_state_t  atkbd_set_state;
230 static kbd_poll_mode_t  atkbd_poll;
231
232 keyboard_switch_t atkbdsw = {
233         atkbd_probe,
234         atkbd_init,
235         atkbd_term,
236         atkbd_intr,
237         atkbd_test_if,
238         atkbd_enable,
239         atkbd_disable,
240         atkbd_read,
241         atkbd_check,
242         atkbd_read_char,
243         atkbd_check_char,
244         atkbd_ioctl,
245         atkbd_lock,
246         atkbd_clear_state,
247         atkbd_get_state,
248         atkbd_set_state,
249         genkbd_get_fkeystr,
250         atkbd_poll,
251         genkbd_diag,
252 };
253
254 KEYBOARD_DRIVER(atkbd, atkbdsw, atkbd_configure);
255
256 /* local functions */
257 static int              get_typematic(keyboard_t *kbd);
258 static int              setup_kbd_port(KBDC kbdc, int port, int intr);
259 static int              get_kbd_echo(KBDC kbdc);
260 static int              probe_keyboard(KBDC kbdc, int flags);
261 static int              init_keyboard(KBDC kbdc, int *type, int flags);
262 static int              write_kbd(KBDC kbdc, int command, int data);
263 static int              get_kbd_id(KBDC kbdc);
264 static int              typematic(int delay, int rate);
265 static int              typematic_delay(int delay);
266 static int              typematic_rate(int rate);
267
268 /* local variables */
269
270 /* the initial key map, accent map and fkey strings */
271 #ifdef ATKBD_DFLT_KEYMAP
272 #define KBD_DFLT_KEYMAP
273 #include "atkbdmap.h"
274 #endif
275 #include "kbdtables.h"
276
277 /* structures for the default keyboard */
278 static keyboard_t       default_kbd;
279 static atkbd_state_t    default_kbd_state;
280 static keymap_t         default_keymap;
281 static accentmap_t      default_accentmap;
282 static fkeytab_t        default_fkeytab[NUM_FKEYS];
283
284 /* 
285  * The back door to the keyboard driver!
286  * This function is called by the console driver, via the kbdio module,
287  * to tickle keyboard drivers when the low-level console is being initialized.
288  * Almost nothing in the kernel has been initialied yet.  Try to probe
289  * keyboards if possible.
290  * NOTE: because of the way the low-level console is initialized, this routine
291  * may be called more than once!!
292  */
293 static int
294 atkbd_configure(int flags)
295 {
296         keyboard_t *kbd;
297         int arg[2];
298         int i;
299
300         lwkt_gettoken(&tty_token);
301
302         /*
303          * Probe the keyboard controller, if not present or if the driver
304          * is disabled, unregister the keyboard if any.
305          */
306         if (atkbdc_configure() != 0 ||
307             resource_disabled("atkbd", ATKBD_DEFAULT)) {
308                 i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT);
309                 if (i >= 0) {
310                         kbd = kbd_get_keyboard(i);
311                         kbd_unregister(kbd);
312                         kbd->kb_flags &= ~KB_REGISTERED;
313                 }
314                 lwkt_reltoken(&tty_token);
315                 return 0;
316         }
317         
318         /* XXX: a kludge to obtain the device configuration flags */
319         if (resource_int_value("atkbd", ATKBD_DEFAULT, "flags", &i) == 0)
320                 flags |= i;
321
322         /* probe the default keyboard */
323         arg[0] = -1;
324         arg[1] = -1;
325         kbd = NULL;
326         if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) {
327                 lwkt_reltoken(&tty_token);
328                 return 0;
329         }
330         if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) {
331                 lwkt_reltoken(&tty_token);
332                 return 0;
333         }
334
335         /* return the number of found keyboards */
336         lwkt_reltoken(&tty_token);
337         return 1;
338 }
339
340 /* low-level functions */
341
342 /* detect a keyboard */
343 static int
344 atkbd_probe(int unit, void *arg, int flags)
345 {
346         KBDC kbdc;
347         int *data = (int *)arg; /* data[0]: controller, data[1]: irq */
348
349         lwkt_gettoken(&tty_token);
350
351         if (unit == ATKBD_DEFAULT) {
352                 if (KBD_IS_PROBED(&default_kbd)) {
353                         lwkt_reltoken(&tty_token);
354                         return 0;
355                 }
356         }
357
358         kbdc = atkbdc_open(data[0]);
359         if (kbdc == NULL) {
360                 lwkt_reltoken(&tty_token);
361                 return ENXIO;
362         }
363         if (probe_keyboard(kbdc, flags)) {
364                 if (flags & KB_CONF_FAIL_IF_NO_KBD) {
365                         lwkt_reltoken(&tty_token);
366                         return ENXIO;
367                 }
368         }
369
370         lwkt_reltoken(&tty_token);
371         return 0;
372 }
373
374 /* reset and initialize the device */
375 static int
376 atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
377 {
378         keyboard_t *kbd;
379         atkbd_state_t *state;
380         keymap_t *keymap;
381         accentmap_t *accmap;
382         fkeytab_t *fkeymap;
383         int fkeymap_size;
384         int delay[2];
385         int *data = (int *)arg; /* data[0]: controller, data[1]: irq */
386
387         lwkt_gettoken(&tty_token);
388
389         /* XXX */
390         if (unit == ATKBD_DEFAULT) {
391                 *kbdp = kbd = &default_kbd;
392                 if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) {
393                         lwkt_reltoken(&tty_token);
394                         return 0;
395                 }
396                 state = &default_kbd_state;
397                 keymap = &default_keymap;
398                 accmap = &default_accentmap;
399                 fkeymap = default_fkeytab;
400                 fkeymap_size =
401                         sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
402         } else if (*kbdp == NULL) {
403                 *kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_WAITOK|M_ZERO);
404                 state = kmalloc(sizeof(*state), M_DEVBUF, M_WAITOK|M_ZERO);
405                 keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_WAITOK);
406                 accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_WAITOK);
407                 fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_WAITOK);
408                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
409         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
410                 lwkt_reltoken(&tty_token);
411                 return 0;
412         } else {
413                 kbd = *kbdp;
414                 state = (atkbd_state_t *)kbd->kb_data;
415                 bzero(state, sizeof(*state));
416                 keymap = kbd->kb_keymap;
417                 accmap = kbd->kb_accentmap;
418                 fkeymap = kbd->kb_fkeytab;
419                 fkeymap_size = kbd->kb_fkeytab_size;
420         }
421
422         if (!KBD_IS_PROBED(kbd)) {
423                 state->kbdc = atkbdc_open(data[0]);
424                 if (state->kbdc == NULL) {
425                         lwkt_reltoken(&tty_token);
426                         return ENXIO;
427                 }
428                 kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
429                                 KB_PRI_ATKBD, 0, 0);
430                 bcopy(&key_map, keymap, sizeof(key_map));
431                 bcopy(&accent_map, accmap, sizeof(accent_map));
432                 bcopy(fkey_tab, fkeymap,
433                       imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
434                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
435                 kbd->kb_data = (void *)state;
436         
437                 if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
438                         if (flags & KB_CONF_FAIL_IF_NO_KBD) {
439                                 lwkt_reltoken(&tty_token);
440                                 return ENXIO;
441                         }
442                 } else {
443                         KBD_FOUND_DEVICE(kbd);
444                 }
445                 atkbd_clear_state(kbd);
446                 state->ks_mode = K_XLATE;
447                 /* 
448                  * FIXME: set the initial value for lock keys in ks_state
449                  * according to the BIOS data?
450                  */
451                 KBD_PROBE_DONE(kbd);
452         }
453         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
454                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
455                 if (KBD_HAS_DEVICE(kbd)
456                     && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
457                     && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
458                         lwkt_reltoken(&tty_token);
459                         return ENXIO;
460                 }
461                 atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
462                 get_typematic(kbd);
463                 delay[0] = kbd->kb_delay1;
464                 delay[1] = kbd->kb_delay2;
465                 atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
466                 KBD_INIT_DONE(kbd);
467         }
468         if (!KBD_IS_CONFIGURED(kbd)) {
469                 if (kbd_register(kbd) < 0) {
470                         lwkt_reltoken(&tty_token);
471                         return ENXIO;
472                 }
473                 KBD_CONFIG_DONE(kbd);
474         }
475
476         lwkt_reltoken(&tty_token);
477         return 0;
478 }
479
480 /* finish using this keyboard */
481 static int
482 atkbd_term(keyboard_t *kbd)
483 {
484         lwkt_gettoken(&tty_token);
485         kbd_unregister(kbd);
486         lwkt_reltoken(&tty_token);
487         return 0;
488 }
489
490 /* keyboard interrupt routine */
491 static int
492 atkbd_intr(keyboard_t *kbd, void *arg)
493 {
494         atkbd_state_t *state;
495         int delay[2];
496         int c;
497
498         lwkt_gettoken(&tty_token);
499         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
500                 /* let the callback function to process the input */
501                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
502                                             kbd->kb_callback.kc_arg);
503         } else {
504                 /* read and discard the input; no one is waiting for input */
505                 do {
506                         c = atkbd_read_char(kbd, FALSE);
507                 } while (c != NOKEY);
508
509                 if (!KBD_HAS_DEVICE(kbd)) {
510                         /*
511                          * The keyboard was not detected before;
512                          * it must have been reconnected!
513                          */
514                         state = (atkbd_state_t *)kbd->kb_data;
515                         init_keyboard(state->kbdc, &kbd->kb_type,
516                                       kbd->kb_config);
517                         atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
518                         get_typematic(kbd);
519                         delay[0] = kbd->kb_delay1;
520                         delay[1] = kbd->kb_delay2;
521                         atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
522                         KBD_FOUND_DEVICE(kbd);
523                 }
524         }
525
526         lwkt_reltoken(&tty_token);
527         return 0;
528 }
529
530 /* test the interface to the device */
531 static int
532 atkbd_test_if(keyboard_t *kbd)
533 {
534         int error;
535
536         error = 0;
537         empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10);
538         crit_enter();
539         if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc))
540                 error = EIO;
541         else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0)
542                 error = EIO;
543         crit_exit();
544
545         return error;
546 }
547
548 /* 
549  * Enable the access to the device; until this function is called,
550  * the client cannot read from the keyboard.
551  */
552 static int
553 atkbd_enable(keyboard_t *kbd)
554 {
555         crit_enter();
556         lwkt_gettoken(&tty_token);
557         KBD_ACTIVATE(kbd);
558         lwkt_reltoken(&tty_token);
559         crit_exit();
560         return 0;
561 }
562
563 /* disallow the access to the device */
564 static int
565 atkbd_disable(keyboard_t *kbd)
566 {
567         crit_enter();
568         lwkt_gettoken(&tty_token);
569         KBD_DEACTIVATE(kbd);
570         lwkt_reltoken(&tty_token);
571         crit_exit();
572         return 0;
573 }
574
575 /* read one byte from the keyboard if it's allowed */
576 static int
577 atkbd_read(keyboard_t *kbd, int wait)
578 {
579         int c, ret;
580
581         lwkt_gettoken(&tty_token);
582         if (wait)
583                 c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc);
584         else
585                 c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc);
586         if (c != -1)
587                 ++kbd->kb_count;
588
589         ret = (KBD_IS_ACTIVE(kbd) ? c : -1);
590
591         lwkt_reltoken(&tty_token);
592         return ret;
593 }
594
595 /* check if data is waiting */
596 static int
597 atkbd_check(keyboard_t *kbd)
598 {
599         int ret;
600
601         lwkt_gettoken(&tty_token);
602
603         if (!KBD_IS_ACTIVE(kbd)) {
604                 lwkt_reltoken(&tty_token);
605                 return FALSE;
606         }
607         ret = kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc);
608
609         lwkt_reltoken(&tty_token);
610         return ret;
611 }
612
613 /* read char from the keyboard */
614 static u_int
615 atkbd_read_char(keyboard_t *kbd, int wait)
616 {
617         atkbd_state_t *state;
618         u_int action;
619         int scancode;
620         int keycode;
621
622         lwkt_gettoken(&tty_token);
623         state = (atkbd_state_t *)kbd->kb_data;
624 next_code:
625         /* do we have a composed char to return? */
626         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
627                 action = state->ks_composed_char;
628                 state->ks_composed_char = 0;
629                 if (action > UCHAR_MAX) {
630                         lwkt_reltoken(&tty_token);
631                         return ERRKEY;
632                 }
633                 lwkt_reltoken(&tty_token);
634                 return action;
635         }
636
637         /* see if there is something in the keyboard port */
638         if (wait) {
639                 do {
640                         scancode = read_kbd_data(state->kbdc);
641                 } while (scancode == -1);
642         } else {
643                 scancode = read_kbd_data_no_wait(state->kbdc);
644                 if (scancode == -1) {
645                         lwkt_reltoken(&tty_token);
646                         return NOKEY;
647                 }
648         }
649         ++kbd->kb_count;
650
651 #if KBDIO_DEBUG >= 10
652         kprintf("atkbd_read_char(): scancode:0x%x\n", scancode);
653 #endif
654
655         /* return the byte as is for the K_RAW mode */
656         if (state->ks_mode == K_RAW) {
657                 lwkt_reltoken(&tty_token);
658                 return scancode;
659         }
660
661         /* translate the scan code into a keycode */
662         keycode = scancode & 0x7F;
663         switch (state->ks_prefix) {
664         case 0x00:      /* normal scancode */
665                 switch(scancode) {
666                 case 0xB8:      /* left alt (compose key) released */
667                         if (state->ks_flags & COMPOSE) {
668                                 state->ks_flags &= ~COMPOSE;
669                                 if (state->ks_composed_char > UCHAR_MAX)
670                                         state->ks_composed_char = 0;
671                         }
672                         break;
673                 case 0x38:      /* left alt (compose key) pressed */
674                         if (!(state->ks_flags & COMPOSE)) {
675                                 state->ks_flags |= COMPOSE;
676                                 state->ks_composed_char = 0;
677                         }
678                         break;
679                 case 0xE0:
680                 case 0xE1:
681                         state->ks_prefix = scancode;
682                         goto next_code;
683                 }
684                 break;
685         case 0xE0:      /* 0xE0 prefix */
686                 state->ks_prefix = 0;
687                 switch (keycode) {
688                 case 0x1C:      /* right enter key */
689                         keycode = 0x59;
690                         break;
691                 case 0x1D:      /* right ctrl key */
692                         keycode = 0x5A;
693                         break;
694                 case 0x35:      /* keypad divide key */
695                         keycode = 0x5B;
696                         break;
697                 case 0x37:      /* print scrn key */
698                         keycode = 0x5C;
699                         break;
700                 case 0x38:      /* right alt key (alt gr) */
701                         keycode = 0x5D;
702                         break;
703                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
704                         keycode = 0x68;
705                         break;
706                 case 0x47:      /* grey home key */
707                         keycode = 0x5E;
708                         break;
709                 case 0x48:      /* grey up arrow key */
710                         keycode = 0x5F;
711                         break;
712                 case 0x49:      /* grey page up key */
713                         keycode = 0x60;
714                         break;
715                 case 0x4B:      /* grey left arrow key */
716                         keycode = 0x61;
717                         break;
718                 case 0x4D:      /* grey right arrow key */
719                         keycode = 0x62;
720                         break;
721                 case 0x4F:      /* grey end key */
722                         keycode = 0x63;
723                         break;
724                 case 0x50:      /* grey down arrow key */
725                         keycode = 0x64;
726                         break;
727                 case 0x51:      /* grey page down key */
728                         keycode = 0x65;
729                         break;
730                 case 0x52:      /* grey insert key */
731                         keycode = 0x66;
732                         break;
733                 case 0x53:      /* grey delete key */
734                         keycode = 0x67;
735                         break;
736                 /* the following 3 are only used on the MS "Natural" keyboard */
737                 case 0x5b:      /* left Window key */
738                         keycode = 0x69;
739                         break;
740                 case 0x5c:      /* right Window key */
741                         keycode = 0x6a;
742                         break;
743                 case 0x5d:      /* menu key */
744                         keycode = 0x6b;
745                         break;
746                 default:        /* ignore everything else */
747                         goto next_code;
748                 }
749                 break;
750         case 0xE1:      /* 0xE1 prefix */
751                 /* 
752                  * The pause/break key on the 101 keyboard produces:
753                  * E1-1D-45 E1-9D-C5
754                  * Ctrl-pause/break produces:
755                  * E0-46 E0-C6 (See above.)
756                  */
757                 state->ks_prefix = 0;
758                 if (keycode == 0x1D)
759                         state->ks_prefix = 0x1D;
760                 goto next_code;
761                 /* NOT REACHED */
762         case 0x1D:      /* pause / break */
763                 state->ks_prefix = 0;
764                 if (keycode != 0x45)
765                         goto next_code;
766                 keycode = 0x68;
767                 break;
768         }
769
770         if (kbd->kb_type == KB_84) {
771                 switch (keycode) {
772                 case 0x37:      /* *(numpad)/print screen */
773                         if (state->ks_flags & SHIFTS)
774                                 keycode = 0x5c; /* print screen */
775                         break;
776                 case 0x45:      /* num lock/pause */
777                         if (state->ks_flags & CTLS)
778                                 keycode = 0x68; /* pause */
779                         break;
780                 case 0x46:      /* scroll lock/break */
781                         if (state->ks_flags & CTLS)
782                                 keycode = 0x6c; /* break */
783                         break;
784                 }
785         } else if (kbd->kb_type == KB_101) {
786                 switch (keycode) {
787                 case 0x5c:      /* print screen */
788                         if (state->ks_flags & ALTS)
789                                 keycode = 0x54; /* sysrq */
790                         break;
791                 case 0x68:      /* pause/break */
792                         if (state->ks_flags & CTLS)
793                                 keycode = 0x6c; /* break */
794                         break;
795                 }
796         }
797
798         /* return the key code in the K_CODE mode */
799         if (state->ks_mode == K_CODE) {
800                 lwkt_reltoken(&tty_token);
801                 return (keycode | (scancode & 0x80));
802         }
803
804         /* compose a character code */
805         if (state->ks_flags & COMPOSE) {
806                 switch (keycode | (scancode & 0x80)) {
807                 /* key pressed, process it */
808                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
809                         state->ks_composed_char *= 10;
810                         state->ks_composed_char += keycode - 0x40;
811                         if (state->ks_composed_char > UCHAR_MAX)
812                                 return ERRKEY;
813                         goto next_code;
814                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
815                         state->ks_composed_char *= 10;
816                         state->ks_composed_char += keycode - 0x47;
817                         if (state->ks_composed_char > UCHAR_MAX)
818                                 return ERRKEY;
819                         goto next_code;
820                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
821                         state->ks_composed_char *= 10;
822                         state->ks_composed_char += keycode - 0x4E;
823                         if (state->ks_composed_char > UCHAR_MAX)
824                                 return ERRKEY;
825                         goto next_code;
826                 case 0x52:                              /* keypad 0 */
827                         state->ks_composed_char *= 10;
828                         if (state->ks_composed_char > UCHAR_MAX)
829                                 return ERRKEY;
830                         goto next_code;
831
832                 /* key released, no interest here */
833                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
834                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
835                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
836                 case 0xD2:                              /* keypad 0 */
837                         goto next_code;
838
839                 case 0x38:                              /* left alt key */
840                         break;
841
842                 default:
843                         if (state->ks_composed_char > 0) {
844                                 state->ks_flags &= ~COMPOSE;
845                                 state->ks_composed_char = 0;
846                                 lwkt_reltoken(&tty_token);
847                                 return ERRKEY;
848                         }
849                         break;
850                 }
851         }
852
853         /* keycode to key action */
854         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
855                                   &state->ks_state, &state->ks_accents);
856         if (action == NOKEY) {
857                 goto next_code;
858         } else {
859                 lwkt_reltoken(&tty_token);
860                 return action;
861         }
862         lwkt_reltoken(&tty_token);
863 }
864
865 /* check if char is waiting */
866 static int
867 atkbd_check_char(keyboard_t *kbd)
868 {
869         atkbd_state_t *state;
870         int ret;
871
872         lwkt_gettoken(&tty_token);
873         if (!KBD_IS_ACTIVE(kbd)) {
874                 lwkt_reltoken(&tty_token);
875                 return FALSE;
876         }
877         state = (atkbd_state_t *)kbd->kb_data;
878         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
879                 lwkt_reltoken(&tty_token);
880                 return TRUE;
881         }
882         ret = kbdc_data_ready(state->kbdc);
883         lwkt_reltoken(&tty_token);
884         return ret;
885 }
886
887 /* some useful control functions */
888 static int
889 atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
890 {
891         /* trasnlate LED_XXX bits into the device specific bits */
892         static u_char ledmap[8] = {
893                 0, 4, 2, 6, 1, 5, 3, 7,
894         };
895         atkbd_state_t *state = kbd->kb_data;
896         int error;
897         int i;
898
899         crit_enter();
900         lwkt_gettoken(&tty_token);
901
902         switch (cmd) {
903
904         case KDGKBMODE:         /* get keyboard mode */
905                 *(int *)arg = state->ks_mode;
906                 break;
907         case KDSKBMODE:         /* set keyboard mode */
908                 switch (*(int *)arg) {
909                 case K_XLATE:
910                         if (state->ks_mode != K_XLATE) {
911                                 /* make lock key state and LED state match */
912                                 state->ks_state &= ~LOCK_MASK;
913                                 state->ks_state |= KBD_LED_VAL(kbd);
914                         }
915                         /* FALL THROUGH */
916                 case K_RAW:
917                 case K_CODE:
918                         if (state->ks_mode != *(int *)arg) {
919                                 atkbd_clear_state(kbd);
920                                 state->ks_mode = *(int *)arg;
921                         }
922                         break;
923                 default:
924                         lwkt_reltoken(&tty_token);
925                         crit_exit();
926                         return EINVAL;
927                 }
928                 break;
929
930         case KDGETLED:          /* get keyboard LED */
931                 *(int *)arg = KBD_LED_VAL(kbd);
932                 break;
933         case KDSETLED:          /* set keyboard LED */
934                 /* NOTE: lock key state in ks_state won't be changed */
935                 if (*(int *)arg & ~LOCK_MASK) {
936                         lwkt_reltoken(&tty_token);
937                         crit_exit();
938                         return EINVAL;
939                 }
940                 i = *(int *)arg;
941                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
942                 if (state->ks_mode == K_XLATE &&
943                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
944                         if (i & ALKED)
945                                 i |= CLKED;
946                         else
947                                 i &= ~CLKED;
948                 }
949                 if (KBD_HAS_DEVICE(kbd)) {
950                         error = write_kbd(state->kbdc, KBDC_SET_LEDS,
951                                           ledmap[i & LED_MASK]);
952                         if (error) {
953                                 lwkt_reltoken(&tty_token);
954                                 crit_exit();
955                                 return error;
956                         }
957                 }
958                 KBD_LED_VAL(kbd) = *(int *)arg;
959                 break;
960
961         case KDGKBSTATE:        /* get lock key state */
962                 *(int *)arg = state->ks_state & LOCK_MASK;
963                 break;
964         case KDSKBSTATE:        /* set lock key state */
965                 if (*(int *)arg & ~LOCK_MASK) {
966                         lwkt_reltoken(&tty_token);
967                         crit_exit();
968                         return EINVAL;
969                 }
970                 state->ks_state &= ~LOCK_MASK;
971                 state->ks_state |= *(int *)arg;
972                 lwkt_reltoken(&tty_token);
973                 crit_exit();
974                 /* set LEDs and quit */
975                 return atkbd_ioctl(kbd, KDSETLED, arg);
976
977         case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
978                 crit_exit();
979                 if (!KBD_HAS_DEVICE(kbd)) {
980                         lwkt_reltoken(&tty_token);
981                         return 0;
982                 }
983                 i = typematic(((int *)arg)[0], ((int *)arg)[1]);
984                 error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i);
985                 if (error == 0) {
986                         kbd->kb_delay1 = typematic_delay(i);
987                         kbd->kb_delay2 = typematic_rate(i);
988                 }
989                 lwkt_reltoken(&tty_token);
990                 return error;
991
992         case KDSETRAD:          /* set keyboard repeat rate (old interface) */
993                 crit_exit();
994                 if (!KBD_HAS_DEVICE(kbd)) {
995                         lwkt_reltoken(&tty_token);
996                         return 0;
997                 }
998                 error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg);
999                 if (error == 0) {
1000                         kbd->kb_delay1 = typematic_delay(*(int *)arg);
1001                         kbd->kb_delay2 = typematic_rate(*(int *)arg);
1002                 }
1003                 lwkt_reltoken(&tty_token);
1004                 return error;
1005
1006         case PIO_KEYMAP:        /* set keyboard translation table */
1007         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
1008         case PIO_DEADKEYMAP:    /* set accent key translation table */
1009                 state->ks_accents = 0;
1010                 /* FALL THROUGH */
1011         default:
1012                 lwkt_reltoken(&tty_token);
1013                 crit_exit();
1014                 return genkbd_commonioctl(kbd, cmd, arg);
1015         }
1016
1017         lwkt_reltoken(&tty_token);
1018         crit_exit();
1019         return 0;
1020 }
1021
1022 /* lock the access to the keyboard */
1023 static int
1024 atkbd_lock(keyboard_t *kbd, int lock)
1025 {
1026         return kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc, lock);
1027 }
1028
1029 /* clear the internal state of the keyboard */
1030 static void
1031 atkbd_clear_state(keyboard_t *kbd)
1032 {
1033         atkbd_state_t *state;
1034
1035         state = (atkbd_state_t *)kbd->kb_data;
1036         state->ks_flags = 0;
1037         state->ks_polling = 0;
1038         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
1039         state->ks_accents = 0;
1040         state->ks_composed_char = 0;
1041 #if 0
1042         state->ks_prefix = 0; /* XXX */
1043 #endif
1044 }
1045
1046 /* save the internal state */
1047 static int
1048 atkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
1049 {
1050         if (len == 0)
1051                 return sizeof(atkbd_state_t);
1052         if (len < sizeof(atkbd_state_t))
1053                 return -1;
1054
1055         lwkt_gettoken(&tty_token);
1056         bcopy(kbd->kb_data, buf, sizeof(atkbd_state_t));
1057         lwkt_reltoken(&tty_token);
1058         return 0;
1059 }
1060
1061 /* set the internal state */
1062 static int
1063 atkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
1064 {
1065         if (len < sizeof(atkbd_state_t))
1066                 return ENOMEM;
1067         if (((atkbd_state_t *)kbd->kb_data)->kbdc
1068                 != ((atkbd_state_t *)buf)->kbdc)
1069                 return ENOMEM;
1070         lwkt_gettoken(&tty_token);
1071         bcopy(buf, kbd->kb_data, sizeof(atkbd_state_t));
1072         lwkt_reltoken(&tty_token);
1073         return 0;
1074 }
1075
1076 static int
1077 atkbd_poll(keyboard_t *kbd, int on)
1078 {
1079         atkbd_state_t *state;
1080
1081         lwkt_gettoken(&tty_token);
1082         state = (atkbd_state_t *)kbd->kb_data;
1083         crit_enter();
1084         if (on)
1085                 ++state->ks_polling;
1086         else
1087                 --state->ks_polling;
1088         crit_exit();
1089         lwkt_reltoken(&tty_token);
1090         return 0;
1091 }
1092
1093 /* local functions */
1094
1095 static int
1096 get_typematic(keyboard_t *kbd)
1097 {
1098 #ifdef __i386__
1099         /*
1100          * Only some systems allow us to retrieve the keyboard repeat 
1101          * rate previously set via the BIOS...
1102          */
1103         struct vm86frame vmf;
1104         u_int32_t p;
1105
1106         bzero(&vmf, sizeof(vmf));
1107         vmf.vmf_ax = 0xc000;
1108         vm86_intcall(0x15, &vmf);
1109         if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah)
1110                 return ENODEV;
1111         p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx);
1112         if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */
1113                 return ENODEV;
1114         vmf.vmf_ax = 0x0900;
1115         vm86_intcall(0x16, &vmf);
1116         if ((vmf.vmf_al & 0x08) == 0)   /* int 16, function 0x0306 supported? */
1117                 return ENODEV;
1118         vmf.vmf_ax = 0x0306;
1119         vm86_intcall(0x16, &vmf);
1120         kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5);
1121         kbd->kb_delay2 = typematic_rate(vmf.vmf_bl);
1122         return 0;
1123 #else
1124         return ENODEV;
1125 #endif /* __i386__ */
1126 }
1127
1128 static int
1129 setup_kbd_port(KBDC kbdc, int port, int intr)
1130 {
1131         if (!set_controller_command_byte(kbdc,
1132                 KBD_KBD_CONTROL_BITS,
1133                 ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT)
1134                     | ((intr) ? KBD_ENABLE_KBD_INT : KBD_DISABLE_KBD_INT)))
1135                 return 1;
1136         return 0;
1137 }
1138
1139 static int
1140 get_kbd_echo(KBDC kbdc)
1141 {
1142         /* enable the keyboard port, but disable the keyboard intr. */
1143         if (setup_kbd_port(kbdc, TRUE, FALSE))
1144                 /* CONTROLLER ERROR: there is very little we can do... */
1145                 return ENXIO;
1146
1147         /* see if something is present */
1148         write_kbd_command(kbdc, KBDC_ECHO);
1149         if (read_kbd_data(kbdc) != KBD_ECHO) {
1150                 empty_both_buffers(kbdc, 10);
1151                 test_controller(kbdc);
1152                 test_kbd_port(kbdc);
1153                 return ENXIO;
1154         }
1155
1156         /* enable the keyboard port and intr. */
1157         if (setup_kbd_port(kbdc, TRUE, TRUE)) {
1158                 /*
1159                  * CONTROLLER ERROR 
1160                  * This is serious; the keyboard intr is left disabled! 
1161                  */
1162                 return ENXIO;
1163         }
1164     
1165         return 0;
1166 }
1167
1168 static int
1169 probe_keyboard(KBDC kbdc, int flags)
1170 {
1171         /*
1172          * Don't try to print anything in this function.  The low-level 
1173          * console may not have been initialized yet...
1174          */
1175         int err;
1176         int c;
1177         int m;
1178
1179         if (!kbdc_lock(kbdc, TRUE)) {
1180                 /* driver error? */
1181                 return ENXIO;
1182         }
1183
1184         /* temporarily block data transmission from the keyboard */
1185         write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);
1186
1187         /* flush any noise in the buffer */
1188         empty_both_buffers(kbdc, 100);
1189
1190         /* save the current keyboard controller command byte */
1191         m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS;
1192         c = get_controller_command_byte(kbdc);
1193         if (c == -1) {
1194                 /* CONTROLLER ERROR */
1195                 kbdc_set_device_mask(kbdc, m);
1196                 kbdc_lock(kbdc, FALSE);
1197                 return ENXIO;
1198         }
1199
1200         /* 
1201          * The keyboard may have been screwed up by the boot block.
1202          * We may just be able to recover from error by testing the controller
1203          * and the keyboard port. The controller command byte needs to be
1204          * saved before this recovery operation, as some controllers seem 
1205          * to set the command byte to particular values.
1206          */
1207         test_controller(kbdc);
1208         test_kbd_port(kbdc);
1209
1210         err = get_kbd_echo(kbdc);
1211
1212         /*
1213          * Even if the keyboard doesn't seem to be present (err != 0),
1214          * we shall enable the keyboard port and interrupt so that
1215          * the driver will be operable when the keyboard is attached
1216          * to the system later.  It is NOT recommended to hot-plug
1217          * the AT keyboard, but many people do so...
1218          */
1219         kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
1220         setup_kbd_port(kbdc, TRUE, TRUE);
1221 #if 0
1222         if (err == 0) {
1223                 kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
1224         } else {
1225                 /* try to restore the command byte as before */
1226                 set_controller_command_byte(kbdc, 0xff, c);
1227                 kbdc_set_device_mask(kbdc, m);
1228         }
1229 #endif
1230
1231         kbdc_lock(kbdc, FALSE);
1232         return err;
1233 }
1234
1235 static int
1236 init_keyboard(KBDC kbdc, int *type, int flags)
1237 {
1238         int codeset;
1239         int id;
1240         int c;
1241
1242         if (!kbdc_lock(kbdc, TRUE)) {
1243                 /* driver error? */
1244                 return EIO;
1245         }
1246
1247         /* temporarily block data transmission from the keyboard */
1248         write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);
1249
1250         /* save the current controller command byte */
1251         empty_both_buffers(kbdc, 200);
1252         c = get_controller_command_byte(kbdc);
1253         if (c == -1) {
1254                 /* CONTROLLER ERROR */
1255                 kbdc_lock(kbdc, FALSE);
1256                 kprintf("atkbd: unable to get the current command byte value.\n");
1257                 return EIO;
1258         }
1259         if (bootverbose)
1260                 kprintf("atkbd: the current kbd controller command byte %04x\n",
1261                        c);
1262 #if 0
1263         /* override the keyboard lock switch */
1264         c |= KBD_OVERRIDE_KBD_LOCK;
1265 #endif
1266
1267         /* enable the keyboard port, but disable the keyboard intr. */
1268         if (setup_kbd_port(kbdc, TRUE, FALSE)) {
1269                 /* CONTROLLER ERROR: there is very little we can do... */
1270                 kprintf("atkbd: unable to set the command byte.\n");
1271                 kbdc_lock(kbdc, FALSE);
1272                 return EIO;
1273         }
1274
1275         /* 
1276          * Check if we have an XT keyboard before we attempt to reset it. 
1277          * The procedure assumes that the keyboard and the controller have 
1278          * been set up properly by BIOS and have not been messed up 
1279          * during the boot process.
1280          */
1281         codeset = -1;
1282         if (flags & KB_CONF_ALT_SCANCODESET)
1283                 /* the user says there is a XT keyboard */
1284                 codeset = 1;
1285 #ifdef KBD_DETECT_XT_KEYBOARD
1286         else if ((c & KBD_TRANSLATION) == 0) {
1287                 /* SET_SCANCODE_SET is not always supported; ignore error */
1288                 if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0)
1289                         == KBD_ACK) 
1290                         codeset = read_kbd_data(kbdc);
1291         }
1292         if (bootverbose)
1293                 kprintf("atkbd: scancode set %d\n", codeset);
1294 #endif /* KBD_DETECT_XT_KEYBOARD */
1295  
1296         *type = KB_OTHER;
1297         id = get_kbd_id(kbdc);
1298         switch(id) {
1299         case 0x41ab:    /* 101/102/... Enhanced */
1300         case 0x83ab:    /* ditto */
1301         case 0x54ab:    /* SpaceSaver */
1302         case 0x84ab:    /* ditto */
1303 #if 0
1304         case 0x90ab:    /* 'G' */
1305         case 0x91ab:    /* 'P' */
1306         case 0x92ab:    /* 'A' */
1307 #endif
1308                 *type = KB_101;
1309                 break;
1310         case -1:        /* AT 84 keyboard doesn't return ID */
1311                 *type = KB_84;
1312                 break;
1313         default:
1314                 break;
1315         }
1316         if (bootverbose)
1317                 kprintf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);
1318
1319         /* reset keyboard hardware */
1320         if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
1321                 /*
1322                  * KEYBOARD ERROR
1323                  * Keyboard reset may fail either because the keyboard
1324                  * doen't exist, or because the keyboard doesn't pass
1325                  * the self-test, or the keyboard controller on the
1326                  * motherboard and the keyboard somehow fail to shake hands.
1327                  * It is just possible, particularly in the last case,
1328                  * that the keyoard controller may be left in a hung state.
1329                  * test_controller() and test_kbd_port() appear to bring
1330                  * the keyboard controller back (I don't know why and how,
1331                  * though.)
1332                  */
1333                 empty_both_buffers(kbdc, 10);
1334                 test_controller(kbdc);
1335                 test_kbd_port(kbdc);
1336                 /*
1337                  * We could disable the keyboard port and interrupt... but, 
1338                  * the keyboard may still exist (see above). 
1339                  */
1340                 set_controller_command_byte(kbdc, 0xff, c);
1341                 kbdc_lock(kbdc, FALSE);
1342                 if (bootverbose)
1343                         kprintf("atkbd: failed to reset the keyboard.\n");
1344                 return EIO;
1345         }
1346
1347         /*
1348          * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
1349          * such as those on the IBM ThinkPad laptop computers can be used
1350          * with the standard console driver.
1351          */
1352         if (codeset == 1) {
1353                 if (send_kbd_command_and_data(kbdc,
1354                         KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
1355                         /* XT kbd doesn't need scan code translation */
1356                         c &= ~KBD_TRANSLATION;
1357                 } else {
1358                         /*
1359                          * KEYBOARD ERROR 
1360                          * The XT kbd isn't usable unless the proper scan
1361                          * code set is selected. 
1362                          */
1363                         set_controller_command_byte(kbdc, 0xff, c);
1364                         kbdc_lock(kbdc, FALSE);
1365                         kprintf("atkbd: unable to set the XT keyboard mode.\n");
1366                         return EIO;
1367                 }
1368         }
1369
1370         /* enable the keyboard port and intr. */
1371         if (!set_controller_command_byte(kbdc, 
1372                 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
1373                 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
1374                     | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
1375                 /*
1376                  * CONTROLLER ERROR 
1377                  * This is serious; we are left with the disabled
1378                  * keyboard intr. 
1379                  */
1380                 set_controller_command_byte(kbdc, 0xff, c);
1381                 kbdc_lock(kbdc, FALSE);
1382                 kprintf("atkbd: unable to enable the keyboard port and intr.\n");
1383                 return EIO;
1384         }
1385
1386         kbdc_lock(kbdc, FALSE);
1387         return 0;
1388 }
1389
1390 static int
1391 write_kbd(KBDC kbdc, int command, int data)
1392 {
1393     /* prevent the timeout routine from polling the keyboard */
1394     if (!kbdc_lock(kbdc, TRUE)) 
1395         return EBUSY;
1396
1397     /* disable the keyboard and mouse interrupt */
1398     crit_enter();
1399 #if 0
1400     c = get_controller_command_byte(kbdc);
1401     if ((c == -1) 
1402         || !set_controller_command_byte(kbdc, 
1403             kbdc_get_device_mask(kbdc),
1404             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1405                 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1406         /* CONTROLLER ERROR */
1407         kbdc_lock(kbdc, FALSE);
1408         crit_exit();
1409         return EIO;
1410     }
1411     /* 
1412      * Now that the keyboard controller is told not to generate 
1413      * the keyboard and mouse interrupts, call `splx()' to allow 
1414      * the other tty interrupts. The clock interrupt may also occur, 
1415      * but the timeout routine (`scrn_timer()') will be blocked 
1416      * by the lock flag set via `kbdc_lock()'
1417      */
1418     crit_exit();
1419 #endif
1420
1421     if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
1422         send_kbd_command(kbdc, KBDC_ENABLE_KBD);
1423
1424 #if 0
1425     /* restore the interrupts */
1426     if (!set_controller_command_byte(kbdc,
1427             kbdc_get_device_mask(kbdc),
1428             c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 
1429         /* CONTROLLER ERROR */
1430     }
1431 #else
1432     crit_exit();
1433 #endif
1434     kbdc_lock(kbdc, FALSE);
1435
1436     return 0;
1437 }
1438
1439 static int
1440 get_kbd_id(KBDC kbdc)
1441 {
1442         int id1, id2;
1443
1444         empty_both_buffers(kbdc, 10);
1445         id1 = id2 = -1;
1446         if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) != KBD_ACK)
1447                 return -1;
1448
1449         DELAY(10000);   /* 10 msec delay */
1450         id1 = read_kbd_data(kbdc);
1451         if (id1 != -1)
1452                 id2 = read_kbd_data(kbdc);
1453
1454         if ((id1 == -1) || (id2 == -1)) {
1455                 empty_both_buffers(kbdc, 10);
1456                 test_controller(kbdc);
1457                 test_kbd_port(kbdc);
1458                 return -1;
1459         }
1460         return ((id2 << 8) | id1);
1461 }
1462
1463 static int delays[] = { 250, 500, 750, 1000 };
1464 static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
1465                         68,  76,  84,  92, 100, 110, 118, 126,
1466                        136, 152, 168, 184, 200, 220, 236, 252,
1467                        272, 304, 336, 368, 400, 440, 472, 504 };
1468
1469 static int
1470 typematic_delay(int i)
1471 {
1472         return delays[(i >> 5) & 3];
1473 }
1474
1475 static int
1476 typematic_rate(int i)
1477 {
1478         return rates[i & 0x1f];
1479 }
1480
1481 static int
1482 typematic(int delay, int rate)
1483 {
1484         int value;
1485         int i;
1486
1487         for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; --i) {
1488                 if (delay >= delays[i])
1489                         break;
1490         }
1491         value = i << 5;
1492         for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; --i) {
1493                 if (rate >= rates[i])
1494                         break;
1495         }
1496         value |= i;
1497         return value;
1498 }