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