]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/kbdmux/kbdmux.c
Update lldb to release_39 branch r276489 and resolve immediate conflicts.
[FreeBSD/FreeBSD.git] / sys / dev / kbdmux / kbdmux.c
1 /*
2  * kbdmux.c
3  */
4
5 /*-
6  * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
31  * $FreeBSD$
32  */
33
34 #include "opt_compat.h"
35 #include "opt_kbd.h"
36 #include "opt_kbdmux.h"
37
38 #include <sys/param.h>
39 #include <sys/bus.h>
40 #include <sys/conf.h>
41 #include <sys/consio.h>
42 #include <sys/fcntl.h>
43 #include <sys/kbio.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/module.h>
49 #include <sys/mutex.h>
50 #include <sys/poll.h>
51 #include <sys/proc.h>
52 #include <sys/queue.h>
53 #include <sys/selinfo.h>
54 #include <sys/systm.h>
55 #include <sys/taskqueue.h>
56 #include <sys/uio.h>
57 #include <dev/kbd/kbdreg.h>
58
59 /* the initial key map, accent map and fkey strings */
60 #ifdef KBDMUX_DFLT_KEYMAP
61 #define KBD_DFLT_KEYMAP
62 #include "kbdmuxmap.h"
63 #endif
64
65 #include <dev/kbd/kbdtables.h>
66
67 #define KEYBOARD_NAME   "kbdmux"
68
69 MALLOC_DECLARE(M_KBDMUX);
70 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
71
72 /*****************************************************************************
73  *****************************************************************************
74  **                             Keyboard state
75  *****************************************************************************
76  *****************************************************************************/
77
78 #define KBDMUX_Q_SIZE   512     /* input queue size */
79
80 /*
81  * XXX
82  * For now rely on Giant mutex to protect our data structures.
83  * Just like the rest of keyboard drivers and syscons(4) do.
84  * Note that callout is initialized as not MP-safe to make sure
85  * Giant is held.
86  */
87
88 #if 0 /* not yet */
89 #define KBDMUX_LOCK_DECL_GLOBAL \
90         struct mtx ks_lock
91 #define KBDMUX_LOCK_INIT(s) \
92         mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
93 #define KBDMUX_LOCK_DESTROY(s) \
94         mtx_destroy(&(s)->ks_lock)
95 #define KBDMUX_LOCK(s) \
96         mtx_lock(&(s)->ks_lock)
97 #define KBDMUX_UNLOCK(s) \
98         mtx_unlock(&(s)->ks_lock)
99 #define KBDMUX_LOCK_ASSERT(s, w) \
100         mtx_assert(&(s)->ks_lock, (w))
101 #define KBDMUX_SLEEP(s, f, d, t) \
102         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
103 #define KBDMUX_CALLOUT_INIT(s) \
104         callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
105 #define KBDMUX_QUEUE_INTR(s) \
106         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
107 #else
108 #define KBDMUX_LOCK_DECL_GLOBAL
109
110 #define KBDMUX_LOCK_INIT(s)
111
112 #define KBDMUX_LOCK_DESTROY(s)
113
114 #define KBDMUX_LOCK(s)
115
116 #define KBDMUX_UNLOCK(s)
117
118 #define KBDMUX_LOCK_ASSERT(s, w)
119
120 #define KBDMUX_SLEEP(s, f, d, t) \
121         tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
122 #define KBDMUX_CALLOUT_INIT(s) \
123         callout_init(&(s)->ks_timo, 0)
124 #define KBDMUX_QUEUE_INTR(s) \
125         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
126 #endif /* not yet */
127
128 /*
129  * kbdmux keyboard
130  */
131 struct kbdmux_kbd
132 {
133         keyboard_t              *kbd;   /* keyboard */
134         SLIST_ENTRY(kbdmux_kbd)  next;  /* link to next */
135 };
136
137 typedef struct kbdmux_kbd       kbdmux_kbd_t;
138
139 /*
140  * kbdmux state
141  */
142 struct kbdmux_state
143 {
144         char                     ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
145         unsigned int             ks_inq_start;
146         unsigned int             ks_inq_length;
147         struct task              ks_task;       /* interrupt task */
148         struct callout           ks_timo;       /* timeout handler */
149 #define TICKS                   (hz)            /* rate */
150
151         int                      ks_flags;      /* flags */
152 #define COMPOSE                 (1 << 0)        /* compose char flag */ 
153 #define POLLING                 (1 << 1)        /* polling */
154 #define TASK                    (1 << 2)        /* interrupt task queued */
155
156         int                      ks_mode;       /* K_XLATE, K_RAW, K_CODE */
157         int                      ks_state;      /* state */
158         int                      ks_accents;    /* accent key index (> 0) */
159         u_int                    ks_composed_char; /* composed char code */
160         u_char                   ks_prefix;     /* AT scan code prefix */
161
162         SLIST_HEAD(, kbdmux_kbd) ks_kbds;       /* keyboards */
163
164         KBDMUX_LOCK_DECL_GLOBAL;
165 };
166
167 typedef struct kbdmux_state     kbdmux_state_t;
168
169 /*****************************************************************************
170  *****************************************************************************
171  **                             Helper functions
172  *****************************************************************************
173  *****************************************************************************/
174
175 static task_fn_t                kbdmux_kbd_intr;
176 static timeout_t                kbdmux_kbd_intr_timo;
177 static kbd_callback_func_t      kbdmux_kbd_event;
178
179 static void
180 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
181 {
182         unsigned int p;
183
184         if (state->ks_inq_length == KBDMUX_Q_SIZE)
185                 return;
186
187         p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
188         state->ks_inq[p] = c;
189         state->ks_inq_length++;
190 }
191
192 static int
193 kbdmux_kbd_getc(kbdmux_state_t *state)
194 {
195         unsigned char c;
196
197         if (state->ks_inq_length == 0)
198                 return (-1);
199
200         c = state->ks_inq[state->ks_inq_start];
201         state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
202         state->ks_inq_length--;
203
204         return (c);
205 }
206
207 /*
208  * Interrupt handler task
209  */
210 void
211 kbdmux_kbd_intr(void *xkbd, int pending)
212 {
213         keyboard_t      *kbd = (keyboard_t *) xkbd;
214         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
215
216         kbdd_intr(kbd, NULL);
217
218         KBDMUX_LOCK(state);
219
220         state->ks_flags &= ~TASK;
221         wakeup(&state->ks_task);
222
223         KBDMUX_UNLOCK(state);
224 }
225
226 /*
227  * Schedule interrupt handler on timeout. Called with locked state.
228  */
229 void
230 kbdmux_kbd_intr_timo(void *xstate)
231 {
232         kbdmux_state_t  *state = (kbdmux_state_t *) xstate;
233
234         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
235
236         if (callout_pending(&state->ks_timo))
237                 return; /* callout was reset */
238
239         if (!callout_active(&state->ks_timo))
240                 return; /* callout was stopped */
241
242         callout_deactivate(&state->ks_timo);
243
244         /* queue interrupt task if needed */
245         if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
246             KBDMUX_QUEUE_INTR(state) == 0)
247                 state->ks_flags |= TASK;
248
249         /* re-schedule timeout */
250         callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
251 }
252
253 /*
254  * Process event from one of our keyboards
255  */
256 static int
257 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
258 {
259         kbdmux_state_t  *state = (kbdmux_state_t *) arg;
260
261         switch (event) {
262         case KBDIO_KEYINPUT: {
263                 int     c;
264
265                 KBDMUX_LOCK(state);
266
267                 /*
268                  * Read all chars from the keyboard
269                  *
270                  * Turns out that atkbd(4) check_char() method may return
271                  * "true" while read_char() method returns NOKEY. If this
272                  * happens we could stuck in the loop below. Avoid this
273                  * by breaking out of the loop if read_char() method returns
274                  * NOKEY.
275                  */
276
277                 while (kbdd_check_char(kbd)) {
278                         c = kbdd_read_char(kbd, 0);
279                         if (c == NOKEY)
280                                 break;
281                         if (c == ERRKEY)
282                                 continue; /* XXX ring bell */
283                         if (!KBD_IS_BUSY(kbd))
284                                 continue; /* not open - discard the input */
285
286                         kbdmux_kbd_putc(state, c);
287                 }
288
289                 /* queue interrupt task if needed */
290                 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
291                     KBDMUX_QUEUE_INTR(state) == 0)
292                         state->ks_flags |= TASK;
293
294                 KBDMUX_UNLOCK(state);
295                 } break;
296
297         case KBDIO_UNLOADING: {
298                 kbdmux_kbd_t    *k;
299
300                 KBDMUX_LOCK(state);
301
302                 SLIST_FOREACH(k, &state->ks_kbds, next)
303                         if (k->kbd == kbd)
304                                 break;
305
306                 if (k != NULL) {
307                         kbd_release(k->kbd, &k->kbd);
308                         SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
309
310                         k->kbd = NULL;
311
312                         free(k, M_KBDMUX);
313                 }
314
315                 KBDMUX_UNLOCK(state);
316                 } break;
317
318         default:
319                 return (EINVAL);
320                 /* NOT REACHED */
321         }
322
323         return (0);
324 }
325
326 /****************************************************************************
327  ****************************************************************************
328  **                              Keyboard driver
329  ****************************************************************************
330  ****************************************************************************/
331
332 static int              kbdmux_configure(int flags);
333 static kbd_probe_t      kbdmux_probe;
334 static kbd_init_t       kbdmux_init;
335 static kbd_term_t       kbdmux_term;
336 static kbd_intr_t       kbdmux_intr;
337 static kbd_test_if_t    kbdmux_test_if;
338 static kbd_enable_t     kbdmux_enable;
339 static kbd_disable_t    kbdmux_disable;
340 static kbd_read_t       kbdmux_read;
341 static kbd_check_t      kbdmux_check;
342 static kbd_read_char_t  kbdmux_read_char;
343 static kbd_check_char_t kbdmux_check_char;
344 static kbd_ioctl_t      kbdmux_ioctl;
345 static kbd_lock_t       kbdmux_lock;
346 static void             kbdmux_clear_state_locked(kbdmux_state_t *state);
347 static kbd_clear_state_t kbdmux_clear_state;
348 static kbd_get_state_t  kbdmux_get_state;
349 static kbd_set_state_t  kbdmux_set_state;
350 static kbd_poll_mode_t  kbdmux_poll;
351
352 static keyboard_switch_t kbdmuxsw = {
353         .probe =        kbdmux_probe,
354         .init =         kbdmux_init,
355         .term =         kbdmux_term,
356         .intr =         kbdmux_intr,
357         .test_if =      kbdmux_test_if,
358         .enable =       kbdmux_enable,
359         .disable =      kbdmux_disable,
360         .read =         kbdmux_read,
361         .check =        kbdmux_check,
362         .read_char =    kbdmux_read_char,
363         .check_char =   kbdmux_check_char,
364         .ioctl =        kbdmux_ioctl,
365         .lock =         kbdmux_lock,
366         .clear_state =  kbdmux_clear_state,
367         .get_state =    kbdmux_get_state,
368         .set_state =    kbdmux_set_state,
369         .get_fkeystr =  genkbd_get_fkeystr,
370         .poll =         kbdmux_poll,
371         .diag =         genkbd_diag,
372 };
373
374 /*
375  * Return the number of found keyboards
376  */
377 static int
378 kbdmux_configure(int flags)
379 {
380         return (1);
381 }
382
383 /*
384  * Detect a keyboard
385  */
386 static int
387 kbdmux_probe(int unit, void *arg, int flags)
388 {
389         if (resource_disabled(KEYBOARD_NAME, unit))
390                 return (ENXIO);
391
392         return (0);
393 }
394
395 /*
396  * Reset and initialize the keyboard (stolen from atkbd.c)
397  */
398 static int
399 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
400 {
401         keyboard_t      *kbd = NULL;
402         kbdmux_state_t  *state = NULL;
403         keymap_t        *keymap = NULL;
404         accentmap_t     *accmap = NULL;
405         fkeytab_t       *fkeymap = NULL;
406         int              error, needfree, fkeymap_size, delay[2];
407
408         if (*kbdp == NULL) {
409                 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
410                 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
411                 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
412                 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
413                 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
414                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
415                 needfree = 1;
416
417                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
418                     (accmap == NULL) || (fkeymap == NULL)) {
419                         error = ENOMEM;
420                         goto bad;
421                 }
422
423                 KBDMUX_LOCK_INIT(state);
424                 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
425                 KBDMUX_CALLOUT_INIT(state);
426                 SLIST_INIT(&state->ks_kbds);
427         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
428                 return (0);
429         } else {
430                 kbd = *kbdp;
431                 state = (kbdmux_state_t *) kbd->kb_data;
432                 keymap = kbd->kb_keymap;
433                 accmap = kbd->kb_accentmap;
434                 fkeymap = kbd->kb_fkeytab;
435                 fkeymap_size = kbd->kb_fkeytab_size;
436                 needfree = 0;
437         }
438
439         if (!KBD_IS_PROBED(kbd)) {
440                 /* XXX assume 101/102 keys keyboard */
441                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
442                 bcopy(&key_map, keymap, sizeof(key_map));
443                 bcopy(&accent_map, accmap, sizeof(accent_map));
444                 bcopy(fkey_tab, fkeymap,
445                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
446                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
447                 kbd->kb_data = (void *)state;
448         
449                 KBD_FOUND_DEVICE(kbd);
450                 KBD_PROBE_DONE(kbd);
451
452                 KBDMUX_LOCK(state);
453                 kbdmux_clear_state_locked(state);
454                 state->ks_mode = K_XLATE;
455                 KBDMUX_UNLOCK(state);
456         }
457
458         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
459                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
460
461                 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
462
463                 delay[0] = kbd->kb_delay1;
464                 delay[1] = kbd->kb_delay2;
465                 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
466
467                 KBD_INIT_DONE(kbd);
468         }
469
470         if (!KBD_IS_CONFIGURED(kbd)) {
471                 if (kbd_register(kbd) < 0) {
472                         error = ENXIO;
473                         goto bad;
474                 }
475
476                 KBD_CONFIG_DONE(kbd);
477
478                 KBDMUX_LOCK(state);
479                 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
480                 KBDMUX_UNLOCK(state);
481         }
482
483         return (0);
484 bad:
485         if (needfree) {
486                 if (state != NULL)
487                         free(state, M_KBDMUX);
488                 if (keymap != NULL)
489                         free(keymap, M_KBDMUX);
490                 if (accmap != NULL)
491                         free(accmap, M_KBDMUX);
492                 if (fkeymap != NULL)
493                         free(fkeymap, M_KBDMUX);
494                 if (kbd != NULL) {
495                         free(kbd, M_KBDMUX);
496                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
497                 }
498         }
499
500         return (error);
501 }
502
503 /*
504  * Finish using this keyboard
505  */
506 static int
507 kbdmux_term(keyboard_t *kbd)
508 {
509         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
510         kbdmux_kbd_t    *k;
511
512         KBDMUX_LOCK(state);
513
514         /* kill callout */
515         callout_stop(&state->ks_timo);
516
517         /* wait for interrupt task */
518         while (state->ks_flags & TASK)
519                 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
520
521         /* release all keyboards from the mux */
522         while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
523                 kbd_release(k->kbd, &k->kbd);
524                 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
525
526                 k->kbd = NULL;
527
528                 free(k, M_KBDMUX);
529         }
530
531         KBDMUX_UNLOCK(state);
532
533         kbd_unregister(kbd);
534
535         KBDMUX_LOCK_DESTROY(state);
536         bzero(state, sizeof(*state));
537         free(state, M_KBDMUX);
538
539         free(kbd->kb_keymap, M_KBDMUX);
540         free(kbd->kb_accentmap, M_KBDMUX);
541         free(kbd->kb_fkeytab, M_KBDMUX);
542         free(kbd, M_KBDMUX);
543
544         return (0);
545 }
546
547 /*
548  * Keyboard interrupt routine
549  */
550 static int
551 kbdmux_intr(keyboard_t *kbd, void *arg)
552 {
553         int     c;
554
555         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
556                 /* let the callback function to process the input */
557                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
558                                             kbd->kb_callback.kc_arg);
559         } else {
560                 /* read and discard the input; no one is waiting for input */
561                 do {
562                         c = kbdmux_read_char(kbd, FALSE);
563                 } while (c != NOKEY);
564         }
565
566         return (0);
567 }
568
569 /*
570  * Test the interface to the device
571  */
572 static int
573 kbdmux_test_if(keyboard_t *kbd)
574 {
575         return (0);
576 }
577
578 /* 
579  * Enable the access to the device; until this function is called,
580  * the client cannot read from the keyboard.
581  */
582 static int
583 kbdmux_enable(keyboard_t *kbd)
584 {
585         KBD_ACTIVATE(kbd);
586         return (0);
587 }
588
589 /*
590  * Disallow the access to the device
591  */
592 static int
593 kbdmux_disable(keyboard_t *kbd)
594 {
595         KBD_DEACTIVATE(kbd);
596         return (0);
597 }
598
599 /*
600  * Read one byte from the keyboard if it's allowed
601  */
602 static int
603 kbdmux_read(keyboard_t *kbd, int wait)
604 {
605         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
606         int              c;
607
608         KBDMUX_LOCK(state);
609         c = kbdmux_kbd_getc(state);
610         KBDMUX_UNLOCK(state);
611
612         if (c != -1)
613                 kbd->kb_count ++;
614
615         return (KBD_IS_ACTIVE(kbd)? c : -1);
616 }
617
618 /*
619  * Check if data is waiting
620  */
621 static int
622 kbdmux_check(keyboard_t *kbd)
623 {
624         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
625         int              ready;
626
627         if (!KBD_IS_ACTIVE(kbd))
628                 return (FALSE);
629
630         KBDMUX_LOCK(state);
631         ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
632         KBDMUX_UNLOCK(state);
633
634         return (ready);
635 }
636
637 /*
638  * Read char from the keyboard (stolen from atkbd.c)
639  */
640 static u_int
641 kbdmux_read_char(keyboard_t *kbd, int wait)
642 {
643         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
644         u_int            action;
645         int              scancode, keycode;
646
647         KBDMUX_LOCK(state);
648
649 next_code:
650
651         /* do we have a composed char to return? */
652         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
653                 action = state->ks_composed_char;
654                 state->ks_composed_char = 0;
655                 if (action > UCHAR_MAX) {
656                         KBDMUX_UNLOCK(state);
657
658                         return (ERRKEY);
659                 }
660
661                 KBDMUX_UNLOCK(state);
662
663                 return (action);
664         }
665
666         /* see if there is something in the keyboard queue */
667         scancode = kbdmux_kbd_getc(state);
668         if (scancode == -1) {
669                 if (state->ks_flags & POLLING) {
670                         kbdmux_kbd_t    *k;
671
672                         SLIST_FOREACH(k, &state->ks_kbds, next) {
673                                 while (kbdd_check_char(k->kbd)) {
674                                         scancode = kbdd_read_char(k->kbd, 0);
675                                         if (scancode == NOKEY)
676                                                 break;
677                                         if (scancode == ERRKEY)
678                                                 continue;
679                                         if (!KBD_IS_BUSY(k->kbd))
680                                                 continue; 
681
682                                         kbdmux_kbd_putc(state, scancode);
683                                 }
684                         }
685
686                         if (state->ks_inq_length > 0)
687                                 goto next_code;
688                 }
689
690                 KBDMUX_UNLOCK(state);
691                 return (NOKEY);
692         }
693         /* XXX FIXME: check for -1 if wait == 1! */
694
695         kbd->kb_count ++;
696
697         /* return the byte as is for the K_RAW mode */
698         if (state->ks_mode == K_RAW) {
699                 KBDMUX_UNLOCK(state);
700                 return (scancode);
701         }
702
703         /* translate the scan code into a keycode */
704         keycode = scancode & 0x7F;
705         switch (state->ks_prefix) {
706         case 0x00:      /* normal scancode */
707                 switch(scancode) {
708                 case 0xB8:      /* left alt (compose key) released */
709                         if (state->ks_flags & COMPOSE) {
710                                 state->ks_flags &= ~COMPOSE;
711                                 if (state->ks_composed_char > UCHAR_MAX)
712                                         state->ks_composed_char = 0;
713                         }
714                         break;
715                 case 0x38:      /* left alt (compose key) pressed */
716                         if (!(state->ks_flags & COMPOSE)) {
717                                 state->ks_flags |= COMPOSE;
718                                 state->ks_composed_char = 0;
719                         }
720                         break;
721                 case 0xE0:
722                 case 0xE1:
723                         state->ks_prefix = scancode;
724                         goto next_code;
725                 }
726                 break;
727         case 0xE0:      /* 0xE0 prefix */
728                 state->ks_prefix = 0;
729                 switch (keycode) {
730                 case 0x1C:      /* right enter key */
731                         keycode = 0x59;
732                         break;
733                 case 0x1D:      /* right ctrl key */
734                         keycode = 0x5A;
735                         break;
736                 case 0x35:      /* keypad divide key */
737                         keycode = 0x5B;
738                         break;
739                 case 0x37:      /* print scrn key */
740                         keycode = 0x5C;
741                         break;
742                 case 0x38:      /* right alt key (alt gr) */
743                         keycode = 0x5D;
744                         break;
745                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
746                         keycode = 0x68;
747                         break;
748                 case 0x47:      /* grey home key */
749                         keycode = 0x5E;
750                         break;
751                 case 0x48:      /* grey up arrow key */
752                         keycode = 0x5F;
753                         break;
754                 case 0x49:      /* grey page up key */
755                         keycode = 0x60;
756                         break;
757                 case 0x4B:      /* grey left arrow key */
758                         keycode = 0x61;
759                         break;
760                 case 0x4D:      /* grey right arrow key */
761                         keycode = 0x62;
762                         break;
763                 case 0x4F:      /* grey end key */
764                         keycode = 0x63;
765                         break;
766                 case 0x50:      /* grey down arrow key */
767                         keycode = 0x64;
768                         break;
769                 case 0x51:      /* grey page down key */
770                         keycode = 0x65;
771                         break;
772                 case 0x52:      /* grey insert key */
773                         keycode = 0x66;
774                         break;
775                 case 0x53:      /* grey delete key */
776                         keycode = 0x67;
777                         break;
778                 /* the following 3 are only used on the MS "Natural" keyboard */
779                 case 0x5b:      /* left Window key */
780                         keycode = 0x69;
781                         break;
782                 case 0x5c:      /* right Window key */
783                         keycode = 0x6a;
784                         break;
785                 case 0x5d:      /* menu key */
786                         keycode = 0x6b;
787                         break;
788                 case 0x5e:      /* power key */
789                         keycode = 0x6d;
790                         break;
791                 case 0x5f:      /* sleep key */
792                         keycode = 0x6e;
793                         break;
794                 case 0x63:      /* wake key */
795                         keycode = 0x6f;
796                         break;
797                 case 0x64:      /* [JP106USB] backslash, underscore */
798                         keycode = 0x73;
799                         break;
800                 default:        /* ignore everything else */
801                         goto next_code;
802                 }
803                 break;
804         case 0xE1:      /* 0xE1 prefix */
805                 /* 
806                  * The pause/break key on the 101 keyboard produces:
807                  * E1-1D-45 E1-9D-C5
808                  * Ctrl-pause/break produces:
809                  * E0-46 E0-C6 (See above.)
810                  */
811                 state->ks_prefix = 0;
812                 if (keycode == 0x1D)
813                         state->ks_prefix = 0x1D;
814                 goto next_code;
815                 /* NOT REACHED */
816         case 0x1D:      /* pause / break */
817                 state->ks_prefix = 0;
818                 if (keycode != 0x45)
819                         goto next_code;
820                 keycode = 0x68;
821                 break;
822         }
823
824         /* XXX assume 101/102 keys AT keyboard */
825         switch (keycode) {
826         case 0x5c:      /* print screen */
827                 if (state->ks_flags & ALTS)
828                         keycode = 0x54; /* sysrq */
829                 break;
830         case 0x68:      /* pause/break */
831                 if (state->ks_flags & CTLS)
832                         keycode = 0x6c; /* break */
833                 break;
834         }
835
836         /* return the key code in the K_CODE mode */
837         if (state->ks_mode == K_CODE) {
838                 KBDMUX_UNLOCK(state);
839                 return (keycode | (scancode & 0x80));
840         }
841
842         /* compose a character code */
843         if (state->ks_flags & COMPOSE) {
844                 switch (keycode | (scancode & 0x80)) {
845                 /* key pressed, process it */
846                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
847                         state->ks_composed_char *= 10;
848                         state->ks_composed_char += keycode - 0x40;
849                         if (state->ks_composed_char > UCHAR_MAX) {
850                                 KBDMUX_UNLOCK(state);
851                                 return (ERRKEY);
852                         }
853                         goto next_code;
854                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
855                         state->ks_composed_char *= 10;
856                         state->ks_composed_char += keycode - 0x47;
857                         if (state->ks_composed_char > UCHAR_MAX) {
858                                 KBDMUX_UNLOCK(state);
859                                 return (ERRKEY);
860                         }
861                         goto next_code;
862                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
863                         state->ks_composed_char *= 10;
864                         state->ks_composed_char += keycode - 0x4E;
865                         if (state->ks_composed_char > UCHAR_MAX) {
866                                 KBDMUX_UNLOCK(state);
867                                 return (ERRKEY);
868                         }
869                         goto next_code;
870                 case 0x52:      /* keypad 0 */
871                         state->ks_composed_char *= 10;
872                         if (state->ks_composed_char > UCHAR_MAX) {
873                                 KBDMUX_UNLOCK(state);
874                                 return (ERRKEY);
875                         }
876                         goto next_code;
877
878                 /* key released, no interest here */
879                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
880                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
881                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
882                 case 0xD2:                              /* keypad 0 */
883                         goto next_code;
884
885                 case 0x38:                              /* left alt key */
886                         break;
887
888                 default:
889                         if (state->ks_composed_char > 0) {
890                                 state->ks_flags &= ~COMPOSE;
891                                 state->ks_composed_char = 0;
892                                 KBDMUX_UNLOCK(state);
893                                 return (ERRKEY);
894                         }
895                         break;
896                 }
897         }
898
899         /* keycode to key action */
900         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
901                         &state->ks_state, &state->ks_accents);
902         if (action == NOKEY)
903                 goto next_code;
904
905         KBDMUX_UNLOCK(state);
906
907         return (action);
908 }
909
910 /*
911  * Check if char is waiting
912  */
913 static int
914 kbdmux_check_char(keyboard_t *kbd)
915 {
916         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
917         int              ready;
918
919         if (!KBD_IS_ACTIVE(kbd))
920                 return (FALSE);
921
922         KBDMUX_LOCK(state);
923
924         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
925                 ready = TRUE;
926         else
927                 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
928
929         KBDMUX_UNLOCK(state);
930
931         return (ready);
932 }
933
934 /*
935  * Keyboard ioctl's
936  */
937 static int
938 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
939 {
940         static int       delays[] = {
941                 250, 500, 750, 1000
942         };
943
944         static int       rates[]  =  {
945                 34,  38,  42,  46,  50,   55,  59,  63,
946                 68,  76,  84,  92,  100, 110, 118, 126,
947                 136, 152, 168, 184, 200, 220, 236, 252,
948                 272, 304, 336, 368, 400, 440, 472, 504
949         };
950
951         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
952         kbdmux_kbd_t    *k;
953         keyboard_info_t *ki;
954         int              error = 0, mode;
955 #ifdef COMPAT_FREEBSD6
956         int              ival;
957 #endif
958
959         if (state == NULL)
960                 return (ENXIO);
961
962         switch (cmd) {
963         case KBADDKBD: /* add keyboard to the mux */
964                 ki = (keyboard_info_t *) arg;
965
966                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
967                     strcmp(ki->kb_name, "*") == 0)
968                         return (EINVAL); /* bad input */
969
970                 KBDMUX_LOCK(state);
971
972                 SLIST_FOREACH(k, &state->ks_kbds, next)
973                         if (k->kbd->kb_unit == ki->kb_unit &&
974                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
975                                 break;
976
977                 if (k != NULL) {
978                         KBDMUX_UNLOCK(state);
979
980                         return (0); /* keyboard already in the mux */
981                 }
982
983                 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
984                 if (k == NULL) {
985                         KBDMUX_UNLOCK(state);
986
987                         return (ENOMEM); /* out of memory */
988                 }
989
990                 k->kbd = kbd_get_keyboard(
991                                 kbd_allocate(
992                                         ki->kb_name,
993                                         ki->kb_unit,
994                                         (void *) &k->kbd,
995                                         kbdmux_kbd_event, (void *) state));
996                 if (k->kbd == NULL) {
997                         KBDMUX_UNLOCK(state);
998                         free(k, M_KBDMUX);
999
1000                         return (EINVAL); /* bad keyboard */
1001                 }
1002
1003                 kbdd_enable(k->kbd);
1004                 kbdd_clear_state(k->kbd);
1005
1006                 /* set K_RAW mode on slave keyboard */
1007                 mode = K_RAW;
1008                 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1009                 if (error == 0) {
1010                         /* set lock keys state on slave keyboard */
1011                         mode = state->ks_state & LOCK_MASK;
1012                         error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1013                 }
1014
1015                 if (error != 0) {
1016                         KBDMUX_UNLOCK(state);
1017
1018                         kbd_release(k->kbd, &k->kbd);
1019                         k->kbd = NULL;
1020
1021                         free(k, M_KBDMUX);
1022
1023                         return (error); /* could not set mode */
1024                 }
1025
1026                 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1027
1028                 KBDMUX_UNLOCK(state);
1029                 break;
1030
1031         case KBRELKBD: /* release keyboard from the mux */
1032                 ki = (keyboard_info_t *) arg;
1033
1034                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1035                     strcmp(ki->kb_name, "*") == 0)
1036                         return (EINVAL); /* bad input */
1037
1038                 KBDMUX_LOCK(state);
1039
1040                 SLIST_FOREACH(k, &state->ks_kbds, next)
1041                         if (k->kbd->kb_unit == ki->kb_unit &&
1042                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1043                                 break;
1044
1045                 if (k != NULL) {
1046                         error = kbd_release(k->kbd, &k->kbd);
1047                         if (error == 0) {
1048                                 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1049
1050                                 k->kbd = NULL;
1051
1052                                 free(k, M_KBDMUX);
1053                         }
1054                 } else
1055                         error = ENXIO; /* keyboard is not in the mux */
1056
1057                 KBDMUX_UNLOCK(state);
1058                 break;
1059
1060         case KDGKBMODE: /* get kyboard mode */
1061                 KBDMUX_LOCK(state);
1062                 *(int *)arg = state->ks_mode;
1063                 KBDMUX_UNLOCK(state);
1064                 break;
1065
1066 #ifdef COMPAT_FREEBSD6
1067         case _IO('K', 7):
1068                 ival = IOCPARM_IVAL(arg);
1069                 arg = (caddr_t)&ival;
1070                 /* FALLTHROUGH */
1071 #endif
1072         case KDSKBMODE: /* set keyboard mode */
1073                 KBDMUX_LOCK(state);
1074
1075                 switch (*(int *)arg) {
1076                 case K_XLATE:
1077                         if (state->ks_mode != K_XLATE) {
1078                                 /* make lock key state and LED state match */
1079                                 state->ks_state &= ~LOCK_MASK;
1080                                 state->ks_state |= KBD_LED_VAL(kbd);
1081                         }
1082                         /* FALLTHROUGH */
1083
1084                 case K_RAW:
1085                 case K_CODE:
1086                         if (state->ks_mode != *(int *)arg) {
1087                                 kbdmux_clear_state_locked(state);
1088                                 state->ks_mode = *(int *)arg;
1089                         }
1090                         break;
1091
1092                 default:
1093                         error = EINVAL;
1094                         break;
1095                 }
1096
1097                 KBDMUX_UNLOCK(state);
1098                 break;
1099
1100         case KDGETLED: /* get keyboard LED */
1101                 KBDMUX_LOCK(state);
1102                 *(int *)arg = KBD_LED_VAL(kbd);
1103                 KBDMUX_UNLOCK(state);
1104                 break;
1105
1106 #ifdef COMPAT_FREEBSD6
1107         case _IO('K', 66):
1108                 ival = IOCPARM_IVAL(arg);
1109                 arg = (caddr_t)&ival;
1110                 /* FALLTHROUGH */
1111 #endif
1112         case KDSETLED: /* set keyboard LED */
1113                 KBDMUX_LOCK(state);
1114
1115                 /* NOTE: lock key state in ks_state won't be changed */
1116                 if (*(int *)arg & ~LOCK_MASK) {
1117                         KBDMUX_UNLOCK(state);
1118
1119                         return (EINVAL);
1120                 }
1121
1122                 KBD_LED_VAL(kbd) = *(int *)arg;
1123
1124                 /* KDSETLED on all slave keyboards */
1125                 SLIST_FOREACH(k, &state->ks_kbds, next)
1126                         (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1127
1128                 KBDMUX_UNLOCK(state);
1129                 break;
1130
1131         case KDGKBSTATE: /* get lock key state */
1132                 KBDMUX_LOCK(state);
1133                 *(int *)arg = state->ks_state & LOCK_MASK;
1134                 KBDMUX_UNLOCK(state);
1135                 break;
1136
1137 #ifdef COMPAT_FREEBSD6
1138         case _IO('K', 20):
1139                 ival = IOCPARM_IVAL(arg);
1140                 arg = (caddr_t)&ival;
1141                 /* FALLTHROUGH */
1142 #endif
1143         case KDSKBSTATE: /* set lock key state */
1144                 KBDMUX_LOCK(state);
1145
1146                 if (*(int *)arg & ~LOCK_MASK) {
1147                         KBDMUX_UNLOCK(state);
1148
1149                         return (EINVAL);
1150                 }
1151
1152                 state->ks_state &= ~LOCK_MASK;
1153                 state->ks_state |= *(int *)arg;
1154
1155                 /* KDSKBSTATE on all slave keyboards */
1156                 SLIST_FOREACH(k, &state->ks_kbds, next)
1157                         (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1158
1159                 KBDMUX_UNLOCK(state);
1160
1161                 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1162                 /* NOT REACHED */
1163
1164 #ifdef COMPAT_FREEBSD6
1165         case _IO('K', 67):
1166                 cmd = KDSETRAD;
1167                 ival = IOCPARM_IVAL(arg);
1168                 arg = (caddr_t)&ival;
1169                 /* FALLTHROUGH */
1170 #endif
1171         case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1172         case KDSETRAD: /* set keyboard repeat rate (old interface) */
1173                 KBDMUX_LOCK(state);
1174
1175                 if (cmd == KDSETREPEAT) {
1176                         int     i;
1177
1178                         /* lookup delay */
1179                         for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1180                                 if (((int *)arg)[0] >= delays[i])
1181                                         break;
1182                         mode = i << 5;
1183
1184                         /* lookup rate */
1185                         for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1186                                 if (((int *)arg)[1] >= rates[i])
1187                                         break;
1188                         mode |= i;
1189                 } else
1190                         mode = *(int *)arg;
1191
1192                 if (mode & ~0x7f) {
1193                         KBDMUX_UNLOCK(state);
1194
1195                         return (EINVAL);
1196                 }
1197
1198                 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1199                 kbd->kb_delay2 = rates[mode & 0x1f];
1200
1201                 /* perform command on all slave keyboards */
1202                 SLIST_FOREACH(k, &state->ks_kbds, next)
1203                         (void)kbdd_ioctl(k->kbd, cmd, arg);
1204
1205                 KBDMUX_UNLOCK(state);
1206                 break;
1207
1208         case PIO_KEYMAP:        /* set keyboard translation table */
1209         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
1210         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
1211         case PIO_DEADKEYMAP:    /* set accent key translation table */
1212                 KBDMUX_LOCK(state);
1213                 state->ks_accents = 0;
1214
1215                 /* perform command on all slave keyboards */
1216                 SLIST_FOREACH(k, &state->ks_kbds, next)
1217                         (void)kbdd_ioctl(k->kbd, cmd, arg);
1218
1219                 KBDMUX_UNLOCK(state);
1220                 /* FALLTHROUGH */
1221
1222         default:
1223                 error = genkbd_commonioctl(kbd, cmd, arg);
1224                 break;
1225         }
1226
1227         return (error);
1228 }
1229
1230 /*
1231  * Lock the access to the keyboard
1232  */
1233 static int
1234 kbdmux_lock(keyboard_t *kbd, int lock)
1235 {
1236         return (1); /* XXX */
1237 }
1238
1239 /*
1240  * Clear the internal state of the keyboard
1241  */
1242 static void
1243 kbdmux_clear_state_locked(kbdmux_state_t *state)
1244 {
1245         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1246
1247         state->ks_flags &= ~(COMPOSE|POLLING);
1248         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
1249         state->ks_accents = 0;
1250         state->ks_composed_char = 0;
1251 /*      state->ks_prefix = 0;           XXX */
1252         state->ks_inq_length = 0;
1253 }
1254
1255 static void
1256 kbdmux_clear_state(keyboard_t *kbd)
1257 {
1258         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
1259
1260         KBDMUX_LOCK(state);
1261         kbdmux_clear_state_locked(state);
1262         KBDMUX_UNLOCK(state);
1263 }
1264
1265 /*
1266  * Save the internal state
1267  */
1268 static int
1269 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1270 {
1271         if (len == 0)
1272                 return (sizeof(kbdmux_state_t));
1273         if (len < sizeof(kbdmux_state_t))
1274                 return (-1);
1275
1276         bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1277
1278         return (0);
1279 }
1280
1281 /*
1282  * Set the internal state
1283  */
1284 static int
1285 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1286 {
1287         if (len < sizeof(kbdmux_state_t))
1288                 return (ENOMEM);
1289
1290         bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1291
1292         return (0);
1293 }
1294
1295 /*
1296  * Set polling
1297  */
1298 static int
1299 kbdmux_poll(keyboard_t *kbd, int on)
1300 {
1301         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
1302         kbdmux_kbd_t    *k;
1303
1304         KBDMUX_LOCK(state);
1305
1306         if (on)
1307                 state->ks_flags |= POLLING; 
1308         else
1309                 state->ks_flags &= ~POLLING;
1310
1311         /* set poll on slave keyboards */
1312         SLIST_FOREACH(k, &state->ks_kbds, next)
1313                 kbdd_poll(k->kbd, on);
1314
1315         KBDMUX_UNLOCK(state);
1316
1317         return (0);
1318 }
1319
1320 /*****************************************************************************
1321  *****************************************************************************
1322  **                                    Module 
1323  *****************************************************************************
1324  *****************************************************************************/
1325
1326 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1327
1328 static int
1329 kbdmux_modevent(module_t mod, int type, void *data)
1330 {
1331         keyboard_switch_t       *sw;
1332         keyboard_t              *kbd;
1333         int                      error;
1334
1335         switch (type) {
1336         case MOD_LOAD:
1337                 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1338                         break;
1339
1340                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1341                         kbd_delete_driver(&kbdmux_kbd_driver);
1342                         error = ENXIO;
1343                         break;
1344                 }
1345
1346                 kbd = NULL;
1347
1348                 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1349                     (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1350                         kbd_delete_driver(&kbdmux_kbd_driver);
1351                         break;
1352                 }
1353
1354 #ifdef KBD_INSTALL_CDEV
1355                 if ((error = kbd_attach(kbd)) != 0) {
1356                         (*sw->term)(kbd);
1357                         kbd_delete_driver(&kbdmux_kbd_driver);
1358                         break;
1359                 }
1360 #endif
1361
1362                 if ((error = (*sw->enable)(kbd)) != 0) {
1363                         (*sw->disable)(kbd);
1364 #ifdef KBD_INSTALL_CDEV
1365                         kbd_detach(kbd);
1366 #endif
1367                         (*sw->term)(kbd);
1368                         kbd_delete_driver(&kbdmux_kbd_driver);
1369                         break;
1370                 }
1371                 break;
1372
1373         case MOD_UNLOAD:
1374                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1375                         panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1376
1377                 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1378                 if (kbd != NULL) {
1379                         (*sw->disable)(kbd);
1380 #ifdef KBD_INSTALL_CDEV
1381                         kbd_detach(kbd);
1382 #endif
1383                         (*sw->term)(kbd);
1384                         kbd_delete_driver(&kbdmux_kbd_driver);
1385                 }
1386                 error = 0;
1387                 break;
1388
1389         default:
1390                 error = EOPNOTSUPP;
1391                 break;
1392         }
1393
1394         return (error);
1395 }
1396
1397 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1398