xref: /freebsd/sys/dev/kbdmux/kbdmux.c (revision e4e9813eb92cd7c4d4b819a8fbed5cbd3d92f5d8)
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 		default:	/* ignore everything else */
789 			goto next_code;
790 		}
791 		break;
792 	case 0xE1:	/* 0xE1 prefix */
793 		/*
794 		 * The pause/break key on the 101 keyboard produces:
795 		 * E1-1D-45 E1-9D-C5
796 		 * Ctrl-pause/break produces:
797 		 * E0-46 E0-C6 (See above.)
798 		 */
799 		state->ks_prefix = 0;
800 		if (keycode == 0x1D)
801 			state->ks_prefix = 0x1D;
802 		goto next_code;
803 		/* NOT REACHED */
804 	case 0x1D:	/* pause / break */
805 		state->ks_prefix = 0;
806 		if (keycode != 0x45)
807 			goto next_code;
808 		keycode = 0x68;
809 		break;
810 	}
811 
812 	/* XXX assume 101/102 keys AT keyboard */
813 	switch (keycode) {
814 	case 0x5c:	/* print screen */
815 		if (state->ks_flags & ALTS)
816 			keycode = 0x54;	/* sysrq */
817 		break;
818 	case 0x68:	/* pause/break */
819 		if (state->ks_flags & CTLS)
820 			keycode = 0x6c;	/* break */
821 		break;
822 	}
823 
824 	/* return the key code in the K_CODE mode */
825 	if (state->ks_mode == K_CODE) {
826 		KBDMUX_UNLOCK(state);
827 		return (keycode | (scancode & 0x80));
828 	}
829 
830 	/* compose a character code */
831 	if (state->ks_flags & COMPOSE) {
832 		switch (keycode | (scancode & 0x80)) {
833 		/* key pressed, process it */
834 		case 0x47: case 0x48: case 0x49:	/* keypad 7,8,9 */
835 			state->ks_composed_char *= 10;
836 			state->ks_composed_char += keycode - 0x40;
837 			if (state->ks_composed_char > UCHAR_MAX) {
838 				KBDMUX_UNLOCK(state);
839 				return (ERRKEY);
840 			}
841 			goto next_code;
842 		case 0x4B: case 0x4C: case 0x4D:	/* keypad 4,5,6 */
843 			state->ks_composed_char *= 10;
844 			state->ks_composed_char += keycode - 0x47;
845 			if (state->ks_composed_char > UCHAR_MAX) {
846 				KBDMUX_UNLOCK(state);
847 				return (ERRKEY);
848 			}
849 			goto next_code;
850 		case 0x4F: case 0x50: case 0x51:	/* keypad 1,2,3 */
851 			state->ks_composed_char *= 10;
852 			state->ks_composed_char += keycode - 0x4E;
853 			if (state->ks_composed_char > UCHAR_MAX) {
854 				KBDMUX_UNLOCK(state);
855 				return (ERRKEY);
856 			}
857 			goto next_code;
858 		case 0x52:	/* keypad 0 */
859 			state->ks_composed_char *= 10;
860 			if (state->ks_composed_char > UCHAR_MAX) {
861 				KBDMUX_UNLOCK(state);
862 				return (ERRKEY);
863 			}
864 			goto next_code;
865 
866 		/* key released, no interest here */
867 		case 0xC7: case 0xC8: case 0xC9:	/* keypad 7,8,9 */
868 		case 0xCB: case 0xCC: case 0xCD:	/* keypad 4,5,6 */
869 		case 0xCF: case 0xD0: case 0xD1:	/* keypad 1,2,3 */
870 		case 0xD2:				/* keypad 0 */
871 			goto next_code;
872 
873 		case 0x38:				/* left alt key */
874 			break;
875 
876 		default:
877 			if (state->ks_composed_char > 0) {
878 				state->ks_flags &= ~COMPOSE;
879 				state->ks_composed_char = 0;
880 				KBDMUX_UNLOCK(state);
881 				return (ERRKEY);
882 			}
883 			break;
884 		}
885 	}
886 
887 	/* keycode to key action */
888 	action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
889 			&state->ks_state, &state->ks_accents);
890 	if (action == NOKEY)
891 		goto next_code;
892 
893 	KBDMUX_UNLOCK(state);
894 
895 	return (action);
896 }
897 
898 /*
899  * Check if char is waiting
900  */
901 static int
902 kbdmux_check_char(keyboard_t *kbd)
903 {
904 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
905 	int		 ready;
906 
907 	if (!KBD_IS_ACTIVE(kbd))
908 		return (FALSE);
909 
910 	KBDMUX_LOCK(state);
911 
912 	if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
913 		ready = TRUE;
914 	else
915 		ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE;
916 
917 	KBDMUX_UNLOCK(state);
918 
919 	return (ready);
920 }
921 
922 /*
923  * Keyboard ioctl's
924  */
925 static int
926 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
927 {
928 	static int	 delays[] = {
929 		250, 500, 750, 1000
930 	};
931 
932 	static int	 rates[]  =  {
933 		34,  38,  42,  46,  50,   55,  59,  63,
934 		68,  76,  84,  92,  100, 110, 118, 126,
935 		136, 152, 168, 184, 200, 220, 236, 252,
936 		272, 304, 336, 368, 400, 440, 472, 504
937 	};
938 
939 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
940 	kbdmux_kbd_t	*k;
941 	keyboard_info_t	*ki;
942 	int		 error = 0, mode;
943 
944 	if (state == NULL)
945 		return (ENXIO);
946 
947 	switch (cmd) {
948 	case KBADDKBD: /* add keyboard to the mux */
949 		ki = (keyboard_info_t *) arg;
950 
951 		if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
952 		    strcmp(ki->kb_name, "*") == 0)
953 			return (EINVAL); /* bad input */
954 
955 		KBDMUX_LOCK(state);
956 
957 		SLIST_FOREACH(k, &state->ks_kbds, next)
958 			if (k->kbd->kb_unit == ki->kb_unit &&
959 			    strcmp(k->kbd->kb_name, ki->kb_name) == 0)
960 				break;
961 
962 		if (k != NULL) {
963 			KBDMUX_UNLOCK(state);
964 
965 			return (0); /* keyboard already in the mux */
966 		}
967 
968 		k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
969 		if (k == NULL) {
970 			KBDMUX_UNLOCK(state);
971 
972 			return (ENOMEM); /* out of memory */
973 		}
974 
975 		k->kbd = kbd_get_keyboard(
976 				kbd_allocate(
977 					ki->kb_name,
978 					ki->kb_unit,
979 					(void *) &k->kbd,
980 					kbdmux_kbd_event, (void *) state));
981 		if (k->kbd == NULL) {
982 			KBDMUX_UNLOCK(state);
983 			free(k, M_KBDMUX);
984 
985 			return (EINVAL); /* bad keyboard */
986 		}
987 
988 		KBDMUX_ENABLE(k->kbd);
989 		KBDMUX_CLEAR_STATE(k->kbd);
990 
991 		/* set K_RAW mode on slave keyboard */
992 		mode = K_RAW;
993 		error = KBDMUX_IOCTL(k->kbd, KDSKBMODE, &mode);
994 		if (error == 0) {
995 			/* set lock keys state on slave keyboard */
996 			mode = state->ks_state & LOCK_MASK;
997 			error = KBDMUX_IOCTL(k->kbd, KDSKBSTATE, &mode);
998 		}
999 
1000 		if (error != 0) {
1001 			KBDMUX_UNLOCK(state);
1002 
1003 			kbd_release(k->kbd, &k->kbd);
1004 			k->kbd = NULL;
1005 
1006 			free(k, M_KBDMUX);
1007 
1008 			return (error); /* could not set mode */
1009 		}
1010 
1011 		SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1012 
1013 		KBDMUX_UNLOCK(state);
1014 		break;
1015 
1016 	case KBRELKBD: /* release keyboard from the mux */
1017 		ki = (keyboard_info_t *) arg;
1018 
1019 		if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1020 		    strcmp(ki->kb_name, "*") == 0)
1021 			return (EINVAL); /* bad input */
1022 
1023 		KBDMUX_LOCK(state);
1024 
1025 		SLIST_FOREACH(k, &state->ks_kbds, next)
1026 			if (k->kbd->kb_unit == ki->kb_unit &&
1027 			    strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1028 				break;
1029 
1030 		if (k != NULL) {
1031 			error = kbd_release(k->kbd, &k->kbd);
1032 			if (error == 0) {
1033 				SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1034 
1035 				k->kbd = NULL;
1036 
1037 				free(k, M_KBDMUX);
1038 			}
1039 		} else
1040 			error = ENXIO; /* keyboard is not in the mux */
1041 
1042 		KBDMUX_UNLOCK(state);
1043 		break;
1044 
1045 	case KDGKBMODE: /* get kyboard mode */
1046 		KBDMUX_LOCK(state);
1047 		*((intptr_t *) arg) = state->ks_mode;
1048 		KBDMUX_UNLOCK(state);
1049 		break;
1050 
1051 	case KDSKBMODE: /* set keyboard mode */
1052 		KBDMUX_LOCK(state);
1053 
1054 		switch (*((intptr_t *) arg)) {
1055 		case K_XLATE:
1056 			if (state->ks_mode != K_XLATE) {
1057 				/* make lock key state and LED state match */
1058 				state->ks_state &= ~LOCK_MASK;
1059 				state->ks_state |= KBD_LED_VAL(kbd);
1060                         }
1061                         /* FALLTHROUGH */
1062 
1063 		case K_RAW:
1064 		case K_CODE:
1065 			if (state->ks_mode != *((intptr_t *) arg)) {
1066 				kbdmux_clear_state_locked(state);
1067 				state->ks_mode = *((intptr_t *) arg);
1068 			}
1069 			break;
1070 
1071                 default:
1072 			error = EINVAL;
1073 			break;
1074 		}
1075 
1076 		KBDMUX_UNLOCK(state);
1077 		break;
1078 
1079 	case KDGETLED: /* get keyboard LED */
1080 		KBDMUX_LOCK(state);
1081 		*((intptr_t *) arg) = KBD_LED_VAL(kbd);
1082 		KBDMUX_UNLOCK(state);
1083 		break;
1084 
1085 	case KDSETLED: /* set keyboard LED */
1086 		KBDMUX_LOCK(state);
1087 
1088 		/* NOTE: lock key state in ks_state won't be changed */
1089 		if (*((intptr_t *) arg) & ~LOCK_MASK) {
1090 			KBDMUX_UNLOCK(state);
1091 
1092 			return (EINVAL);
1093 		}
1094 
1095 		KBD_LED_VAL(kbd) = *((intptr_t *) arg);
1096 
1097 		/* KDSETLED on all slave keyboards */
1098 		SLIST_FOREACH(k, &state->ks_kbds, next)
1099 			KBDMUX_IOCTL(k->kbd, KDSETLED, arg);
1100 
1101 		KBDMUX_UNLOCK(state);
1102 		break;
1103 
1104 	case KDGKBSTATE: /* get lock key state */
1105 		KBDMUX_LOCK(state);
1106 		*((intptr_t *) arg) = state->ks_state & LOCK_MASK;
1107 		KBDMUX_UNLOCK(state);
1108 		break;
1109 
1110 	case KDSKBSTATE: /* set lock key state */
1111 		KBDMUX_LOCK(state);
1112 
1113 		if (*((intptr_t *) arg) & ~LOCK_MASK) {
1114 			KBDMUX_UNLOCK(state);
1115 
1116 			return (EINVAL);
1117 		}
1118 
1119 		state->ks_state &= ~LOCK_MASK;
1120 		state->ks_state |= *((intptr_t *) arg);
1121 
1122 		/* KDSKBSTATE on all slave keyboards */
1123 		SLIST_FOREACH(k, &state->ks_kbds, next)
1124 			KBDMUX_IOCTL(k->kbd, KDSKBSTATE, arg);
1125 
1126 		KBDMUX_UNLOCK(state);
1127 
1128 		return (kbdmux_ioctl(kbd, KDSETLED, arg));
1129 		/* NOT REACHED */
1130 
1131 	case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1132 	case KDSETRAD: /* set keyboard repeat rate (old interface) */
1133 		KBDMUX_LOCK(state);
1134 
1135 		if (cmd == KDSETREPEAT) {
1136 			int	i;
1137 
1138 			/* lookup delay */
1139 			for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1140 				if (((intptr_t *) arg)[0] >= delays[i])
1141 					break;
1142 			mode = i << 5;
1143 
1144 			/* lookup rate */
1145 			for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1146 				if (((intptr_t *) arg)[1] >= rates[i])
1147 					break;
1148 			mode |= i;
1149 		} else
1150 			mode = *((intptr_t *) arg);
1151 
1152 		if (mode & ~0x7f) {
1153 			KBDMUX_UNLOCK(state);
1154 
1155 			return (EINVAL);
1156 		}
1157 
1158 		kbd->kb_delay1 = delays[(mode >> 5) & 3];
1159 		kbd->kb_delay2 = rates[mode & 0x1f];
1160 
1161 		/* perform command on all slave keyboards */
1162 		SLIST_FOREACH(k, &state->ks_kbds, next)
1163 			KBDMUX_IOCTL(k->kbd, cmd, arg);
1164 
1165 		KBDMUX_UNLOCK(state);
1166 		break;
1167 
1168 	case PIO_KEYMAP:	/* set keyboard translation table */
1169 	case PIO_KEYMAPENT:	/* set keyboard translation table entry */
1170 	case PIO_DEADKEYMAP:	/* set accent key translation table */
1171 		KBDMUX_LOCK(state);
1172                 state->ks_accents = 0;
1173 
1174 		/* perform command on all slave keyboards */
1175 		SLIST_FOREACH(k, &state->ks_kbds, next)
1176 			KBDMUX_IOCTL(k->kbd, cmd, arg);
1177 
1178 		KBDMUX_UNLOCK(state);
1179                 /* FALLTHROUGH */
1180 
1181 	default:
1182 		error = genkbd_commonioctl(kbd, cmd, arg);
1183 		break;
1184 	}
1185 
1186 	return (error);
1187 }
1188 
1189 /*
1190  * Lock the access to the keyboard
1191  */
1192 static int
1193 kbdmux_lock(keyboard_t *kbd, int lock)
1194 {
1195 	return (1); /* XXX */
1196 }
1197 
1198 /*
1199  * Clear the internal state of the keyboard
1200  */
1201 static void
1202 kbdmux_clear_state_locked(kbdmux_state_t *state)
1203 {
1204 	KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1205 
1206 	state->ks_flags &= ~(COMPOSE|POLLING);
1207 	state->ks_state &= LOCK_MASK;	/* preserve locking key state */
1208 	state->ks_accents = 0;
1209 	state->ks_composed_char = 0;
1210 /*	state->ks_prefix = 0;		XXX */
1211 
1212 	ndflush(&state->ks_inq, state->ks_inq.c_cc);
1213 }
1214 
1215 static void
1216 kbdmux_clear_state(keyboard_t *kbd)
1217 {
1218 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
1219 
1220 	KBDMUX_LOCK(state);
1221 	kbdmux_clear_state_locked(state);
1222 	KBDMUX_UNLOCK(state);
1223 }
1224 
1225 /*
1226  * Save the internal state
1227  */
1228 static int
1229 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1230 {
1231 	if (len == 0)
1232 		return (sizeof(kbdmux_state_t));
1233 	if (len < sizeof(kbdmux_state_t))
1234 		return (-1);
1235 
1236 	bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1237 
1238 	return (0);
1239 }
1240 
1241 /*
1242  * Set the internal state
1243  */
1244 static int
1245 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1246 {
1247 	if (len < sizeof(kbdmux_state_t))
1248 		return (ENOMEM);
1249 
1250 	bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1251 
1252 	return (0);
1253 }
1254 
1255 /*
1256  * Set polling
1257  */
1258 static int
1259 kbdmux_poll(keyboard_t *kbd, int on)
1260 {
1261 	kbdmux_state_t	*state = (kbdmux_state_t *) kbd->kb_data;
1262 	kbdmux_kbd_t	*k;
1263 
1264 	KBDMUX_LOCK(state);
1265 
1266 	if (on)
1267 		state->ks_flags |= POLLING;
1268 	else
1269 		state->ks_flags &= ~POLLING;
1270 
1271 	/* set poll on slave keyboards */
1272 	SLIST_FOREACH(k, &state->ks_kbds, next)
1273 		KBDMUX_POLL(k->kbd, on);
1274 
1275 	KBDMUX_UNLOCK(state);
1276 
1277 	return (0);
1278 }
1279 
1280 /*****************************************************************************
1281  *****************************************************************************
1282  **                                    Module
1283  *****************************************************************************
1284  *****************************************************************************/
1285 
1286 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1287 
1288 static int
1289 kbdmux_modevent(module_t mod, int type, void *data)
1290 {
1291 	keyboard_switch_t	*sw;
1292 	keyboard_t		*kbd;
1293 	int			 error;
1294 
1295 	switch (type) {
1296 	case MOD_LOAD:
1297 		if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1298 			break;
1299 
1300 		if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1301 			kbd_delete_driver(&kbdmux_kbd_driver);
1302 			error = ENXIO;
1303 			break;
1304 		}
1305 
1306 		kbd = NULL;
1307 
1308 		if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1309 		    (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1310 			kbd_delete_driver(&kbdmux_kbd_driver);
1311 			break;
1312 		}
1313 
1314 #ifdef KBD_INSTALL_CDEV
1315 		if ((error = kbd_attach(kbd)) != 0) {
1316 			(*sw->term)(kbd);
1317 			kbd_delete_driver(&kbdmux_kbd_driver);
1318 			break;
1319 		}
1320 #endif
1321 
1322 		if ((error = (*sw->enable)(kbd)) != 0) {
1323 			(*sw->disable)(kbd);
1324 #ifdef KBD_INSTALL_CDEV
1325 			kbd_detach(kbd);
1326 #endif
1327 			(*sw->term)(kbd);
1328 			kbd_delete_driver(&kbdmux_kbd_driver);
1329 			break;
1330 		}
1331 		break;
1332 
1333 	case MOD_UNLOAD:
1334 		if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1335 			panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1336 
1337 		kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1338 		if (kbd == NULL)
1339 			 panic("kbd_get_keyboard(kbd_find_keyboard(" KEYBOARD_NAME ", 0)) == NULL");
1340 
1341 		(*sw->disable)(kbd);
1342 #ifdef KBD_INSTALL_CDEV
1343 		kbd_detach(kbd);
1344 #endif
1345 		(*sw->term)(kbd);
1346 		kbd_delete_driver(&kbdmux_kbd_driver);
1347 		error = 0;
1348 		break;
1349 
1350 	default:
1351 		error = EOPNOTSUPP;
1352 		break;
1353 	}
1354 
1355 	return (0);
1356 }
1357 
1358 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1359 
1360