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