Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 /*
     29  * Console kbd multiplexor driver for Sun.
     30  * The console "zs" port is linked under us, with the "kbd" module pushed
     31  * on top of it.
     32  * Minor device 0 is what programs normally use.
     33  * Minor device 1 is used to feed predigested keystrokes to the "workstation
     34  * console" driver, which it is linked beneath.
     35  *
     36  *
     37  *     This module can support multiple keyboards to be used simultaneously.
     38  * and enable users to use at a time multiple keyboards connected to the
     39  * same system. All the keyboards are linked under conskbd, and act as a
     40  * keyboard with replicated keys.
     41  *
     42  *     The DIN keyboards of SUN, for exmple , type 3/4/5,  are supported via
     43  * a two-level architecure. The lower one is one of serialport drivers, such
     44  * as zs, se, and the upper is  "kb" STREAMS module. Currenly, the serialport
     45  * drivers don't support polled I/O interfaces, we couldn't group the keyboard
     46  * of this kind under conskbd. So we do as the follows:
     47  *
     48  *         A new ioctl CONSSETKBDTYPE interface between conskbd and lower
     49  *     keyboard drivers is added. When conskbd receives I_LINK or I_PLINK
     50  *     ioctl, it will send a CONSSETKBDTYPE ioctl to the driver which is
     51  *     requesting to be linked under conskbd. If the lower driver does't
     52  *     recognize this ioctl, the virtual keyboard will be disabled so that
     53  *     only one keyboard instance could be linked under conskbd.
     54  */
     55 #define	KEYMAP_SIZE_VARIABLE
     56 
     57 #include <sys/types.h>
     58 #include <sys/param.h>
     59 #include <sys/stropts.h>
     60 #include <sys/stream.h>
     61 #include <sys/strsubr.h>
     62 #include <sys/strsun.h>
     63 #include <sys/conf.h>
     64 #include <sys/stat.h>
     65 #include <sys/errno.h>
     66 #include <sys/modctl.h>
     67 #include <sys/kbio.h>
     68 #include <sys/ddi.h>
     69 #include <sys/sunddi.h>
     70 #include <sys/consdev.h>
     71 #include <sys/note.h>
     72 #include <sys/kmem.h>
     73 #include <sys/kstat.h>
     74 #include <sys/policy.h>
     75 #include <sys/kbd.h>
     76 #include <sys/kbtrans.h>
     77 #include <sys/promif.h>
     78 #include <sys/vuid_event.h>
     79 #include <sys/conskbd.h>
     80 #include <sys/beep.h>
     81 
     82 extern struct keyboard *kbtrans_usbkb_maptab_init(void);
     83 extern void kbtrans_usbkb_maptab_fini(struct keyboard **);
     84 extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
     85 
     86 /*
     87  * Module linkage routines for the kernel
     88  */
     89 static int conskbd_attach(dev_info_t *, ddi_attach_cmd_t);
     90 static int conskbd_detach(dev_info_t *, ddi_detach_cmd_t);
     91 static int conskbd_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
     92 
     93 /*
     94  * STREAMS queue processing procedures
     95  */
     96 static void	conskbduwsrv(queue_t *);
     97 static void	conskbdlwserv(queue_t *);
     98 static void	conskbdlrput(queue_t *, mblk_t *);
     99 static int	conskbdclose(queue_t *, int, cred_t *);
    100 static int	conskbdopen(queue_t *, dev_t *, int, int, cred_t *);
    101 
    102 
    103 /* STREAMS driver id and limit value struct */
    104 static struct module_info conskbdm_info = {
    105 	0,		/* mi_idnum */
    106 	"conskbd",	/* mi_idname */
    107 	0,		/* mi_minpsz */
    108 	1024,		/* mi_maxpsz */
    109 	2048,		/* mi_hiwat */
    110 	128		/* mi_lowat */
    111 };
    112 
    113 /*
    114  * STREAMS queue processing procedure structures
    115  */
    116 /* upper read queue processing procedure structures */
    117 static struct qinit conskbdurinit = {
    118 	NULL,			/* qi_putp */
    119 	(int (*)())NULL,	/* qi_srvp */
    120 	conskbdopen,		/* qi_qopen */
    121 	conskbdclose,		/* qi_qclose */
    122 	(int (*)())NULL,	/* qi_qadmin */
    123 	&conskbdm_info,		/* qi_minfo */
    124 	NULL			/* qi_mstat */
    125 };
    126 
    127 /* upper write queue processing procedures structuresi */
    128 static struct qinit conskbduwinit = {
    129 	(int (*)())putq,		/* qi_putp */
    130 	(int (*)())conskbduwsrv,	/* qi_srvp */
    131 	conskbdopen,			/* qi_qopen */
    132 	conskbdclose,			/* qi_qclose */
    133 	(int (*)())NULL,		/* qi_qadmin */
    134 	&conskbdm_info,			/* qi_minfo */
    135 	NULL				/* qi_mstat */
    136 };
    137 
    138 /* lower read queue processing procedures structures */
    139 static struct qinit conskbdlrinit = {
    140 	(int (*)())conskbdlrput,	/* qi_putp */
    141 	(int (*)())NULL,		/* qi_srvp */
    142 	(int (*)())NULL,		/* qi_qopen */
    143 	(int (*)())NULL,		/* qi_qclose */
    144 	(int (*)())NULL,		/* qi_qadmin */
    145 	&conskbdm_info,			/* qi_minfo */
    146 	NULL				/* qi_mstat */
    147 };
    148 
    149 /* lower write processing procedures structures */
    150 static struct qinit conskbdlwinit = {
    151 	putq,				/* qi_putp */
    152 	(int (*)())conskbdlwserv,	/* qi_srvp */
    153 	(int (*)())NULL,		/* qi_qopen */
    154 	(int (*)())NULL,		/* qi_qclose */
    155 	(int (*)())NULL,		/* qi_qadmin */
    156 	&conskbdm_info,			/* qi_minfo */
    157 	NULL				/* qi_mstat */
    158 };
    159 
    160 /* STREAMS entity declaration structure */
    161 static struct streamtab conskbd_str_info = {
    162 	&conskbdurinit,		/* st_rdinit */
    163 	&conskbduwinit,		/* st_wrinit */
    164 	&conskbdlrinit,		/* st_muxrinit */
    165 	&conskbdlwinit,		/* st_muxwinit */
    166 };
    167 
    168 
    169 /* Entry points structure */
    170 static 	struct cb_ops cb_conskbd_ops = {
    171 	nulldev,		/* cb_open */
    172 	nulldev,		/* cb_close */
    173 	nodev,			/* cb_strategy */
    174 	nodev,			/* cb_print */
    175 	nodev,			/* cb_dump */
    176 	nodev,			/* cb_read */
    177 	nodev,			/* cb_write */
    178 	nodev,			/* cb_ioctl */
    179 	nodev,			/* cb_devmap */
    180 	nodev,			/* cb_mmap */
    181 	nodev,			/* cb_segmap */
    182 	nochpoll,		/* cb_chpoll */
    183 	ddi_prop_op,		/* cb_prop_op */
    184 	&conskbd_str_info,	/* cb_stream */
    185 	D_MP | D_MTOUTPERIM | D_MTOCEXCL	/* cb_flag */
    186 };
    187 
    188 
    189 /*
    190  * Device operations structure
    191  */
    192 static struct dev_ops conskbd_ops = {
    193 	DEVO_REV,		/* devo_rev */
    194 	0,			/* devo_refcnt */
    195 	conskbd_info,		/* devo_getinfo */
    196 	nulldev,		/* devo_identify */
    197 	nulldev,		/* devo_probe */
    198 	conskbd_attach,		/* devo_attach */
    199 	conskbd_detach,		/* devo_detach */
    200 	nodev,			/* devo_reset */
    201 	&(cb_conskbd_ops),	/* devo_cb_ops */
    202 	(struct bus_ops *)NULL,	/* devo_bus_ops */
    203 	NULL,			/* devo_power */
    204 	ddi_quiesce_not_needed,		/* quiesce */
    205 };
    206 
    207 /*
    208  * Module linkage information for the kernel.
    209  */
    210 static struct modldrv modldrv = {
    211 	&mod_driverops, /* Type of module.  This one is a pseudo driver */
    212 	"conskbd multiplexer driver",
    213 	&conskbd_ops,	/* driver ops */
    214 };
    215 
    216 /*
    217  * Module linkage structure
    218  */
    219 static struct modlinkage modlinkage = {
    220 	MODREV_1,	/* ml_rev */
    221 	&modldrv,	/* ml_linkage */
    222 	NULL		/* NULL terminates the list */
    223 };
    224 
    225 /*
    226  * Debug printing
    227  */
    228 #ifndef DPRINTF
    229 #ifdef DEBUG
    230 void	conskbd_dprintf(const char *fmt, ...);
    231 #define	DPRINTF(l, m, args) \
    232 	(((l) >= conskbd_errlevel) && ((m) & conskbd_errmask) ?	\
    233 		conskbd_dprintf args :				\
    234 		(void) 0)
    235 
    236 /*
    237  * Severity levels for printing
    238  */
    239 #define	PRINT_L0	0	/* print every message */
    240 #define	PRINT_L1	1	/* debug */
    241 #define	PRINT_L2	2	/* quiet */
    242 
    243 /*
    244  * Masks
    245  */
    246 #define	PRINT_MASK_ALL		0xFFFFFFFFU
    247 uint_t	conskbd_errmask = PRINT_MASK_ALL;
    248 uint_t	conskbd_errlevel = PRINT_L2;
    249 
    250 #else
    251 #define	DPRINTF(l, m, args)	/* NOTHING */
    252 #endif
    253 #endif
    254 
    255 /*
    256  * Module global data are protected by outer perimeter. Modifying
    257  * these global data is executed in outer perimeter exclusively.
    258  * Except in conskbdopen() and conskbdclose(), which are entered
    259  * exclusively (Refer to D_MTOCEXCL flag), all changes for the
    260  * global variables are protected by qwriter().
    261  */
    262 static	queue_t	*conskbd_regqueue; /* regular keyboard queue above us */
    263 static	queue_t	*conskbd_consqueue; /* console queue above us */
    264 
    265 
    266 static dev_info_t *conskbd_dip;		/* private copy of devinfo pointer */
    267 static long	conskbd_idle_stamp;	/* seconds tstamp of latest keystroke */
    268 static struct keyboard *conskbd_keyindex;
    269 
    270 /*
    271  * Normally, kstats of type KSTAT_TYPE_NAMED have multiple elements.  In
    272  * this case we use this type for a single element because the ioctl code
    273  * for it knows how to handle mixed kernel/user data models.  Also, it
    274  * will be easier to add new statistics later.
    275  */
    276 static struct {
    277 	kstat_named_t idle_sec;		/* seconds since last keystroke */
    278 } conskbd_kstat = {
    279 	{ "idle_sec", KSTAT_DATA_LONG, }
    280 };
    281 
    282 /*
    283  * Local routines prototypes
    284  */
    285 static int conskbd_kstat_update(kstat_t *, int);
    286 
    287 static void conskbd_ioctl(queue_t *, mblk_t *);
    288 static void conskbd_ioc_plink(queue_t *, mblk_t *);
    289 static void conskbd_ioc_punlink(queue_t *, mblk_t *);
    290 static void conskbd_legacy_kbd_ioctl(queue_t *, mblk_t *);
    291 static void conskbd_virtual_kbd_ioctl(queue_t *, mblk_t *);
    292 static mblk_t *conskbd_alloc_firm_event(ushort_t, int);
    293 
    294 static conskbd_pending_msg_t *conskbd_mux_find_msg(mblk_t *);
    295 static void conskbd_mux_enqueue_msg(conskbd_pending_msg_t *);
    296 static void conskbd_mux_dequeue_msg(conskbd_pending_msg_t *);
    297 static void conskbd_link_lowque_virt(queue_t *, mblk_t *);
    298 static void conskbd_link_lowque_legacy(queue_t *, mblk_t *);
    299 
    300 static void conskbd_handle_downstream_msg(queue_t *, mblk_t *);
    301 static void conskbd_kioctype_complete(conskbd_lower_queue_t *, mblk_t *);
    302 static void conskbd_kioctrans_complete(conskbd_lower_queue_t *, mblk_t *);
    303 static void conskbd_kioclayout_complete(conskbd_lower_queue_t *, mblk_t *);
    304 static void conskbd_kiocsled_complete(conskbd_lower_queue_t *, mblk_t *);
    305 static void conskbd_mux_upstream_msg(conskbd_lower_queue_t *, mblk_t *);
    306 static void conskbd_legacy_upstream_msg(conskbd_lower_queue_t *, mblk_t *);
    307 static void conskbd_lqs_ack_complete(conskbd_lower_queue_t *, mblk_t *);
    308 
    309 static void conskbd_polledio_enter(cons_polledio_arg_t);
    310 static void conskbd_polledio_exit(cons_polledio_arg_t);
    311 static int  conskbd_polledio_ischar(cons_polledio_arg_t);
    312 static int  conskbd_polledio_getchar(cons_polledio_arg_t);
    313 static void conskbd_polledio_setled(struct kbtrans_hardware *, int);
    314 
    315 static void conskbd_streams_setled(struct kbtrans_hardware *, int);
    316 static boolean_t conskbd_override_kbtrans(queue_t *, mblk_t *);
    317 static boolean_t
    318 conskbd_polled_keycheck(struct kbtrans_hardware *,
    319 		kbtrans_key_t *, enum keystate *);
    320 
    321 /*
    322  * Callbacks needed by kbtrans
    323  */
    324 static struct kbtrans_callbacks conskbd_callbacks = {
    325 	conskbd_streams_setled,
    326 	conskbd_polledio_setled,
    327 	conskbd_polled_keycheck,
    328 };
    329 
    330 /*
    331  * Single private "global" lock for the few rare conditions
    332  * we want single-threaded.
    333  */
    334 static	kmutex_t	conskbd_msgq_lock;
    335 static	conskbd_pending_msg_t	*conskbd_msg_queue;
    336 
    337 /*
    338  * The software state structure of virtual keyboard.
    339  * Currently, only one virtual keyboard is supported.
    340  */
    341 static conskbd_state_t	conskbd = { 0 };
    342 
    343 /* This variable backs up the layout state for non-self-ID keyboards */
    344 static int kbd_layout_bak = 0;
    345 
    346 /*
    347  * _init()
    348  *
    349  * Description:
    350  *      Driver initialization, called when driver is first loaded.
    351  *      This is how access is initially given to all the static structures.
    352  *
    353  * Arguments:
    354  *      None
    355  *
    356  * Returns:
    357  *      ddi_soft_state_init() status, see ddi_soft_state_init(9f), or
    358  *      mod_install() status, see mod_install(9f)
    359  */
    360 int
    361 _init(void)
    362 {
    363 	int	error;
    364 
    365 	error = mod_install(&modlinkage);
    366 	if (error != 0) {
    367 		return (error);
    368 	}
    369 
    370 	conskbd_keyindex = kbtrans_usbkb_maptab_init();
    371 
    372 	mutex_init(&conskbd_msgq_lock, NULL, MUTEX_DRIVER, NULL);
    373 
    374 	return (error);
    375 
    376 }	/* _init() */
    377 
    378 /*
    379  * _fini()
    380  *
    381  * Description:
    382  *      Module de-initialization, called when the driver is to be unloaded.
    383  *
    384  * Arguments:
    385  *      None
    386  *
    387  * Returns:
    388  *      mod_remove() status, see mod_remove(9f)
    389  */
    390 int
    391 _fini(void)
    392 {
    393 	int	error;
    394 
    395 	error = mod_remove(&modlinkage);
    396 	if (error != 0)
    397 		return (error);
    398 	mutex_destroy(&conskbd_msgq_lock);
    399 	kbtrans_usbkb_maptab_fini(&conskbd_keyindex);
    400 
    401 	return (0);
    402 
    403 }	/* _fini() */
    404 
    405 /*
    406  * _info()
    407  *
    408  * Description:
    409  *      Module information, returns information about the driver.
    410  *
    411  * Arguments:
    412  *      modinfo         *modinfop       Pointer to the opaque modinfo structure
    413  *
    414  * Returns:
    415  *      mod_info() status, see mod_info(9f)
    416  */
    417 int
    418 _info(struct modinfo *modinfop)
    419 {
    420 	return (mod_info(&modlinkage, modinfop));
    421 
    422 }	/* _info() */
    423 
    424 
    425 /*
    426  * conskbd_attach()
    427  *
    428  * Description:
    429  * 	This routine creates two device nodes. One is the "kbd" node, which
    430  * is used by user application programs(such as Xserver).The other is the
    431  * "conskbd" node, which is an internal node. consconfig_dacf module will
    432  * open this internal node, and link the conskbd under the wc (workstaion
    433  * console).
    434  *
    435  * Arguments:
    436  *      dev_info_t      *dip    Pointer to the device's dev_info struct
    437  *      ddi_attach_cmd_t cmd    Attach command
    438  *
    439  * Returns:
    440  *      DDI_SUCCESS             The driver was initialized properly
    441  *      DDI_FAILURE             The driver couldn't be initialized properly
    442  */
    443 /*ARGSUSED*/
    444 static int
    445 conskbd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    446 {
    447 	kstat_t	*ksp;
    448 
    449 	switch (cmd) {
    450 	case DDI_ATTACH:
    451 		break;
    452 
    453 	default:
    454 		return (DDI_FAILURE);
    455 
    456 	}
    457 	if ((ddi_create_minor_node(devi, "kbd", S_IFCHR,
    458 	    0, DDI_PSEUDO, NULL) == DDI_FAILURE) ||
    459 	    (ddi_create_internal_pathname(devi, "conskbd", S_IFCHR,
    460 	    1) == DDI_FAILURE)) {
    461 		ddi_remove_minor_node(devi, NULL);
    462 		return (DDI_FAILURE);
    463 	}
    464 	conskbd_dip = devi;
    465 
    466 	ksp = kstat_create("conskbd", 0, "activity", "misc", KSTAT_TYPE_NAMED,
    467 	    sizeof (conskbd_kstat) / sizeof (kstat_named_t),
    468 	    KSTAT_FLAG_VIRTUAL);
    469 	if (ksp) {
    470 		ksp->ks_data = (void *) &conskbd_kstat;
    471 		ksp->ks_update = conskbd_kstat_update;
    472 		kstat_install(ksp);
    473 		conskbd_idle_stamp = gethrestime_sec();	/* initial value */
    474 	}
    475 
    476 	conskbd.conskbd_layout = -1;	/* invalid layout */
    477 	conskbd.conskbd_led_state = -1;
    478 	conskbd.conskbd_bypassed = B_FALSE;
    479 
    480 	return (DDI_SUCCESS);
    481 
    482 }	/* conskbd_attach() */
    483 
    484 /*
    485  * conskbd_detach()
    486  *
    487  * Description:
    488  *      Detach an instance of the conskbd driver. In fact, the driver can not
    489  * be detached.
    490  *
    491  * Arguments:
    492  *      dev_info_t              *dip    Pointer to the device's dev_info struct
    493  *      ddi_detach_cmd_t        cmd     Detach command
    494  *
    495  * Returns:
    496  *      DDI_SUCCESS     The driver was detached
    497  *      DDI_FAILURE     The driver couldn't be detached
    498  */
    499 /*ARGSUSED*/
    500 static int
    501 conskbd_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
    502 {
    503 	return (DDI_FAILURE);
    504 
    505 }	/* conskbd_detach() */
    506 
    507 /* ARGSUSED */
    508 static int
    509 conskbd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
    510 	void **result)
    511 {
    512 	register int error;
    513 
    514 	switch (infocmd) {
    515 	case DDI_INFO_DEVT2DEVINFO:
    516 		if (conskbd_dip == NULL) {
    517 			error = DDI_FAILURE;
    518 		} else {
    519 			*result = (void *) conskbd_dip;
    520 			error = DDI_SUCCESS;
    521 		}
    522 		break;
    523 	case DDI_INFO_DEVT2INSTANCE:
    524 		*result = (void *)0;
    525 		error = DDI_SUCCESS;
    526 		break;
    527 	default:
    528 		error = DDI_FAILURE;
    529 	}
    530 	return (error);
    531 
    532 }	/* conskbd_info() */
    533 
    534 /*ARGSUSED*/
    535 static int
    536 conskbdopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
    537 {
    538 	dev_t	unit;
    539 	int	err;
    540 
    541 	unit = getminor(*devp);
    542 
    543 	if (unit == 0) {
    544 		/*
    545 		 * Opening "/dev/kbd".
    546 		 */
    547 		conskbd_regqueue = q;
    548 		qprocson(q);
    549 		return (0);
    550 	} else if (unit != 1) {
    551 		/* we don't do that under Bozo's Big Tent */
    552 		return (ENODEV);
    553 	}
    554 
    555 	/*
    556 	 * Check if already initialized
    557 	 */
    558 	if (conskbd_consqueue != NULL)
    559 		return (0);
    560 
    561 	/*
    562 	 * Opening the device to be linked under the console.
    563 	 */
    564 	conskbd_consqueue = q;
    565 
    566 	if (secpolicy_console(crp) != 0)
    567 		return (EPERM);
    568 
    569 	/*
    570 	 * initialize kbtrans module for conskbd
    571 	 */
    572 	err = kbtrans_streams_init(q, sflag, (struct kbtrans_hardware *)
    573 	    &conskbd, &conskbd_callbacks, &conskbd.conskbd_kbtrans, 0, 0);
    574 	if (err != 0)
    575 		return (err);
    576 	kbtrans_streams_set_keyboard(conskbd.conskbd_kbtrans, KB_USB,
    577 	    conskbd_keyindex);
    578 
    579 	conskbd.conskbd_polledio.cons_polledio_version = CONSPOLLEDIO_V1;
    580 	conskbd.conskbd_polledio.cons_polledio_argument =
    581 	    (cons_polledio_arg_t)&conskbd;
    582 	conskbd.conskbd_polledio.cons_polledio_putchar = NULL;
    583 	conskbd.conskbd_polledio.cons_polledio_getchar =
    584 	    (int (*)(cons_polledio_arg_t)) conskbd_polledio_getchar;
    585 	conskbd.conskbd_polledio.cons_polledio_ischar =
    586 	    (boolean_t (*)(cons_polledio_arg_t))conskbd_polledio_ischar;
    587 	conskbd.conskbd_polledio.cons_polledio_enter = conskbd_polledio_enter;
    588 	conskbd.conskbd_polledio.cons_polledio_exit = conskbd_polledio_exit;
    589 	qprocson(q);
    590 
    591 	return (0);
    592 
    593 }	/* conskbdopen() */
    594 
    595 
    596 /*ARGSUSED*/
    597 static int
    598 conskbdclose(queue_t *q, int flag, cred_t *crp)
    599 {
    600 	if (q == conskbd_regqueue) {
    601 
    602 		conskbd_pending_msg_t	*pmsg, *prev, *next;
    603 		mblk_t		*mp;
    604 
    605 		/* switch the input stream back to conskbd_consqueue */
    606 		conskbd.conskbd_directio = B_FALSE;
    607 
    608 		kbtrans_streams_untimeout(conskbd.conskbd_kbtrans);
    609 		kbtrans_streams_set_queue(conskbd.conskbd_kbtrans,
    610 		    conskbd_consqueue);
    611 		qprocsoff(q);
    612 		conskbd_regqueue = NULL;
    613 
    614 		/*
    615 		 * If there are any pending ioctls which conskbd hasn't
    616 		 * responded to yet, remove them from conskbd_msg_queue.
    617 		 * Otherwise, we might send the response to a nonexistent
    618 		 * closed queue. Refer to: conskbd_mux_upstream_msg().
    619 		 */
    620 		for (prev = NULL, pmsg = conskbd_msg_queue; pmsg != NULL;
    621 		    pmsg = next) {
    622 			next = pmsg->kpm_next;
    623 			if (pmsg->kpm_upper_queue == WR(q)) {
    624 				if (prev == NULL)
    625 					conskbd_msg_queue = next;
    626 				else
    627 					prev->kpm_next = next;
    628 
    629 				while (pmsg->kpm_resp_list != NULL) {
    630 					mp = pmsg->kpm_resp_list;
    631 					pmsg->kpm_resp_list = mp->b_next;
    632 					mp->b_next = mp->b_prev = NULL;
    633 					freemsg(mp);
    634 				}
    635 				mutex_destroy(&pmsg->kpm_lock);
    636 				kmem_free(pmsg, sizeof (*pmsg));
    637 			} else {
    638 				prev = pmsg;
    639 			}
    640 		}
    641 	} else if (q == conskbd_consqueue) {
    642 		/*
    643 		 * Well, this is probably a mistake, but we will permit you
    644 		 * to close the path to the console if you really insist.
    645 		 */
    646 		qprocsoff(q);
    647 		conskbd_consqueue = NULL;
    648 	}
    649 
    650 	return (0);
    651 
    652 }	/* conskbdclose() */
    653 
    654 /*
    655  * Service procedure for upper write queue.
    656  *	To make sure the order of messages, we don't process any
    657  * message in qi_putq() routine of upper write queue, instead the
    658  * qi_putq() routine, which is a standard putq() routine, puts all
    659  * messages into a queue, and lets the following service procedure
    660  * deal with all messages.
    661  * 	This routine is invoked when ioctl commands are send down
    662  * by a consumer of the keyboard device, eg, when the keyboard
    663  * consumer tries to determine the keyboard layout type, or sets
    664  * the led states.
    665  */
    666 static void
    667 conskbduwsrv(queue_t *q)
    668 {
    669 	mblk_t	*mp;
    670 	queue_t	*oldq;
    671 	enum kbtrans_message_response ret;
    672 	struct copyresp *csp;
    673 	struct freq_request *frqp;
    674 	int error;
    675 
    676 	while ((mp = getq(q)) != NULL) {
    677 
    678 		/*
    679 		 * if the virtual keyboard is supported
    680 		 */
    681 		if (conskbd.conskbd_bypassed == B_FALSE) {
    682 
    683 			if (conskbd_override_kbtrans(q, mp) == B_TRUE)
    684 				continue;
    685 			/*
    686 			 * The conskbd driver is a psaudo driver. It has two
    687 			 * devcice nodes, one is used by kernel, and the other
    688 			 * is used by end-users. There are two STREAMS queues
    689 			 * corresponding to the two device nodes, console queue
    690 			 * and regular queue.
    691 			 * In conskbd_override_kbtrans() routine, when receives
    692 			 * KIOCSDIRECT ioctl, we need change the direction of
    693 			 * keyboard input messages, and direct the input stream
    694 			 * from keyboard into right queue. It causes this queue
    695 			 * to be switched between regular queue and console
    696 			 * queue. And here, in this routine, the in-parameter
    697 			 * "q" can be any one of the two. Moreover, this module
    698 			 * is executed in multithreaded environment, even if the
    699 			 * q is switched to regular queue, it is possible that
    700 			 * the in-parameter is still the console queue, and we
    701 			 * need to return response to right queue.
    702 			 * The response is sent to upstream by the kbtrans
    703 			 * module. so we need to save the old queue, and wait
    704 			 * kbtrans to proces message and to send response out,
    705 			 * and then switch back to old queue.
    706 			 */
    707 			oldq = kbtrans_streams_get_queue(
    708 			    conskbd.conskbd_kbtrans);
    709 			kbtrans_streams_set_queue(
    710 			    conskbd.conskbd_kbtrans, RD(q));
    711 			ret = kbtrans_streams_message(
    712 			    conskbd.conskbd_kbtrans, mp);
    713 			kbtrans_streams_set_queue(
    714 			    conskbd.conskbd_kbtrans, oldq);
    715 
    716 			switch (ret) {
    717 				case KBTRANS_MESSAGE_HANDLED:
    718 					continue;
    719 				case KBTRANS_MESSAGE_NOT_HANDLED:
    720 					break;
    721 			}
    722 		}
    723 
    724 		switch (mp->b_datap->db_type) {
    725 
    726 		case M_IOCTL:
    727 			conskbd_ioctl(q, mp);
    728 			break;
    729 
    730 		case M_FLUSH:
    731 			if (*mp->b_rptr & FLUSHW) {
    732 				flushq(q, FLUSHDATA);
    733 			}
    734 			/*
    735 			 * here, if flush read queue, some key-up messages
    736 			 * may be lost so that upper module or applications
    737 			 * treat corresponding keys as being held down for
    738 			 * ever.
    739 			 */
    740 			freemsg(mp);
    741 			break;
    742 
    743 		case M_DATA:
    744 			/*
    745 			 * virtual keyboard doesn't support this interface.
    746 			 * only when it is disabled, we pass the message
    747 			 * down to lower queue.
    748 			 */
    749 			if ((conskbd.conskbd_bypassed) &&
    750 			    (conskbd.conskbd_lqueue_nums > 0)) {
    751 				if (putq(conskbd.conskbd_lqueue_list->
    752 				    lqs_queue, mp) != 1)
    753 					freemsg(mp);
    754 			} else {
    755 				freemsg(mp);
    756 			}
    757 			break;
    758 
    759 		case M_IOCDATA:
    760 			/*
    761 			 * Only deal with copyresp to KIOCSETFREQ
    762 			 * transparent ioctl now
    763 			 */
    764 			csp = (struct copyresp *)mp->b_rptr;
    765 			if (csp->cp_rval) {
    766 				miocnak(q, mp, 0, EINVAL);
    767 				break;
    768 			}
    769 
    770 			error = 0;
    771 			switch (csp->cp_cmd) {
    772 			case KIOCSETFREQ:
    773 				frqp = (struct freq_request *)mp->
    774 				    b_cont->b_rptr;
    775 
    776 				switch (frqp->type) {
    777 				case CONSOLE_BEEP:
    778 					error = beeper_freq(BEEP_CONSOLE,
    779 					    (int)frqp->freq);
    780 						break;
    781 
    782 				case KBD_BEEP:
    783 					error = beeper_freq(BEEP_TYPE4,
    784 					    (int)frqp->freq);
    785 						break;
    786 
    787 				default:
    788 					error = 1;
    789 				} /* frqp->type */
    790 
    791 				break;
    792 
    793 			default:
    794 				error = 1;
    795 			} /* csp->cp_cmd */
    796 
    797 			if (error == 0)
    798 				miocack(q, mp, 0, 0);
    799 			else
    800 				miocnak(q, mp, 0, EINVAL);
    801 
    802 			break;
    803 
    804 		default:
    805 			/*
    806 			 * Pass an error message up.
    807 			 */
    808 			mp->b_datap->db_type = M_ERROR;
    809 			if (mp->b_cont) {
    810 				freemsg(mp->b_cont);
    811 				mp->b_cont = NULL;
    812 			}
    813 			mp->b_rptr = mp->b_datap->db_base;
    814 			mp->b_wptr = mp->b_rptr + sizeof (char);
    815 			*mp->b_rptr = EINVAL;
    816 			qreply(q, mp);
    817 		}
    818 	}	/* end of while */
    819 
    820 }	/* conskbduwsrv() */
    821 
    822 static void
    823 conskbd_ioctl(queue_t *q, mblk_t *mp)
    824 {
    825 	struct	iocblk			*iocp;
    826 	int	error = 0;
    827 
    828 	iocp = (struct iocblk *)mp->b_rptr;
    829 
    830 	switch (iocp->ioc_cmd) {
    831 
    832 	case I_LINK:
    833 	case I_PLINK:
    834 		if (conskbd.conskbd_bypassed == B_TRUE) {
    835 		/*
    836 		 * A legacy keyboard can NOT be connected to conskbd together
    837 		 * with other keyboards. So when a legacy keyboard is already
    838 		 * linked under conkbd, we just reject all others.
    839 		 */
    840 			miocnak(q, mp, 0, EAGAIN);
    841 			break;
    842 		}
    843 		qwriter(q, mp, conskbd_ioc_plink, PERIM_OUTER);
    844 		break;
    845 
    846 	case I_UNLINK:
    847 	case I_PUNLINK:
    848 		qwriter(q, mp, conskbd_ioc_punlink, PERIM_OUTER);
    849 		break;
    850 
    851 	case KIOCSKABORTEN:
    852 		/*
    853 		 * Check if privileged
    854 		 */
    855 		if ((error = secpolicy_sys_config(iocp->ioc_cr, B_FALSE))) {
    856 			miocnak(q, mp, 0, error);
    857 			return;
    858 		}
    859 
    860 		error = miocpullup(mp, sizeof (int));
    861 		if (error != 0) {
    862 			miocnak(q, mp, 0, error);
    863 			return;
    864 		}
    865 
    866 		abort_enable = *(int *)mp->b_cont->b_rptr;
    867 		miocack(q, mp, 0, 0);
    868 		break;
    869 
    870 	case KIOCSETFREQ:
    871 		if (iocp->ioc_count != TRANSPARENT) {
    872 			/*
    873 			 * We don't support non-transparent ioctls,
    874 			 * i.e. I_STR ioctls
    875 			 */
    876 			miocnak(q, mp, 0, EINVAL);
    877 		} else {
    878 			/* Transparent ioctl */
    879 			mcopyin(mp, NULL, sizeof (struct freq_request), NULL);
    880 			qreply(q, mp);
    881 		}
    882 		break;
    883 
    884 	default:
    885 		if (conskbd.conskbd_bypassed == B_TRUE) {
    886 			conskbd_legacy_kbd_ioctl(q, mp);
    887 		} else {
    888 			conskbd_virtual_kbd_ioctl(q, mp);
    889 		}
    890 	}
    891 
    892 }	/* conskbd_ioctl() */
    893 
    894 
    895 static void
    896 conskbd_virtual_kbd_ioctl(queue_t *q, mblk_t *mp)
    897 {
    898 	struct iocblk		*iocp;
    899 	mblk_t			*datap;
    900 	int			cmd;
    901 	int			error = 0;
    902 
    903 	iocp = (struct iocblk *)mp->b_rptr;
    904 
    905 	switch (iocp->ioc_cmd) {
    906 	case KIOCLAYOUT:
    907 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    908 			miocnak(q, mp, 0, ENOMEM);
    909 			break;
    910 		}
    911 
    912 		if (conskbd.conskbd_layout == -1)
    913 			*(int *)datap->b_wptr = KBTRANS_USBKB_DEFAULT_LAYOUT;
    914 		else
    915 			*(int *)datap->b_wptr = conskbd.conskbd_layout;
    916 
    917 		datap->b_wptr += sizeof (int);
    918 		if (mp->b_cont)
    919 			freemsg(mp->b_cont);
    920 		mp->b_cont = datap;
    921 		miocack(q, mp, sizeof (int), 0);
    922 		break;
    923 
    924 	case KIOCSLAYOUT:
    925 		if (iocp->ioc_count != TRANSPARENT) {
    926 			miocnak(q, mp, 0, EINVAL);
    927 			break;
    928 		}
    929 		kbd_layout_bak = conskbd.conskbd_layout;
    930 		conskbd.conskbd_layout = *(intptr_t *)(mp->b_cont->b_rptr);
    931 		if (conskbd.conskbd_layout != kbd_layout_bak) {
    932 
    933 			/* notify the upper of the change event */
    934 			if ((datap = conskbd_alloc_firm_event(
    935 			    KEYBOARD_LAYOUT_CHANGE,
    936 			    conskbd.conskbd_layout)) != NULL) {
    937 				if (conskbd.conskbd_directio) {
    938 					putnext(conskbd_regqueue, datap);
    939 				} else {
    940 					freemsg(datap);
    941 				}
    942 			}
    943 		}
    944 		miocack(q, mp, 0, 0);
    945 		break;
    946 
    947 	case CONSOPENPOLLEDIO:
    948 		error = miocpullup(mp, sizeof (struct cons_polledio *));
    949 		if (error != 0) {
    950 			miocnak(q, mp, 0, error);
    951 			break;
    952 		}
    953 		if (conskbd.conskbd_lqueue_list == NULL) {
    954 			miocnak(q, mp, 0, EINVAL);
    955 			break;
    956 		}
    957 		conskbd_handle_downstream_msg(q, mp);
    958 		break;
    959 
    960 	case CONSCLOSEPOLLEDIO:
    961 		if (conskbd.conskbd_lqueue_list == NULL) {
    962 			miocnak(q, mp, 0, EINVAL);
    963 			break;
    964 		}
    965 		conskbd_handle_downstream_msg(q, mp);
    966 		break;
    967 
    968 	case CONSSETABORTENABLE:
    969 		/*
    970 		 * To enable combined STOP-A(or F1-A) to trap into kmdb,
    971 		 * the lower physical keyboard drivers are always told not
    972 		 * to parse abort sequence(refer to consconfig_dacf module).
    973 		 * Instead, lower drivers always send all keydown & keyup
    974 		 * messages up to conskbd, so that when key STOP(or F1) is
    975 		 * pressed on one keyboard and key A is pressed on another
    976 		 * keyboard, the system could trap into kmdb.
    977 		 *
    978 		 * When we by kbtrans_streams_message() invoked kbtrans to
    979 		 * handle ioctls in conskbduwsrv() routine, kbtrans module
    980 		 * already handle the message though it returned to us a
    981 		 * KBTRANS_MESSAGE_NOT_HANDLED. For virtual keyboard, no
    982 		 * special initialization or un-initialization is needed.
    983 		 * So we just return ACK to upper module.
    984 		 */
    985 		miocack(q, mp, 0, 0);
    986 		break;
    987 
    988 	case KIOCCMD:
    989 	case KIOCMKTONE:
    990 		if (conskbd.conskbd_lqueue_list == NULL ||
    991 		    mp->b_cont == NULL) {
    992 			miocnak(q, mp, 0, EINVAL);
    993 			break;
    994 		}
    995 		cmd = *(int *)mp->b_cont->b_rptr;
    996 		if (cmd == KBD_CMD_GETLAYOUT) {
    997 			freemsg(mp->b_cont);
    998 			datap = allocb(sizeof (int), BPRI_HI);
    999 			if (datap == NULL) {
   1000 				miocnak(q, mp, 0, ENOMEM);
   1001 				return;
   1002 			}
   1003 			if (conskbd.conskbd_layout == -1)
   1004 				*(int *)datap->b_wptr =
   1005 				    KBTRANS_USBKB_DEFAULT_LAYOUT;
   1006 			else
   1007 				*(int *)datap->b_wptr = conskbd.conskbd_layout;
   1008 
   1009 			mp->b_cont = datap;
   1010 			miocack(q, mp, sizeof (int), 0);
   1011 			return;
   1012 		}
   1013 		conskbd_handle_downstream_msg(q, mp);
   1014 		break;
   1015 
   1016 	default:
   1017 		miocnak(q, mp, 0, EINVAL);
   1018 		break;
   1019 	}
   1020 
   1021 }	/* conskbd_virtual_kbd_ioctl() */
   1022 
   1023 static void
   1024 conskbd_legacy_kbd_ioctl(queue_t *q, mblk_t *mp)
   1025 {
   1026 	conskbd_lower_queue_t	*lq;
   1027 	struct	iocblk		*iocp;
   1028 	int	error = 0;
   1029 
   1030 	iocp = (struct iocblk *)mp->b_rptr;
   1031 
   1032 	ASSERT(conskbd.conskbd_lqueue_nums == 1);
   1033 	switch (iocp->ioc_cmd) {
   1034 
   1035 	case KIOCGDIRECT: {
   1036 		mblk_t *datap;
   1037 
   1038 		if ((datap = allocb(sizeof (int), BPRI_MED)) == NULL) {
   1039 			miocnak(q, mp, 0, ENOMEM);
   1040 			break;
   1041 		}
   1042 
   1043 		*(int *)datap->b_wptr = conskbd.conskbd_directio;
   1044 		datap->b_wptr += sizeof (int);
   1045 		if (mp->b_cont != NULL) {
   1046 			freemsg(mp->b_cont);
   1047 			mp->b_cont = NULL;
   1048 		}
   1049 		mp->b_cont = datap;
   1050 		miocack(q, mp, sizeof (int), 0);
   1051 		break;
   1052 	}
   1053 
   1054 	case KIOCSDIRECT:
   1055 		error = miocpullup(mp, sizeof (int));
   1056 		if (error != 0) {
   1057 			miocnak(q, mp, 0, error);
   1058 			break;
   1059 		}
   1060 		conskbd.conskbd_directio = *(int *)mp->b_cont->b_rptr;
   1061 
   1062 		/*
   1063 		 * Pass this through, if there's something to pass
   1064 		 * it through to, so the system keyboard can reset
   1065 		 * itself.
   1066 		 */
   1067 		if (conskbd.conskbd_lqueue_nums > 0) {
   1068 			lq = conskbd.conskbd_lqueue_list;
   1069 			ASSERT(lq && lq->lqs_next == NULL);
   1070 			if (putq(lq->lqs_queue, mp) != 1) {
   1071 				miocnak(q, mp, 0, ENOMEM);
   1072 				return;
   1073 			}
   1074 			break;
   1075 		}
   1076 
   1077 		miocack(q, mp, 0, 0);
   1078 		break;
   1079 
   1080 	default:
   1081 		/*
   1082 		 * Pass this through, if there's something to pass it
   1083 		 * through to; otherwise, reject it.
   1084 		 */
   1085 		if (conskbd.conskbd_lqueue_nums > 0) {
   1086 			lq = conskbd.conskbd_lqueue_list;
   1087 			ASSERT(lq && lq->lqs_next == NULL);
   1088 			if (putq(lq->lqs_queue, mp) != 1) {
   1089 				miocnak(q, mp, 0, ENOMEM);
   1090 				return;
   1091 			}
   1092 			break;
   1093 		}
   1094 
   1095 		/* nobody below us; reject it */
   1096 		miocnak(q, mp, 0, EINVAL);
   1097 		break;
   1098 	}
   1099 
   1100 }	/* conskbd_legacy_kbd_ioctl() */
   1101 
   1102 
   1103 /*
   1104  * Service procedure for lower write queue.
   1105  * Puts things on the queue below us, if it lets us.
   1106  */
   1107 static void
   1108 conskbdlwserv(queue_t *q)
   1109 {
   1110 	register mblk_t *mp;
   1111 
   1112 	while (canput(q->q_next) && (mp = getq(q)) != NULL)
   1113 		putnext(q, mp);
   1114 
   1115 }	/* conskbdlwserv() */
   1116 
   1117 /*
   1118  * Put procedure for lower read queue.
   1119  * Pass everything up to minor device 0 if "directio" set, otherwise to minor
   1120  * device 1.
   1121  */
   1122 static void
   1123 conskbdlrput(queue_t *q, mblk_t *mp)
   1124 {
   1125 	conskbd_lower_queue_t	*lqs;
   1126 	struct iocblk 	*iocp;
   1127 	Firm_event	*fe;
   1128 
   1129 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, ("conskbdlrput\n"));
   1130 
   1131 	switch (mp->b_datap->db_type) {
   1132 
   1133 	case M_FLUSH:
   1134 		if (*mp->b_rptr == FLUSHR) {
   1135 			flushq(q, FLUSHDATA);	/* XXX doesn't flush M_DELAY */
   1136 			*mp->b_rptr &= ~FLUSHR;	/* it has been flushed */
   1137 		}
   1138 		if (*mp->b_rptr == FLUSHW) {
   1139 			flushq(WR(q), FLUSHDATA);
   1140 			qreply(q, mp);	/* give the read queues a crack at it */
   1141 		} else
   1142 			freemsg(mp);
   1143 		break;
   1144 
   1145 	case M_DATA:
   1146 		if (conskbd.conskbd_bypassed == B_FALSE) {
   1147 
   1148 			fe = (Firm_event *)mp->b_rptr;
   1149 
   1150 			/*
   1151 			 * This is a workaround.
   1152 			 *
   1153 			 * According to HID specification, there are the
   1154 			 * following keycode mapping between PS2 and USB,
   1155 			 *
   1156 			 *	PS2 AT-101 keycode(29)  --->    USB(49)
   1157 			 *	PS2 AT-102 keycode(42)  --->    USB(50)
   1158 			 *
   1159 			 * However, the two keys, AT-101(29) and AT-102(42),
   1160 			 * have the same scancode,0x2B, in PS2 scancode SET1
   1161 			 * which we are using. The Kb8042 driver always
   1162 			 * recognizes the two keys as PS2(29) so that we could
   1163 			 * not know which is being pressed or released when we
   1164 			 * receive scancode 0x2B. Fortunately, the two keys can
   1165 			 * not co-exist in a specific layout. In other words,
   1166 			 * in the table of keycode-to-symbol mapping, either
   1167 			 * entry 49 or 50 is a hole. So, if we're processing a
   1168 			 * keycode 49, we look at the entry for 49.  If it's
   1169 			 * HOLE, remap the key to 50; If we're processing a 50,
   1170 			 * look at the entry for 50.  If it's HOLE, we remap
   1171 			 * the key to 49.
   1172 			 */
   1173 			if (fe->id == 49 || fe->id == 50) {
   1174 				if (conskbd_keyindex->k_normal[50] == HOLE)
   1175 					fe->id = 49;
   1176 				else
   1177 					fe->id = 50;
   1178 			}
   1179 
   1180 			/*
   1181 			 * Remember key state of each key of lower physical
   1182 			 * keyboard. When a keyboard is umplumbed from conskbd,
   1183 			 * we will check all key states. By then,  we will fake
   1184 			 * a KEY_RELEASED message for each key in KEY_PRESSED
   1185 			 * state. Otherwise, upper module will treat these keys
   1186 			 * as held-down for ever.
   1187 			 */
   1188 			iocp = (struct iocblk *)mp->b_rptr;
   1189 			lqs = (conskbd_lower_queue_t *)q->q_ptr;
   1190 			if (fe->value)
   1191 				lqs->lqs_key_state[fe->id] = KEY_PRESSED;
   1192 			else
   1193 				lqs->lqs_key_state[fe->id] = KEY_RELEASED;
   1194 
   1195 			kbtrans_streams_key(conskbd.conskbd_kbtrans,
   1196 			    fe->id, fe->value ? KEY_PRESSED : KEY_RELEASED);
   1197 			freemsg(mp);
   1198 		} else {
   1199 			if (conskbd.conskbd_directio)
   1200 				putnext(conskbd_regqueue, mp);
   1201 			else if (conskbd_consqueue != NULL)
   1202 				putnext(conskbd_consqueue, mp);
   1203 			else
   1204 				freemsg(mp);
   1205 		}
   1206 		conskbd_idle_stamp = gethrestime_sec();
   1207 		break;
   1208 
   1209 	case M_IOCACK:
   1210 	case M_IOCNAK:
   1211 		iocp = (struct iocblk *)mp->b_rptr;
   1212 		lqs = (conskbd_lower_queue_t *)q->q_ptr;
   1213 
   1214 		DPRINTF(PRINT_L1, PRINT_MASK_ALL, ("conskbdlrput: "
   1215 		    "ACK/NAK - cmd 0x%x\n", iocp->ioc_cmd));
   1216 
   1217 		conskbd_lqs_ack_complete(lqs, mp);
   1218 		break;
   1219 
   1220 	case M_ERROR:
   1221 	case M_HANGUP:
   1222 	default:
   1223 		freemsg(mp);	/* anything useful here? */
   1224 		break;
   1225 	}
   1226 
   1227 }	/* conskbdlrput() */
   1228 
   1229 
   1230 /* ARGSUSED */
   1231 static int
   1232 conskbd_kstat_update(kstat_t *ksp, int rw)
   1233 {
   1234 	if (rw == KSTAT_WRITE)
   1235 		return (EACCES);
   1236 
   1237 	conskbd_kstat.idle_sec.value.l = gethrestime_sec() - conskbd_idle_stamp;
   1238 
   1239 	return (0);
   1240 
   1241 }	/* conskbd_kstat_update() */
   1242 
   1243 /*
   1244  * STREAMS architecuture provides guarantee that the ID of each
   1245  * message, iocblk.ioc_id, in a stream is unique. The following
   1246  * routine performes the task: When receive request from upstream,
   1247  * it saves the request in a global link list, clones the request,
   1248  * and then sends a copy of the request to each of lower queues
   1249  * which are plumbed into conskbd. And then, when receives responses
   1250  * from lower queues in conskbdlrput() routine, we can know the
   1251  * request matching received responses by searching the global linked
   1252  * list to find the request which has the same message ID of the
   1253  * response. Then, when all lower queues response this request, we
   1254  * give a response to upstreams based the following policy:
   1255  * If any one of lower queues acks our reuqest, then we return ack
   1256  * to upstreams; only if all lower queues nak our request, we return
   1257  * nak to upstreams. If all responses are nak, the error number of
   1258  * the first response is sent to upstream.
   1259  */
   1260 static void
   1261 conskbd_handle_downstream_msg(queue_t *q, mblk_t *mp)
   1262 {
   1263 	conskbd_pending_msg_t	*msg;
   1264 	conskbd_lower_queue_t	*lqs;
   1265 	struct iocblk	*iocp;
   1266 	mblk_t		*clonemp;
   1267 	int		retry;
   1268 
   1269 	if (conskbd.conskbd_lqueue_nums == 0) {
   1270 		miocnak(q, mp, 0, EINVAL);
   1271 		return;
   1272 	}
   1273 
   1274 	msg = (conskbd_pending_msg_t *)
   1275 	    kmem_zalloc(sizeof (conskbd_pending_msg_t), KM_SLEEP);
   1276 	mutex_init(&msg->kpm_lock, NULL, MUTEX_DRIVER, NULL);
   1277 	lqs = conskbd.conskbd_lqueue_list;
   1278 	iocp = (struct iocblk *)mp->b_rptr;
   1279 
   1280 	ASSERT(iocp->ioc_cmd == CONSOPENPOLLEDIO ||
   1281 	    iocp->ioc_cmd == CONSCLOSEPOLLEDIO ||
   1282 	    iocp->ioc_cmd == KIOCCMD ||
   1283 	    iocp->ioc_cmd == KIOCMKTONE);
   1284 
   1285 	msg->kpm_upper_queue = q;
   1286 	msg->kpm_req_msg = mp;
   1287 	msg->kpm_req_id = iocp->ioc_id;
   1288 	msg->kpm_req_cmd = iocp->ioc_cmd;
   1289 	msg->kpm_req_nums = conskbd.conskbd_lqueue_nums;
   1290 	conskbd_mux_enqueue_msg(msg);
   1291 
   1292 	for (retry = 0, lqs = conskbd.conskbd_lqueue_list; lqs; ) {
   1293 
   1294 		/*
   1295 		 * if a lower physical keyboard is not in polled I/O
   1296 		 * mode, we couldn't send CONSCLOSEPOLLEDIO to it,
   1297 		 * otherwise, system will panic.
   1298 		 */
   1299 		if (iocp->ioc_cmd == CONSCLOSEPOLLEDIO &&
   1300 		    lqs->lqs_polledio == NULL) {
   1301 			lqs = lqs->lqs_next;
   1302 			msg->kpm_req_nums --;
   1303 			retry = 0;
   1304 			continue;
   1305 		}
   1306 
   1307 		clonemp = copymsg(mp);
   1308 		if (clonemp != NULL) {
   1309 			if (putq(lqs->lqs_queue, clonemp) == 1) {
   1310 				lqs = lqs->lqs_next;
   1311 				retry = 0;
   1312 				continue;
   1313 			}
   1314 
   1315 			/*
   1316 			 * failed to invoke putq(), retry.
   1317 			 */
   1318 			freemsg(clonemp);
   1319 		}
   1320 
   1321 		/*
   1322 		 * During testing it was observed that occasionally
   1323 		 * copymsg() would fail during boot. The reason for
   1324 		 * these failures is unknown. Since we really want
   1325 		 * to successfully plumb up all the attached keyboards
   1326 		 * during boot we do a best effort here by retrying
   1327 		 * the copymsg() call in the hopes that it will
   1328 		 * succeeded upon subsequent invocations.
   1329 		 *
   1330 		 * If all the calls to copymsg() fails, it will cause
   1331 		 * the corresponding keyboard to be unavailable, or
   1332 		 * or behave weirdly,
   1333 		 *
   1334 		 * 1) for CONSOPENPOLLEDIO
   1335 		 *	if copymsg()fails, the corresponding keyboard
   1336 		 *	is not available in polled I/O mode once
   1337 		 *	entering kmdb;
   1338 		 * 2) for CONSCLOSEPOLLEDIO
   1339 		 *	if copymsg() fails, the corresponding keyboard
   1340 		 *	is not available in normal mode once returning
   1341 		 *	from kmdb;
   1342 		 * 3) for KIOCCMD
   1343 		 * 	3.1) for KBD_CMD_NOBELL
   1344 		 * 		there's no beep in USB and PS2 keyboard,
   1345 		 * 		this ioctl actually disables the beep on
   1346 		 * 		system mainboard. Note that all the cloned
   1347 		 * 		messages sent down to lower queues do the
   1348 		 * 		same job for system mainboard. Therefore,
   1349 		 * 		even if we fail to send this ioctl to most
   1350 		 * 		of lower queues, the beep still would be
   1351 		 * 		disabled. So, no trouble exists here.
   1352 		 *	3.2) for others
   1353 		 *		nothing;
   1354 		 *
   1355 		 * However, all cases could be resume next time when the
   1356 		 * same request comes again.
   1357 		 */
   1358 		if (retry ++ >= 5) {
   1359 			dev_t	devt;
   1360 			char	path[MAXPATHLEN + 1];
   1361 
   1362 			devt = lqs->lqs_queue->q_stream->sd_vnode->v_rdev;
   1363 			switch (iocp->ioc_cmd) {
   1364 			case CONSOPENPOLLEDIO:
   1365 				if (ddi_dev_pathname(devt, S_IFCHR,
   1366 				    path) == DDI_SUCCESS)
   1367 					cmn_err(CE_WARN, "conskbd: "
   1368 					    "keyboard is not available"
   1369 					    " for system debugging: %s",
   1370 					    path);
   1371 				break;
   1372 
   1373 			case CONSCLOSEPOLLEDIO:
   1374 				if (ddi_dev_pathname(devt, S_IFCHR,
   1375 				    path) == DDI_SUCCESS)
   1376 					cmn_err(CE_WARN, "conskbd: "
   1377 					    "keyboard is not available:"
   1378 					    " %s", path);
   1379 				break;
   1380 
   1381 			default:
   1382 				break;
   1383 			}
   1384 			msg->kpm_req_nums --;
   1385 			lqs = lqs->lqs_next;
   1386 			retry = 0;
   1387 		}
   1388 	}
   1389 
   1390 	if (msg->kpm_req_nums == 0) {
   1391 		conskbd_mux_dequeue_msg(msg);
   1392 		kmem_free(msg, sizeof (*msg));
   1393 		miocnak(q, mp, 0, ENOMEM);
   1394 	}
   1395 
   1396 }	/* conskbd_handle_downstream_msg() */
   1397 
   1398 
   1399 static void
   1400 conskbd_ioc_plink(queue_t *q, mblk_t *mp)
   1401 {
   1402 	mblk_t		*req;
   1403 	queue_t		*lowque;
   1404 	struct linkblk		*linkp;
   1405 	conskbd_lower_queue_t	*lqs;
   1406 
   1407 	lqs = kmem_zalloc(sizeof (*lqs), KM_SLEEP);
   1408 	ASSERT(lqs->lqs_state == LQS_UNINITIALIZED);
   1409 
   1410 	linkp = (struct linkblk *)mp->b_cont->b_rptr;
   1411 	lowque = linkp->l_qbot;
   1412 
   1413 	lqs->lqs_queue = lowque;
   1414 	lqs->lqs_pending_plink = mp;
   1415 	lqs->lqs_pending_queue = q;
   1416 
   1417 	req = mkiocb(CONSSETKBDTYPE);
   1418 	if (req == NULL) {
   1419 		miocnak(q, mp, 0, ENOMEM);
   1420 		kmem_free(lqs, sizeof (*lqs));
   1421 		return;
   1422 	}
   1423 
   1424 	req->b_cont = allocb(sizeof (int), BPRI_MED);
   1425 	if (req->b_cont == NULL) {
   1426 		freemsg(req);
   1427 		miocnak(q, mp, 0, ENOMEM);
   1428 		kmem_free(lqs, sizeof (*lqs));
   1429 		return;
   1430 	}
   1431 
   1432 	lowque->q_ptr = lqs;
   1433 	OTHERQ(lowque)->q_ptr = lqs;
   1434 	*(int *)req->b_cont->b_wptr = KB_USB;
   1435 	req->b_cont->b_wptr += sizeof (int);
   1436 
   1437 	lqs->lqs_state = LQS_KIOCTYPE_ACK_PENDING;
   1438 
   1439 	if (putq(lowque, req) != 1) {
   1440 		freemsg(req);
   1441 		miocnak(lqs->lqs_pending_queue,
   1442 		    lqs->lqs_pending_plink, 0, ENOMEM);
   1443 		lowque->q_ptr = NULL;
   1444 		OTHERQ(lowque)->q_ptr = NULL;
   1445 		kmem_free(lqs, sizeof (*lqs));
   1446 	}
   1447 
   1448 }	/* conskbd_ioc_plink() */
   1449 
   1450 
   1451 static void
   1452 conskbd_ioc_punlink(queue_t *q, mblk_t *mp)
   1453 {
   1454 	int			index;
   1455 	struct linkblk		*linkp;
   1456 	conskbd_lower_queue_t	*lqs;
   1457 	conskbd_lower_queue_t	*prev;
   1458 
   1459 	linkp = (struct linkblk *)mp->b_cont->b_rptr;
   1460 	prev = conskbd.conskbd_lqueue_list;
   1461 	for (lqs = prev; lqs; lqs = lqs->lqs_next) {
   1462 		if (lqs->lqs_queue == linkp->l_qbot) {
   1463 			if (prev == lqs)
   1464 				conskbd.conskbd_lqueue_list =
   1465 				    lqs->lqs_next;
   1466 			else
   1467 				prev->lqs_next = lqs->lqs_next;
   1468 
   1469 			lqs->lqs_queue->q_ptr =  NULL;
   1470 			OTHERQ(lqs->lqs_queue)->q_ptr = NULL;
   1471 			conskbd.conskbd_lqueue_nums --;
   1472 			if (conskbd.conskbd_lqueue_nums == 0) {
   1473 				kbd_layout_bak = conskbd.conskbd_layout;
   1474 				conskbd.conskbd_layout = -1;
   1475 			}
   1476 
   1477 			for (index = 0; index < KBTRANS_KEYNUMS_MAX; index ++) {
   1478 				if (lqs->lqs_key_state[index] == KEY_PRESSED)
   1479 					kbtrans_streams_key(
   1480 					    conskbd.conskbd_kbtrans,
   1481 					    index,
   1482 					    KEY_RELEASED);
   1483 			}
   1484 
   1485 			kmem_free(lqs, sizeof (*lqs));
   1486 			miocack(q, mp, 0, 0);
   1487 			return;
   1488 		}
   1489 		prev = lqs;
   1490 	}
   1491 	miocnak(q, mp, 0, EINVAL);
   1492 
   1493 }	/* conskbd_ioc_punlink() */
   1494 
   1495 /*
   1496  * Every physical keyboard has a corresponding STREAMS queue. We call this
   1497  * queue lower queue. Every lower queue has a state, refer to conskbd.h file
   1498  * about "enum conskbd_lqs_state".
   1499  * The following routine is used to handle response messages from lower queue.
   1500  * When receiving ack/nak message from lower queue(s), the routine determines
   1501  * the passage for it according to the current state of this lower queue.
   1502  */
   1503 static void
   1504 conskbd_lqs_ack_complete(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1505 {
   1506 	switch (lqs->lqs_state) {
   1507 
   1508 	/* S6: working in virtual keyboard mode, multi-keyboards are usable */
   1509 	case LQS_INITIALIZED:
   1510 		conskbd_mux_upstream_msg(lqs, mp);
   1511 		break;
   1512 
   1513 	/* S5: working in legacy mode, only one keyboard is usable */
   1514 	case LQS_INITIALIZED_LEGACY:
   1515 		conskbd_legacy_upstream_msg(lqs, mp);
   1516 		break;
   1517 
   1518 	/* S4: wait lower queue to acknowledge KIOCSLED/KIOCGLED  message */
   1519 	case LQS_KIOCSLED_ACK_PENDING:
   1520 		conskbd_kiocsled_complete(lqs, mp);
   1521 		break;
   1522 
   1523 	/* S3: wait lower queue to acknowledge KIOCLAYOUT  message */
   1524 	case LQS_KIOCLAYOUT_ACK_PENDING:
   1525 		conskbd_kioclayout_complete(lqs, mp);
   1526 		break;
   1527 
   1528 	/* S2: wait lower queue to acknowledge KIOCTRANS  message */
   1529 	case LQS_KIOCTRANS_ACK_PENDING:
   1530 		conskbd_kioctrans_complete(lqs, mp);
   1531 		break;
   1532 
   1533 	/* S1: wait lower queue to acknowledge KIOCTYPE  message */
   1534 	case LQS_KIOCTYPE_ACK_PENDING:
   1535 		conskbd_kioctype_complete(lqs, mp);
   1536 		break;
   1537 
   1538 	/* if reaching here, there must be a error */
   1539 	default:
   1540 		freemsg(mp);
   1541 		cmn_err(CE_WARN, "conskbd: lqs_ack_complete() state error");
   1542 		break;
   1543 	}
   1544 
   1545 }	/* conskbd_lqs_ack_complete() */
   1546 
   1547 
   1548 static void
   1549 conskbd_kioctype_complete(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1550 {
   1551 	struct iocblk	*iocp;
   1552 	mblk_t		*req;
   1553 	queue_t		*lowerque;
   1554 	int		err = ENOMEM;
   1555 
   1556 	ASSERT(lqs->lqs_pending_plink);
   1557 	ASSERT(lqs->lqs_state == LQS_KIOCTYPE_ACK_PENDING);
   1558 
   1559 	lowerque = lqs->lqs_queue;
   1560 
   1561 	switch (mp->b_datap->db_type) {
   1562 	case M_IOCACK:
   1563 		req = mkiocb(KIOCTRANS);
   1564 		if (req == NULL) {
   1565 			goto err_exit;
   1566 		}
   1567 
   1568 		req->b_cont = allocb(sizeof (int), BPRI_MED);
   1569 		if (req->b_cont == NULL) {
   1570 			freemsg(req);
   1571 			goto err_exit;
   1572 		}
   1573 
   1574 		/* Set the translate mode to TR_UNTRANS_EVENT */
   1575 		*(int *)req->b_cont->b_wptr = TR_UNTRANS_EVENT;
   1576 		req->b_cont->b_wptr += sizeof (int);
   1577 
   1578 		/* Ready to handle the response to KIOCTRANS */
   1579 		lqs->lqs_state = LQS_KIOCTRANS_ACK_PENDING;
   1580 
   1581 		if (putq(lowerque, req) != 1) {
   1582 			freemsg(req);
   1583 			goto err_exit;
   1584 		}
   1585 		freemsg(mp);
   1586 		return;
   1587 
   1588 	case M_IOCNAK:
   1589 		/*
   1590 		 * The lower keyboard driver can't mimic USB keyboard,
   1591 		 * that's say, the physical keyboard is an old one, such
   1592 		 * as TYPE 3/4/5 one. In this case, the virtual keyboard
   1593 		 * is disabled, and the data from lower keyboard driver
   1594 		 * will bypass the conskbd module.
   1595 		 */
   1596 
   1597 		/*
   1598 		 * if there is any other keyborad already linked under the
   1599 		 * conskbd, we reject the current one.
   1600 		 */
   1601 		if (conskbd.conskbd_lqueue_nums > 0) {
   1602 			iocp = (struct iocblk *)mp->b_rptr;
   1603 			err = iocp->ioc_error;
   1604 			goto err_exit;
   1605 		}
   1606 
   1607 		/*
   1608 		 * link this keyboard under conskbd.
   1609 		 */
   1610 		qwriter(lowerque, mp, conskbd_link_lowque_legacy, PERIM_OUTER);
   1611 		return;
   1612 	}
   1613 
   1614 err_exit:
   1615 	miocnak(lqs->lqs_pending_queue, lqs->lqs_pending_plink, 0, err);
   1616 	lowerque->q_ptr = NULL;
   1617 	OTHERQ(lowerque)->q_ptr = NULL;
   1618 	kmem_free(lqs, sizeof (*lqs));
   1619 	freemsg(mp);
   1620 
   1621 }	/* conskbd_kioctype_complete() */
   1622 
   1623 static void
   1624 conskbd_kioctrans_complete(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1625 {
   1626 	struct iocblk 	*iocp;
   1627 	mblk_t		*req;
   1628 	queue_t		*lowerque;
   1629 	int		err = ENOMEM;
   1630 
   1631 	ASSERT(lqs->lqs_pending_plink != NULL);
   1632 	ASSERT(lqs->lqs_state == LQS_KIOCTRANS_ACK_PENDING);
   1633 
   1634 	lowerque = lqs->lqs_queue;
   1635 
   1636 	switch (mp->b_datap->db_type) {
   1637 	case M_IOCACK:
   1638 		req = mkiocb(KIOCLAYOUT);
   1639 		if (req == NULL) {
   1640 			goto err_exit;
   1641 		}
   1642 
   1643 		req->b_cont = allocb(sizeof (int), BPRI_MED);
   1644 		if (req->b_cont == NULL) {
   1645 			freemsg(req);
   1646 			goto err_exit;
   1647 		}
   1648 
   1649 		/* waiting for response to KIOCLAYOUT */
   1650 		lqs->lqs_state = LQS_KIOCLAYOUT_ACK_PENDING;
   1651 		if (putq(lqs->lqs_queue, req) != 1) {
   1652 			freemsg(req);
   1653 			goto err_exit;
   1654 		}
   1655 		freemsg(mp);
   1656 		return;
   1657 
   1658 	case M_IOCNAK:
   1659 		iocp = (struct iocblk *)mp->b_rptr;
   1660 		err = iocp->ioc_error;
   1661 		goto err_exit;
   1662 	}
   1663 
   1664 err_exit:
   1665 	miocnak(lqs->lqs_pending_queue, lqs->lqs_pending_plink, 0, err);
   1666 	lowerque->q_ptr = NULL;
   1667 	OTHERQ(lowerque)->q_ptr = NULL;
   1668 	kmem_free(lqs, sizeof (*lqs));
   1669 	freemsg(mp);
   1670 
   1671 }	/* conskbd_kioctrans_complete() */
   1672 
   1673 /*
   1674  * Allocate a firm event
   1675  */
   1676 static mblk_t *
   1677 conskbd_alloc_firm_event(ushort_t id, int value)
   1678 {
   1679 	mblk_t	*mb;
   1680 	Firm_event *fe;
   1681 
   1682 	if ((mb = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
   1683 		fe = (Firm_event *)mb->b_wptr;
   1684 		fe->id = id;
   1685 		fe->pair_type = FE_PAIR_NONE;
   1686 		fe->pair = NULL;
   1687 		fe->value = value;
   1688 		mb->b_wptr += sizeof (Firm_event);
   1689 	}
   1690 
   1691 	return (mb);
   1692 }
   1693 
   1694 static void
   1695 conskbd_kioclayout_complete(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1696 {
   1697 	mblk_t		*req;
   1698 	int		layout;
   1699 	boolean_t	fail;
   1700 
   1701 	ASSERT(lqs->lqs_pending_plink != NULL);
   1702 	ASSERT(lqs->lqs_state == LQS_KIOCLAYOUT_ACK_PENDING);
   1703 
   1704 	switch (mp->b_datap->db_type) {
   1705 	case M_IOCACK:
   1706 		if (miocpullup(mp, sizeof (int)) == 0) {
   1707 			layout = *(int *)mp->b_cont->b_rptr;
   1708 			/*
   1709 			 * We just accept the layout of the first keyboard
   1710 			 * requesting to be linked under conskbd. If current
   1711 			 * keyboard is the first one, and if we get right
   1712 			 * layout from it, we set conskbd's layout
   1713 			 */
   1714 			if (layout != -1 && conskbd.conskbd_layout == -1) {
   1715 				if (layout == 0) {
   1716 					conskbd.conskbd_layout = kbd_layout_bak;
   1717 				} else {
   1718 					conskbd.conskbd_layout = layout;
   1719 					if (layout == kbd_layout_bak) {
   1720 						break;
   1721 					}
   1722 					if ((req = conskbd_alloc_firm_event(
   1723 					    KEYBOARD_LAYOUT_CHANGE,
   1724 					    layout)) != NULL) {
   1725 						if (conskbd.conskbd_directio) {
   1726 							putnext(
   1727 							    conskbd_regqueue,
   1728 							    req);
   1729 						} else if (conskbd_consqueue
   1730 						    != NULL) {
   1731 							putnext(
   1732 							    conskbd_consqueue,
   1733 							    req);
   1734 						} else {
   1735 							freemsg(req);
   1736 						}
   1737 					}
   1738 				}
   1739 			}
   1740 		}
   1741 		break;
   1742 
   1743 
   1744 	/* if fail, leave conskbd's layout as it is */
   1745 	case M_IOCNAK:
   1746 		break;
   1747 	}
   1748 
   1749 	fail = B_TRUE;
   1750 
   1751 	if (conskbd.conskbd_led_state == -1)
   1752 		req = mkiocb(KIOCGLED);
   1753 	else
   1754 		req = mkiocb(KIOCSLED);
   1755 
   1756 	if (req) {
   1757 		req->b_cont = allocb(sizeof (uchar_t), BPRI_MED);
   1758 		if (req->b_cont) {
   1759 			if (conskbd.conskbd_led_state != -1) {
   1760 				*(uchar_t *)req->b_cont->b_wptr =
   1761 				    conskbd.conskbd_led_state;
   1762 				req->b_cont->b_wptr += sizeof (uchar_t);
   1763 			}
   1764 
   1765 			/* waiting for response to KIOCSLED */
   1766 			lqs->lqs_state = LQS_KIOCSLED_ACK_PENDING;
   1767 			if (putq(lqs->lqs_queue, req) == 1) {
   1768 				fail = B_FALSE;
   1769 			} else {
   1770 				freemsg(req);
   1771 			}
   1772 
   1773 		} else {
   1774 			freemsg(req);
   1775 		}
   1776 	}
   1777 
   1778 	if (fail) {
   1779 		/*
   1780 		 * If fail to allocate KIOCSLED/KIOCGLED message or put
   1781 		 * the message into lower queue, we immediately link
   1782 		 * current keyboard under conskbd. Thus, even if fails
   1783 		 * to set/get LED, this keyboard could be available.
   1784 		 */
   1785 		qwriter(lqs->lqs_queue,
   1786 		    mp, conskbd_link_lowque_virt, PERIM_OUTER);
   1787 	} else {
   1788 		freemsg(mp);
   1789 	}
   1790 
   1791 }	/* conskbd_kioclayout_complete() */
   1792 
   1793 
   1794 static void
   1795 conskbd_kiocsled_complete(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1796 {
   1797 	int	led_state;
   1798 
   1799 	ASSERT(lqs->lqs_pending_plink != NULL);
   1800 	ASSERT(lqs->lqs_state == LQS_KIOCSLED_ACK_PENDING);
   1801 
   1802 	if (conskbd.conskbd_led_state == -1) {
   1803 		switch (mp->b_datap->db_type) {
   1804 		case M_IOCACK:
   1805 			if (miocpullup(mp, sizeof (uchar_t)) == 0) {
   1806 				led_state = *(uchar_t *)mp->b_cont->b_rptr;
   1807 				conskbd.conskbd_led_state = led_state;
   1808 				kbtrans_streams_setled(conskbd.conskbd_kbtrans,
   1809 				    led_state);
   1810 			}
   1811 			break;
   1812 
   1813 		/* if fail, leave conskbd's led_state as it is */
   1814 		case M_IOCNAK:
   1815 			break;
   1816 		}
   1817 	}
   1818 
   1819 	/*
   1820 	 * Basically, failure of setting/getting LED is not a fatal
   1821 	 * error, so we will plumb the lower queue into conskbd whether
   1822 	 * setting/getting LED succeeds or fails.
   1823 	 */
   1824 	qwriter(lqs->lqs_queue, mp, conskbd_link_lowque_virt, PERIM_OUTER);
   1825 
   1826 }	/* conskbd_kiocsled_complete() */
   1827 
   1828 
   1829 static void
   1830 conskbd_mux_upstream_msg(conskbd_lower_queue_t *lqs, mblk_t *mp)
   1831 {
   1832 	conskbd_pending_msg_t	*msg;
   1833 	struct iocblk		*iocp;
   1834 	int			error;
   1835 	dev_t			devt;
   1836 	char			path[MAXPATHLEN + 1];
   1837 
   1838 	ASSERT(lqs->lqs_state == LQS_INITIALIZED);
   1839 	msg = conskbd_mux_find_msg(mp);
   1840 
   1841 	if (!msg) {
   1842 		/*
   1843 		 * Here we discard the response if:
   1844 		 *
   1845 		 *   1. It's an KIOCSLED request; see conskbd_streams_setled().
   1846 		 *   2. The application has already closed the upper stream;
   1847 		 *		see conskbdclose()
   1848 		 */
   1849 		freemsg(mp);
   1850 		return;
   1851 	}
   1852 
   1853 	/*
   1854 	 * We use the b_next field of mblk_t structure to link all
   1855 	 * response coming from lower queues into a linkage list,
   1856 	 * and make use of the b_prev field to save a pointer to
   1857 	 * the lower queue from which the current response message
   1858 	 * comes.
   1859 	 */
   1860 	ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
   1861 	mutex_enter(&msg->kpm_lock);
   1862 	mp->b_next = msg->kpm_resp_list;
   1863 	mp->b_prev = (mblk_t *)lqs;
   1864 	msg->kpm_resp_list = mp;
   1865 	msg->kpm_resp_nums ++;
   1866 
   1867 	if (msg->kpm_resp_nums < msg->kpm_req_nums) {
   1868 		mutex_exit(&msg->kpm_lock);
   1869 		return;
   1870 	}
   1871 
   1872 	ASSERT(msg->kpm_resp_nums == msg->kpm_req_nums);
   1873 	ASSERT(mp == msg->kpm_resp_list);
   1874 
   1875 	mutex_exit(&msg->kpm_lock);
   1876 
   1877 	conskbd_mux_dequeue_msg(msg);
   1878 
   1879 
   1880 	/*
   1881 	 * Here, we have the policy that, if any one lower queue ACK
   1882 	 * our reuqest, then we return ACK to upstreams; only if all
   1883 	 * lower queues NAK our request, we return NAK to upstreams.
   1884 	 * if all responses are nak, the errno of the  first response
   1885 	 * is sent to upstreams
   1886 	 */
   1887 	ASSERT(mp->b_rptr);
   1888 	error = ((struct iocblk *)mp->b_rptr)->ioc_error;
   1889 
   1890 	switch (msg->kpm_req_cmd) {
   1891 	case CONSOPENPOLLEDIO:
   1892 		/*
   1893 		 * Here, we can safely ignore the NAK message. If any one lower
   1894 		 * queue returns NAK, the pointer to the corresponding polledio
   1895 		 * structure will remain null, that's say lqs->lqs_polledio =
   1896 		 * null. When we need to invoke polled I/O interface, we will
   1897 		 * check if the pointer is null.
   1898 		 */
   1899 		for (mp = msg->kpm_resp_list; mp; ) {
   1900 			cons_polledio_t		*polledio;
   1901 
   1902 			msg->kpm_resp_list = mp->b_next;
   1903 			lqs = (conskbd_lower_queue_t *)mp->b_prev;
   1904 			devt = lqs->lqs_queue->q_stream->sd_vnode->v_rdev;
   1905 			if (mp->b_datap->db_type == M_IOCACK) {
   1906 				polledio = *(struct cons_polledio **)
   1907 				    mp->b_cont->b_rptr;
   1908 				if (polledio->cons_polledio_version ==
   1909 				    CONSPOLLEDIO_V1) {
   1910 					lqs->lqs_polledio = polledio;
   1911 					error = 0;
   1912 				} else {
   1913 					/*
   1914 					 * USB and PS2 keyboard drivers should
   1915 					 * use the same cons_polledio structure
   1916 					 * as conskbd.
   1917 					 */
   1918 					if (ddi_dev_pathname(devt, S_IFCHR,
   1919 					    path) == DDI_SUCCESS) {
   1920 						cmn_err(CE_WARN, "keyboard "
   1921 						    "driver does not support "
   1922 						    "system debugging: %s",
   1923 						    path);
   1924 					}
   1925 					error = EINVAL;
   1926 				}
   1927 			} else {
   1928 				if (ddi_dev_pathname(devt, S_IFCHR, path) ==
   1929 				    DDI_SUCCESS) {
   1930 					cmn_err(CE_WARN, "conskbd: keyboard is"
   1931 					    " not available for system"
   1932 					    " debugging:  %s", path);
   1933 				}
   1934 			}
   1935 			mp->b_next = NULL;
   1936 			mp->b_prev = NULL;
   1937 			freemsg(mp);
   1938 			mp = msg->kpm_resp_list;
   1939 		}
   1940 
   1941 		mp = msg->kpm_req_msg;
   1942 		if (error == 0) {
   1943 			*(struct cons_polledio **)mp->b_cont->b_rptr =
   1944 			    &conskbd.conskbd_polledio;
   1945 		}
   1946 		break;
   1947 
   1948 	case CONSCLOSEPOLLEDIO:
   1949 		for (mp = msg->kpm_resp_list; mp; ) {
   1950 			msg->kpm_resp_list = mp->b_next;
   1951 			lqs = (conskbd_lower_queue_t *)mp->b_prev;
   1952 			if (mp->b_datap->db_type == M_IOCACK) {
   1953 				lqs->lqs_polledio = NULL;
   1954 				error = 0;
   1955 			} else {
   1956 				devt =
   1957 				    lqs->lqs_queue->q_stream->sd_vnode->v_rdev;
   1958 
   1959 				if (ddi_dev_pathname(devt, S_IFCHR, path) ==
   1960 				    DDI_SUCCESS) {
   1961 					cmn_err(CE_WARN, "conskbd: keyboard is"
   1962 					    " not available: %s", path);
   1963 				}
   1964 			}
   1965 
   1966 			mp->b_next = NULL;
   1967 			mp->b_prev = NULL;
   1968 			freemsg(mp);
   1969 			mp = msg->kpm_resp_list;
   1970 		}
   1971 		break;
   1972 
   1973 	case KIOCCMD:
   1974 	case KIOCMKTONE:
   1975 		for (mp = msg->kpm_resp_list; mp; ) {
   1976 			msg->kpm_resp_list = mp->b_next;
   1977 
   1978 			if (mp->b_datap->db_type == M_IOCACK)
   1979 				error = 0;
   1980 			mp->b_next = NULL;
   1981 			mp->b_prev = NULL;
   1982 			freemsg(mp);
   1983 			mp = msg->kpm_resp_list;
   1984 		}
   1985 		break;
   1986 
   1987 	default:  /* it is impossible to reach here */
   1988 		cmn_err(CE_WARN, "conskbd: unexpected ioctl reply");
   1989 	}
   1990 
   1991 	mp = msg->kpm_req_msg;
   1992 	if (error == 0) {
   1993 		mp->b_datap->db_type = M_IOCACK;
   1994 	} else {
   1995 		mp->b_datap->db_type = M_IOCNAK;
   1996 	}
   1997 	iocp = (struct iocblk *)mp->b_rptr;
   1998 	iocp->ioc_error = error;
   1999 	qreply(msg->kpm_upper_queue, mp);
   2000 	mutex_destroy(&msg->kpm_lock);
   2001 	kmem_free(msg, sizeof (*msg));
   2002 
   2003 }	/* conskbd_mux_upstream_msg() */
   2004 
   2005 static void
   2006 conskbd_link_lowque_legacy(queue_t *lowque, mblk_t *mp)
   2007 {
   2008 	conskbd_lower_queue_t *lqs;
   2009 
   2010 	freemsg(mp);
   2011 
   2012 	/*
   2013 	 * Bypass the virutal keyboard for old hardware,
   2014 	 * Now, only current legacy keyboard can be linked
   2015 	 * under conskbd
   2016 	 */
   2017 	conskbd.conskbd_bypassed = B_TRUE;
   2018 
   2019 	/*
   2020 	 * Link the lower queue under conskbd
   2021 	 */
   2022 	lqs = (conskbd_lower_queue_t *)lowque->q_ptr;
   2023 	lqs->lqs_state = LQS_INITIALIZED_LEGACY;
   2024 	lqs->lqs_next = conskbd.conskbd_lqueue_list;
   2025 	conskbd.conskbd_lqueue_list = lqs;
   2026 	conskbd.conskbd_lqueue_nums++;
   2027 
   2028 	mioc2ack(lqs->lqs_pending_plink, NULL, 0, 0);
   2029 	qreply(lqs->lqs_pending_queue, lqs->lqs_pending_plink);
   2030 
   2031 }	/* conskbd_link_lowque_legacy() */
   2032 
   2033 static void
   2034 conskbd_link_lowque_virt(queue_t *lowque, mblk_t *mp)
   2035 {
   2036 	int		index;
   2037 	conskbd_lower_queue_t *lqs;
   2038 
   2039 	freemsg(mp);
   2040 
   2041 	lqs = (conskbd_lower_queue_t *)lowque->q_ptr;
   2042 
   2043 	ASSERT(lqs->lqs_queue == lowque);
   2044 	ASSERT(lqs->lqs_pending_plink != NULL);
   2045 
   2046 	/*
   2047 	 * Now, link the lower queue under conskbd
   2048 	 */
   2049 	for (index = 0; index < KBTRANS_KEYNUMS_MAX; index ++) {
   2050 		lqs->lqs_key_state[index] = KEY_RELEASED;
   2051 	}
   2052 	lqs->lqs_next = conskbd.conskbd_lqueue_list;
   2053 	lqs->lqs_state = LQS_INITIALIZED;
   2054 	conskbd.conskbd_lqueue_nums++;
   2055 	conskbd.conskbd_lqueue_list = lqs;
   2056 	mioc2ack(lqs->lqs_pending_plink, NULL, 0, 0);
   2057 	qreply(lqs->lqs_pending_queue, lqs->lqs_pending_plink);
   2058 
   2059 }	/* conskbd_link_lowque_virt() */
   2060 
   2061 /*ARGSUSED*/
   2062 static void
   2063 conskbd_legacy_upstream_msg(conskbd_lower_queue_t *lqs, mblk_t *mp)
   2064 {
   2065 	struct iocblk	*iocp;
   2066 
   2067 	ASSERT(lqs && lqs->lqs_state == LQS_INITIALIZED_LEGACY);
   2068 
   2069 	/*
   2070 	 * We assume that all of the ioctls are headed to the
   2071 	 * conskbd_regqueue if it is open.  We are intercepting a few ioctls
   2072 	 * that we know belong to conskbd_consqueue, and sending them there.
   2073 	 * Any other, new ioctls that have to be routed to conskbd_consqueue
   2074 	 * should be added to this list.
   2075 	 */
   2076 	iocp = (struct iocblk *)mp->b_rptr;
   2077 
   2078 	if ((iocp->ioc_cmd == CONSOPENPOLLEDIO) ||
   2079 	    (iocp->ioc_cmd == CONSCLOSEPOLLEDIO)) {
   2080 
   2081 		DPRINTF(PRINT_L1, PRINT_MASK_ALL,
   2082 		    ("conskbd_legacy_upstream_msg: "
   2083 		    "CONSOPEN/CLOSEPOLLEDIO ACK/NAK\n"));
   2084 		putnext(conskbd_consqueue, mp);
   2085 
   2086 	} else if (conskbd_regqueue != NULL) {
   2087 		DPRINTF(PRINT_L1, PRINT_MASK_ALL,
   2088 		    ("conskbd_legacy_upstream_msg: conskbd_regqueue != NULL"));
   2089 
   2090 		putnext(conskbd_regqueue, mp);
   2091 
   2092 	} else if (conskbd_consqueue != NULL) {
   2093 		DPRINTF(PRINT_L1, PRINT_MASK_ALL,
   2094 		    ("conskbd_legacy_upstream_msg: conskbd_consqueue != NULL"));
   2095 		putnext(conskbd_consqueue, mp);
   2096 	} else {
   2097 		/* if reached here, it must be a error */
   2098 		cmn_err(CE_WARN,
   2099 		    "kb:  no destination for IOCACK/IOCNAK!");
   2100 		freemsg(mp);
   2101 	}
   2102 
   2103 }	/* conskbd_legacy_upstream_msg() */
   2104 
   2105 /*
   2106  * This routine is a callback routine for kbtrans module to set LED.
   2107  * Kbtrans will invoke it in two cases:
   2108  *
   2109  * 1) application initiated request
   2110  * 	A KIOCSLED ioctl is sent by an application. The ioctl will be
   2111  * 	be prcoessed by queue service procedure conskbduwsrv(), which
   2112  * 	in turn calls kbtrans to process the ioctl. Then kbtrans invokes
   2113  * 	conskbd_streams_setled() to set LED, after that,  kbtrans will
   2114  * 	return an ACK message to upper module.
   2115  *
   2116  * 2) Kbtrans initiated the request
   2117  *	When conskbd works in TR_ASCII translation mode, if anyone of
   2118  *	CapsLock, NumberLock and Compose keys is pressed, kbtrans need
   2119  *	to set LED. In this case, there is no ioctl from upper module.
   2120  *	There is no requirement to send response to somebody.
   2121  *
   2122  * In first case, kbtrans will send response to upper module; and in the
   2123  * second, we don't need to send response. So conskbd_streams_setled()
   2124  * has no return value.
   2125  */
   2126 static void
   2127 conskbd_streams_setled(struct kbtrans_hardware *hw, int led_state)
   2128 {
   2129 	conskbd_state_t  *conskbdp = (conskbd_state_t *)hw;
   2130 	conskbd_lower_queue_t *lqs;
   2131 	mblk_t		*req;
   2132 
   2133 	ASSERT(&conskbd == conskbdp);
   2134 
   2135 	if (led_state == -1)
   2136 		return;
   2137 
   2138 	conskbdp->conskbd_led_state = led_state;
   2139 
   2140 	/*
   2141 	 * Basically, failing to set LED is not a fatal error, we just skip
   2142 	 * it if this happens.
   2143 	 */
   2144 	for (lqs = conskbdp->conskbd_lqueue_list; lqs; lqs = lqs->lqs_next) {
   2145 		req = mkiocb(KIOCSLED);
   2146 
   2147 		if (!req) {
   2148 			continue;
   2149 		}
   2150 
   2151 		req->b_cont = allocb(sizeof (uchar_t), BPRI_MED);
   2152 		if (!req->b_cont) {
   2153 			freemsg(req);
   2154 			continue;
   2155 		}
   2156 		*(uchar_t *)req->b_cont->b_wptr = led_state;
   2157 		req->b_cont->b_wptr += sizeof (uchar_t);
   2158 		if (putq(lqs->lqs_queue, req) != 1)
   2159 			freemsg(req);
   2160 	}
   2161 
   2162 }	/* conskbd_streams_setled() */
   2163 
   2164 static void
   2165 conskbd_polledio_setled(struct kbtrans_hardware *hw, int led_state)
   2166 {
   2167 	conskbd_state_t  *conskbdp = (conskbd_state_t *)hw;
   2168 	struct cons_polledio		*cb;
   2169 	conskbd_lower_queue_t	*lqs;
   2170 
   2171 	for (lqs = conskbdp->conskbd_lqueue_list; lqs; lqs = lqs->lqs_next) {
   2172 		cb = lqs->lqs_polledio;
   2173 		if ((cb != NULL) && (cb->cons_polledio_setled != NULL)) {
   2174 			cb->cons_polledio_setled(cb->cons_polledio_argument,
   2175 			    led_state);
   2176 		}
   2177 	}
   2178 
   2179 }	/* conskbd_polledio_setled() */
   2180 
   2181 static boolean_t
   2182 conskbd_polled_keycheck(struct kbtrans_hardware *hw,
   2183 		kbtrans_key_t *keycode, enum keystate *state)
   2184 {
   2185 	conskbd_state_t  *conskbdp = (conskbd_state_t *)hw;
   2186 	struct cons_polledio 		*cb;
   2187 	conskbd_lower_queue_t	*lqs;
   2188 	boolean_t	ret = B_FALSE;
   2189 
   2190 	for (ret = B_FALSE, lqs = conskbdp->conskbd_lqueue_list; lqs != NULL;
   2191 	    lqs = lqs->lqs_next) {
   2192 		cb = lqs->lqs_polledio;
   2193 		if ((cb != NULL) &&
   2194 		    (cb->cons_polledio_keycheck != NULL)) {
   2195 			ret = cb->cons_polledio_keycheck(
   2196 			    cb->cons_polledio_argument, keycode, state);
   2197 		}
   2198 
   2199 		/* Get a char from lower queue(hardware) ? */
   2200 		if (ret == B_TRUE) {
   2201 
   2202 			/* A legacy keyboard ? */
   2203 			if (conskbd.conskbd_bypassed == B_TRUE)
   2204 				break;
   2205 
   2206 			/*
   2207 			 * This is the PS2 scancode 0x2B -> USB(49) /
   2208 			 * USB(50) keycode mapping workaround, for
   2209 			 * polled mode.
   2210 			 *
   2211 			 * There are two possible USB keycode mappings
   2212 			 * for PS2 scancode 0x2B and this workaround
   2213 			 * makes sure that we use the USB keycode that
   2214 			 * does not end up being mapped to a HOLE key
   2215 			 * using the current keyboard translation
   2216 			 * tables.
   2217 			 *
   2218 			 * See conskbdlrput() for a detailed
   2219 			 * explanation of the problem.
   2220 			 */
   2221 			if (*keycode == 49 || *keycode == 50) {
   2222 				if (conskbd_keyindex->k_normal[50] == HOLE)
   2223 					*keycode = 49;
   2224 				else
   2225 					*keycode = 50;
   2226 			}
   2227 
   2228 			break;
   2229 		}
   2230 	}
   2231 
   2232 	return (ret);
   2233 
   2234 }	/* conskbd_polled_keycheck() */
   2235 
   2236 static boolean_t
   2237 conskbd_override_kbtrans(queue_t *q, mblk_t *mp)
   2238 {
   2239 	struct iocblk		*iocp;
   2240 	int		directio;
   2241 	int		error;
   2242 
   2243 	if (mp->b_datap->db_type != M_IOCTL)
   2244 		return (B_FALSE);
   2245 
   2246 	iocp = (struct iocblk *)mp->b_rptr;
   2247 
   2248 	switch (iocp->ioc_cmd) {
   2249 	case KIOCGDIRECT: {
   2250 		/*
   2251 		 * Don't let the kbtrans-based code see this; it will
   2252 		 * respond incorrectly.
   2253 		 */
   2254 		register mblk_t *datap;
   2255 
   2256 		if ((datap = allocb((int)sizeof (int), BPRI_MED)) == NULL) {
   2257 			miocnak(q, mp, 0, ENOMEM);
   2258 			return (B_TRUE);
   2259 		}
   2260 
   2261 		*(int *)datap->b_wptr = conskbd.conskbd_directio;
   2262 		datap->b_wptr += sizeof (int);
   2263 		if (mp->b_cont) {
   2264 			freemsg(mp->b_cont);
   2265 			mp->b_cont = NULL;
   2266 		}
   2267 		mp->b_cont = datap;
   2268 		miocack(q, mp, sizeof (int), 0);
   2269 		return (B_TRUE);
   2270 	}
   2271 
   2272 	case KIOCSDIRECT:
   2273 		/*
   2274 		 * Peek at this, set our variables, and then let the kbtrans
   2275 		 * based code see it and respond to it.
   2276 		 */
   2277 		error = miocpullup(mp, sizeof (int));
   2278 		if (error != 0) {
   2279 			return (B_FALSE);
   2280 		}
   2281 
   2282 		directio = *(int *)mp->b_cont->b_rptr;
   2283 		if (directio != 0 && directio != 1) {
   2284 			miocnak(q, mp, 0, EINVAL);
   2285 			return (B_TRUE);
   2286 		}
   2287 		conskbd.conskbd_directio = directio;
   2288 
   2289 		if (conskbd.conskbd_directio) {
   2290 			kbtrans_streams_set_queue(
   2291 			    conskbd.conskbd_kbtrans, conskbd_regqueue);
   2292 		} else {
   2293 			kbtrans_streams_set_queue(
   2294 			    conskbd.conskbd_kbtrans, conskbd_consqueue);
   2295 		}
   2296 
   2297 		/*
   2298 		 * Let the kbtrans-based code see this and respond to it.
   2299 		 */
   2300 		return (B_FALSE);
   2301 
   2302 	default:
   2303 		return (B_FALSE);
   2304 	}
   2305 
   2306 }	/* conskbd_override_kbtrans() */
   2307 
   2308 
   2309 static void
   2310 conskbd_polledio_enter(cons_polledio_arg_t arg)
   2311 {
   2312 	conskbd_state_t		*conskbdp;
   2313 	struct cons_polledio		*cb;
   2314 	conskbd_lower_queue_t	*lqs;
   2315 
   2316 	conskbdp = (conskbd_state_t *)arg;
   2317 	for (lqs = conskbdp->conskbd_lqueue_list; lqs; lqs = lqs->lqs_next) {
   2318 		cb = lqs->lqs_polledio;
   2319 		if ((cb != NULL) && (cb->cons_polledio_enter != NULL)) {
   2320 			cb->cons_polledio_enter(cb->cons_polledio_argument);
   2321 		}
   2322 	}
   2323 
   2324 }	/* conskbd_polledio_enter() */
   2325 
   2326 static void
   2327 conskbd_polledio_exit(cons_polledio_arg_t arg)
   2328 {
   2329 	conskbd_state_t		*conskbdp;
   2330 	struct cons_polledio		*cb;
   2331 	conskbd_lower_queue_t	*lqs;
   2332 
   2333 	conskbdp = (conskbd_state_t *)arg;
   2334 	for (lqs = conskbdp->conskbd_lqueue_list; lqs; lqs = lqs->lqs_next) {
   2335 		cb = lqs->lqs_polledio;
   2336 		if ((cb != NULL) && (cb->cons_polledio_exit != NULL)) {
   2337 			cb->cons_polledio_exit(cb->cons_polledio_argument);
   2338 		}
   2339 	}
   2340 
   2341 }	/* conskbd_polledio_exit() */
   2342 
   2343 static int
   2344 conskbd_polledio_getchar(cons_polledio_arg_t arg)
   2345 {
   2346 	conskbd_state_t  *conskbdp;
   2347 
   2348 	conskbdp = (conskbd_state_t *)arg;
   2349 
   2350 	return (kbtrans_getchar(conskbdp->conskbd_kbtrans));
   2351 
   2352 }	/* conskbd_polledio_getchar() */
   2353 
   2354 static int
   2355 conskbd_polledio_ischar(cons_polledio_arg_t arg)
   2356 {
   2357 	conskbd_state_t  *conskbdp;
   2358 
   2359 	conskbdp = (conskbd_state_t *)arg;
   2360 
   2361 	return (kbtrans_ischar(conskbdp->conskbd_kbtrans));
   2362 
   2363 }	/* conskbd_polledio_ischar() */
   2364 
   2365 
   2366 static void
   2367 conskbd_mux_enqueue_msg(conskbd_pending_msg_t *msg)
   2368 {
   2369 	mutex_enter(&conskbd_msgq_lock);
   2370 	msg->kpm_next = conskbd_msg_queue;
   2371 	conskbd_msg_queue = msg;
   2372 	mutex_exit(&conskbd_msgq_lock);
   2373 
   2374 }	/* conskbd_mux_enqueue_msg() */
   2375 
   2376 /*
   2377  * the messages in conskbd_msg_queue we just enqueue
   2378  */
   2379 static conskbd_pending_msg_t *
   2380 conskbd_mux_find_msg(mblk_t *mp)
   2381 {
   2382 	conskbd_pending_msg_t	*msg;
   2383 	struct iocblk		*iocp;
   2384 	uint_t	id;
   2385 
   2386 	mutex_enter(&conskbd_msgq_lock);
   2387 	msg = conskbd_msg_queue;
   2388 
   2389 	iocp = (struct iocblk *)mp->b_rptr;
   2390 	ASSERT(iocp);
   2391 	id = iocp->ioc_id;
   2392 	while (msg && msg->kpm_req_id != id) {
   2393 		msg = msg->kpm_next;
   2394 	}
   2395 	mutex_exit(&conskbd_msgq_lock);
   2396 
   2397 	return (msg);
   2398 
   2399 }	/* conskbd_mux_find_msg() */
   2400 
   2401 
   2402 static void
   2403 conskbd_mux_dequeue_msg(conskbd_pending_msg_t *msg)
   2404 {
   2405 	conskbd_pending_msg_t *prev;
   2406 	conskbd_pending_msg_t *p;
   2407 
   2408 	mutex_enter(&conskbd_msgq_lock);
   2409 	prev = conskbd_msg_queue;
   2410 
   2411 	for (p = prev; p && p != msg; p = p->kpm_next)
   2412 		prev = p;
   2413 
   2414 	ASSERT(p && p == msg);
   2415 
   2416 	if (prev == p) {
   2417 		conskbd_msg_queue = msg->kpm_next;
   2418 	} else {
   2419 		prev->kpm_next = p->kpm_next;
   2420 	}
   2421 	p->kpm_next = NULL;
   2422 	mutex_exit(&conskbd_msgq_lock);
   2423 
   2424 }	/* conskbd_mux_dequeue_msg() */
   2425 
   2426 #ifdef DEBUG
   2427 /*ARGSUSED*/
   2428 void
   2429 conskbd_dprintf(const char *fmt, ...)
   2430 {
   2431 	char buf[256];
   2432 	va_list ap;
   2433 
   2434 	va_start(ap, fmt);
   2435 	(void) vsprintf(buf, fmt, ap);
   2436 	va_end(ap);
   2437 
   2438 	cmn_err(CE_CONT, "conskbd: %s", buf);
   2439 
   2440 }	/* conskbd_dprintf() */
   2441 #endif
   2442