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 2008 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 	/*
    567 	 * initialize kbtrans module for conskbd
    568 	 */
    569 	err = kbtrans_streams_init(q, sflag, crp, (struct kbtrans_hardware *)
    570 	    &conskbd, &conskbd_callbacks, &conskbd.conskbd_kbtrans, 0, 0);
    571 	if (err != 0)
    572 		return (err);
    573 	kbtrans_streams_set_keyboard(conskbd.conskbd_kbtrans, KB_USB,
    574 	    conskbd_keyindex);
    575 
    576 	conskbd.conskbd_polledio.cons_polledio_version = CONSPOLLEDIO_V1;
    577 	conskbd.conskbd_polledio.cons_polledio_argument =
    578 	    (cons_polledio_arg_t)&conskbd;
    579 	conskbd.conskbd_polledio.cons_polledio_putchar = NULL;
    580 	conskbd.conskbd_polledio.cons_polledio_getchar =
    581 	    (int (*)(cons_polledio_arg_t)) conskbd_polledio_getchar;
    582 	conskbd.conskbd_polledio.cons_polledio_ischar =
    583 	    (boolean_t (*)(cons_polledio_arg_t))conskbd_polledio_ischar;
    584 	conskbd.conskbd_polledio.cons_polledio_enter = conskbd_polledio_enter;
    585 	conskbd.conskbd_polledio.cons_polledio_exit = conskbd_polledio_exit;
    586 	qprocson(q);
    587 
    588 	return (0);
    589 
    590 }	/* conskbdopen() */
    591 
    592 
    593 /*ARGSUSED*/
    594 static int
    595 conskbdclose(queue_t *q, int flag, cred_t *crp)
    596 {
    597 	if (q == conskbd_regqueue) {
    598 
    599 		conskbd_pending_msg_t	*pmsg, *prev, *next;
    600 		mblk_t		*mp;
    601 
    602 		/* switch the input stream back to conskbd_consqueue */
    603 		conskbd.conskbd_directio = B_FALSE;
    604 
    605 		kbtrans_streams_untimeout(conskbd.conskbd_kbtrans);
    606 		kbtrans_streams_set_queue(conskbd.conskbd_kbtrans,
    607 		    conskbd_consqueue);
    608 		qprocsoff(q);
    609 		conskbd_regqueue = NULL;
    610 
    611 		/*
    612 		 * If there are any pending ioctls which conskbd hasn't
    613 		 * responded to yet, remove them from conskbd_msg_queue.
    614 		 * Otherwise, we might send the response to a nonexistent
    615 		 * closed queue. Refer to: conskbd_mux_upstream_msg().
    616 		 */
    617 		for (prev = NULL, pmsg = conskbd_msg_queue; pmsg != NULL;
    618 		    pmsg = next) {
    619 			next = pmsg->kpm_next;
    620 			if (pmsg->kpm_upper_queue == WR(q)) {
    621 				if (prev == NULL)
    622 					conskbd_msg_queue = next;
    623 				else
    624 					prev->kpm_next = next;
    625 
    626 				while (pmsg->kpm_resp_list != NULL) {
    627 					mp = pmsg->kpm_resp_list;
    628 					pmsg->kpm_resp_list = mp->b_next;
    629 					mp->b_next = mp->b_prev = NULL;
    630 					freemsg(mp);
    631 				}
    632 				mutex_destroy(&pmsg->kpm_lock);
    633 				kmem_free(pmsg, sizeof (*pmsg));
    634 			} else {
    635 				prev = pmsg;
    636 			}
    637 		}
    638 	} else if (q == conskbd_consqueue) {
    639 		/*
    640 		 * Well, this is probably a mistake, but we will permit you
    641 		 * to close the path to the console if you really insist.
    642 		 */
    643 		qprocsoff(q);
    644 		conskbd_consqueue = NULL;
    645 	}
    646 
    647 	return (0);
    648 
    649 }	/* conskbdclose() */
    650 
    651 /*
    652  * Service procedure for upper write queue.
    653  *	To make sure the order of messages, we don't process any
    654  * message in qi_putq() routine of upper write queue, instead the
    655  * qi_putq() routine, which is a standard putq() routine, puts all
    656  * messages into a queue, and lets the following service procedure
    657  * deal with all messages.
    658  * 	This routine is invoked when ioctl commands are send down
    659  * by a consumer of the keyboard device, eg, when the keyboard
    660  * consumer tries to determine the keyboard layout type, or sets
    661  * the led states.
    662  */
    663 static void
    664 conskbduwsrv(queue_t *q)
    665 {
    666 	mblk_t	*mp;
    667 	queue_t	*oldq;
    668 	enum kbtrans_message_response ret;
    669 	struct copyresp *csp;
    670 	struct freq_request *frqp;
    671 	int error;
    672 
    673 	while ((mp = getq(q)) != NULL) {
    674 
    675 		/*
    676 		 * if the virtual keyboard is supported
    677 		 */
    678 		if (conskbd.conskbd_bypassed == B_FALSE) {
    679 
    680 			if (conskbd_override_kbtrans(q, mp) == B_TRUE)
    681 				continue;
    682 			/*
    683 			 * The conskbd driver is a psaudo driver. It has two
    684 			 * devcice nodes, one is used by kernel, and the other
    685 			 * is used by end-users. There are two STREAMS queues
    686 			 * corresponding to the two device nodes, console queue
    687 			 * and regular queue.
    688 			 * In conskbd_override_kbtrans() routine, when receives
    689 			 * KIOCSDIRECT ioctl, we need change the direction of
    690 			 * keyboard input messages, and direct the input stream
    691 			 * from keyboard into right queue. It causes this queue
    692 			 * to be switched between regular queue and console
    693 			 * queue. And here, in this routine, the in-parameter
    694 			 * "q" can be any one of the two. Moreover, this module
    695 			 * is executed in multithreaded environment, even if the
    696 			 * q is switched to regular queue, it is possible that
    697 			 * the in-parameter is still the console queue, and we
    698 			 * need to return response to right queue.
    699 			 * The response is sent to upstream by the kbtrans
    700 			 * module. so we need to save the old queue, and wait
    701 			 * kbtrans to proces message and to send response out,
    702 			 * and then switch back to old queue.
    703 			 */
    704 			oldq = kbtrans_streams_get_queue(
    705 			    conskbd.conskbd_kbtrans);
    706 			kbtrans_streams_set_queue(
    707 			    conskbd.conskbd_kbtrans, RD(q));
    708 			ret = kbtrans_streams_message(
    709 			    conskbd.conskbd_kbtrans, mp);
    710 			kbtrans_streams_set_queue(
    711 			    conskbd.conskbd_kbtrans, oldq);
    712 
    713 			switch (ret) {
    714 				case KBTRANS_MESSAGE_HANDLED:
    715 					continue;
    716 				case KBTRANS_MESSAGE_NOT_HANDLED:
    717 					break;
    718 			}
    719 		}
    720 
    721 		switch (mp->b_datap->db_type) {
    722 
    723 		case M_IOCTL:
    724 			conskbd_ioctl(q, mp);
    725 			break;
    726 
    727 		case M_FLUSH:
    728 			if (*mp->b_rptr & FLUSHW) {
    729 				flushq(q, FLUSHDATA);
    730 			}
    731 			/*
    732 			 * here, if flush read queue, some key-up messages
    733 			 * may be lost so that upper module or applications
    734 			 * treat corresponding keys as being held down for
    735 			 * ever.
    736 			 */
    737 			freemsg(mp);
    738 			break;
    739 
    740 		case M_DATA:
    741 			/*
    742 			 * virtual keyboard doesn't support this interface.
    743 			 * only when it is disabled, we pass the message
    744 			 * down to lower queue.
    745 			 */
    746 			if ((conskbd.conskbd_bypassed) &&
    747 			    (conskbd.conskbd_lqueue_nums > 0)) {
    748 				if (putq(conskbd.conskbd_lqueue_list->
    749 				    lqs_queue, mp) != 1)
    750 					freemsg(mp);
    751 			} else {
    752 				freemsg(mp);
    753 			}
    754 			break;
    755 
    756 		case M_IOCDATA:
    757 			/*
    758 			 * Only deal with copyresp to KIOCSETFREQ
    759 			 * transparent ioctl now
    760 			 */
    761 			csp = (struct copyresp *)mp->b_rptr;
    762 			if (csp->cp_rval) {
    763 				miocnak(q, mp, 0, EINVAL);
    764 				break;
    765 			}
    766 
    767 			error = 0;
    768 			switch (csp->cp_cmd) {
    769 			case KIOCSETFREQ:
    770 				frqp = (struct freq_request *)mp->
    771 				    b_cont->b_rptr;
    772 
    773 				switch (frqp->type) {
    774 				case CONSOLE_BEEP:
    775 					error = beeper_freq(BEEP_CONSOLE,
    776 					    (int)frqp->freq);
    777 						break;
    778 
    779 				case KBD_BEEP:
    780 					error = beeper_freq(BEEP_TYPE4,
    781 					    (int)frqp->freq);
    782 						break;
    783 
    784 				default:
    785 					error = 1;
    786 				} /* frqp->type */
    787 
    788 				break;
    789 
    790 			default:
    791 				error = 1;
    792 			} /* csp->cp_cmd */
    793 
    794 			if (error == 0)
    795 				miocack(q, mp, 0, 0);
    796 			else
    797 				miocnak(q, mp, 0, EINVAL);
    798 
    799 			break;
    800 
    801 		default:
    802 			/*
    803 			 * Pass an error message up.
    804 			 */
    805 			mp->b_datap->db_type = M_ERROR;
    806 			if (mp->b_cont) {
    807 				freemsg(mp->b_cont);
    808 				mp->b_cont = NULL;
    809 			}
    810 			mp->b_rptr = mp->b_datap->db_base;
    811 			mp->b_wptr = mp->b_rptr + sizeof (char);
    812 			*mp->b_rptr = EINVAL;
    813 			qreply(q, mp);
    814 		}
    815 	}	/* end of while */
    816 
    817 }	/* conskbduwsrv() */
    818 
    819 static void
    820 conskbd_ioctl(queue_t *q, mblk_t *mp)
    821 {
    822 	struct	iocblk			*iocp;
    823 	int	error = 0;
    824 
    825 	iocp = (struct iocblk *)mp->b_rptr;
    826 
    827 	switch (iocp->ioc_cmd) {
    828 
    829 	case I_LINK:
    830 	case I_PLINK:
    831 		if (conskbd.conskbd_bypassed == B_TRUE) {
    832 		/*
    833 		 * A legacy keyboard can NOT be connected to conskbd together
    834 		 * with other keyboards. So when a legacy keyboard is already
    835 		 * linked under conkbd, we just reject all others.
    836 		 */
    837 			miocnak(q, mp, 0, EAGAIN);
    838 			break;
    839 		}
    840 		qwriter(q, mp, conskbd_ioc_plink, PERIM_OUTER);
    841 		break;
    842 
    843 	case I_UNLINK:
    844 	case I_PUNLINK:
    845 		qwriter(q, mp, conskbd_ioc_punlink, PERIM_OUTER);
    846 		break;
    847 
    848 	case KIOCSKABORTEN:
    849 		/*
    850 		 * Check if privileged
    851 		 */
    852 		if ((error = secpolicy_sys_config(iocp->ioc_cr, B_FALSE))) {
    853 			miocnak(q, mp, 0, error);
    854 			return;
    855 		}
    856 
    857 		error = miocpullup(mp, sizeof (int));
    858 		if (error != 0) {
    859 			miocnak(q, mp, 0, error);
    860 			return;
    861 		}
    862 
    863 		abort_enable = *(int *)mp->b_cont->b_rptr;
    864 		miocack(q, mp, 0, 0);
    865 		break;
    866 
    867 	case KIOCSETFREQ:
    868 		if (iocp->ioc_count != TRANSPARENT) {
    869 			/*
    870 			 * We don't support non-transparent ioctls,
    871 			 * i.e. I_STR ioctls
    872 			 */
    873 			miocnak(q, mp, 0, EINVAL);
    874 		} else {
    875 			/* Transparent ioctl */
    876 			mcopyin(mp, NULL, sizeof (struct freq_request), NULL);
    877 			qreply(q, mp);
    878 		}
    879 		break;
    880 
    881 	default:
    882 		if (conskbd.conskbd_bypassed == B_TRUE) {
    883 			conskbd_legacy_kbd_ioctl(q, mp);
    884 		} else {
    885 			conskbd_virtual_kbd_ioctl(q, mp);
    886 		}
    887 	}
    888 
    889 }	/* conskbd_ioctl() */
    890 
    891 
    892 static void
    893 conskbd_virtual_kbd_ioctl(queue_t *q, mblk_t *mp)
    894 {
    895 	struct iocblk		*iocp;
    896 	mblk_t			*datap;
    897 	int			cmd;
    898 	int			error = 0;
    899 
    900 	iocp = (struct iocblk *)mp->b_rptr;
    901 
    902 	switch (iocp->ioc_cmd) {
    903 	case KIOCLAYOUT:
    904 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
    905 			miocnak(q, mp, 0, ENOMEM);
    906 			break;
    907 		}
    908 
    909 		if (conskbd.conskbd_layout == -1)
    910 			*(int *)datap->b_wptr = KBTRANS_USBKB_DEFAULT_LAYOUT;
    911 		else
    912 			*(int *)datap->b_wptr = conskbd.conskbd_layout;
    913 
    914 		datap->b_wptr += sizeof (int);
    915 		if (mp->b_cont)
    916 			freemsg(mp->b_cont);
    917 		mp->b_cont = datap;
    918 		miocack(q, mp, sizeof (int), 0);
    919 		break;
    920 
    921 	case KIOCSLAYOUT:
    922 		if (iocp->ioc_count != TRANSPARENT) {
    923 			miocnak(q, mp, 0, EINVAL);
    924 			break;
    925 		}
    926 		kbd_layout_bak = conskbd.conskbd_layout;
    927 		conskbd.conskbd_layout = *(intptr_t *)(mp->b_cont->b_rptr);
    928 		if (conskbd.conskbd_layout != kbd_layout_bak) {
    929 
    930 			/* notify the upper of the change event */
    931 			if ((datap = conskbd_alloc_firm_event(
    932 			    KEYBOARD_LAYOUT_CHANGE,
    933 			    conskbd.conskbd_layout)) != NULL) {
    934 				if (conskbd.conskbd_directio) {
    935 					putnext(conskbd_regqueue, datap);
    936 				} else {
    937 					freemsg(datap);
    938 				}
    939 			}
    940 		}
    941 		miocack(q, mp, 0, 0);
    942 		break;
    943 
    944 	case CONSOPENPOLLEDIO:
    945 		error = miocpullup(mp, sizeof (struct cons_polledio *));
    946 		if (error != 0) {
    947 			miocnak(q, mp, 0, error);
    948 			break;
    949 		}
    950 		if (conskbd.conskbd_lqueue_list == NULL) {
    951 			miocnak(q, mp, 0, EINVAL);
    952 			break;
    953 		}
    954 		conskbd_handle_downstream_msg(q, mp);
    955 		break;
    956 
    957 	case CONSCLOSEPOLLEDIO:
    958 		if (conskbd.conskbd_lqueue_list == NULL) {
    959 			miocnak(q, mp, 0, EINVAL);
    960 			break;
    961 		}
    962 		conskbd_handle_downstream_msg(q, mp);
    963 		break;
    964 
    965 	case CONSSETABORTENABLE:
    966 		/*
    967 		 * To enable combined STOP-A(or F1-A) to trap into kmdb,
    968 		 * the lower physical keyboard drivers are always told not
    969 		 * to parse abort sequence(refer to consconfig_dacf module).
    970 		 * Instead, lower drivers always send all keydown & keyup
    971 		 * messages up to conskbd, so that when key STOP(or F1) is
    972 		 * pressed on one keyboard and key A is pressed on another
    973 		 * keyboard, the system could trap into kmdb.
    974 		 *
    975 		 * When we by kbtrans_streams_message() invoked kbtrans to
    976 		 * handle ioctls in conskbduwsrv() routine, kbtrans module
    977 		 * already handle the message though it returned to us a
    978 		 * KBTRANS_MESSAGE_NOT_HANDLED. For virtual keyboard, no
    979 		 * special initialization or un-initialization is needed.
    980 		 * So we just return ACK to upper module.
    981 		 */
    982 		miocack(q, mp, 0, 0);
    983 		break;
    984 
    985 	case KIOCCMD:
    986 	case KIOCMKTONE:
    987 		if (conskbd.conskbd_lqueue_list == NULL ||
    988 		    mp->b_cont == NULL) {
    989 			miocnak(q, mp, 0, EINVAL);
    990 			break;
    991 		}
    992 		cmd = *(int *)mp->b_cont->b_rptr;
    993 		if (cmd == KBD_CMD_GETLAYOUT) {
    994 			freemsg(mp->b_cont);
    995 			datap = allocb(sizeof (int), BPRI_HI);
    996 			if (datap == NULL) {
    997 				miocnak(q, mp, 0, ENOMEM);
    998 				return;
    999 			}
   1000 			if (conskbd.conskbd_layout == -1)
   1001 				*(int *)datap->b_wptr =
   1002 				    KBTRANS_USBKB_DEFAULT_LAYOUT;
   1003 			else
   1004 				*(int *)datap->b_wptr = conskbd.conskbd_layout;
   1005 
   1006 			mp->b_cont = datap;
   1007 			miocack(q, mp, sizeof (int), 0);
   1008 			return;
   1009 		}
   1010 		conskbd_handle_downstream_msg(q, mp);
   1011 		break;
   1012 
   1013 	default:
   1014 		miocnak(q, mp, 0, EINVAL);
   1015 		break;
   1016 	}
   1017 
   1018 }	/* conskbd_virtual_kbd_ioctl() */
   1019 
   1020 static void
   1021 conskbd_legacy_kbd_ioctl(queue_t *q, mblk_t *mp)
   1022 {
   1023 	conskbd_lower_queue_t	*lq;
   1024 	struct	iocblk		*iocp;
   1025 	int	error = 0;
   1026 
   1027 	iocp = (struct iocblk *)mp->b_rptr;
   1028 
   1029 	ASSERT(conskbd.conskbd_lqueue_nums == 1);
   1030 	switch (iocp->ioc_cmd) {
   1031 
   1032 	case KIOCGDIRECT: {
   1033 		mblk_t *datap;
   1034 
   1035 		if ((datap = allocb(sizeof (int), BPRI_MED)) == NULL) {
   1036 			miocnak(q, mp, 0, ENOMEM);
   1037 			break;
   1038 		}
   1039 
   1040 		*(int *)datap->b_wptr = conskbd.conskbd_directio;
   1041 		datap->b_wptr += sizeof (int);
   1042 		if (mp->b_cont != NULL) {
   1043 			freemsg(mp->b_cont);
   1044 			mp->b_cont = NULL;
   1045 		}
   1046 		mp->b_cont = datap;
   1047 		miocack(q, mp, sizeof (int), 0);
   1048 		break;
   1049 	}
   1050 
   1051 	case KIOCSDIRECT:
   1052 		error = miocpullup(mp, sizeof (int));
   1053 		if (error != 0) {
   1054 			miocnak(q, mp, 0, error);
   1055 			break;
   1056 		}
   1057 		conskbd.conskbd_directio = *(int *)mp->b_cont->b_rptr;
   1058 
   1059 		/*
   1060 		 * Pass this through, if there's something to pass
   1061 		 * it through to, so the system keyboard can reset
   1062 		 * itself.
   1063 		 */
   1064 		if (conskbd.conskbd_lqueue_nums > 0) {
   1065 			lq = conskbd.conskbd_lqueue_list;
   1066 			ASSERT(lq && lq->lqs_next == NULL);
   1067 			if (putq(lq->lqs_queue, mp) != 1) {
   1068 				miocnak(q, mp, 0, ENOMEM);
   1069 				return;
   1070 			}
   1071 			break;
   1072 		}
   1073 
   1074 		miocack(q, mp, 0, 0);
   1075 		break;
   1076 
   1077 	default:
   1078 		/*
   1079 		 * Pass this through, if there's something to pass it
   1080 		 * through to; otherwise, reject it.
   1081 		 */
   1082 		if (conskbd.conskbd_lqueue_nums > 0) {
   1083 			lq = conskbd.conskbd_lqueue_list;
   1084 			ASSERT(lq && lq->lqs_next == NULL);
   1085 			if (putq(lq->lqs_queue, mp) != 1) {
   1086 				miocnak(q, mp, 0, ENOMEM);
   1087 				return;
   1088 			}
   1089 			break;
   1090 		}
   1091 
   1092 		/* nobody below us; reject it */
   1093 		miocnak(q, mp, 0, EINVAL);
   1094 		break;
   1095 	}
   1096 
   1097 }	/* conskbd_legacy_kbd_ioctl() */
   1098 
   1099 
   1100 /*
   1101  * Service procedure for lower write queue.
   1102  * Puts things on the queue below us, if it lets us.
   1103  */
   1104 static void
   1105 conskbdlwserv(queue_t *q)
   1106 {
   1107 	register mblk_t *mp;
   1108 
   1109 	while (canput(q->q_next) && (mp = getq(q)) != NULL)
   1110 		putnext(q, mp);
   1111 
   1112 }	/* conskbdlwserv() */
   1113 
   1114 /*
   1115  * Put procedure for lower read queue.
   1116  * Pass everything up to minor device 0 if "directio" set, otherwise to minor
   1117  * device 1.
   1118  */
   1119 static void
   1120 conskbdlrput(queue_t *q, mblk_t *mp)
   1121 {
   1122 	conskbd_lower_queue_t	*lqs;
   1123 	struct iocblk 	*iocp;
   1124 	Firm_event	*fe;
   1125 
   1126 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, ("conskbdlrput\n"));
   1127 
   1128 	switch (mp->b_datap->db_type) {
   1129 
   1130 	case M_FLUSH:
   1131 		if (*mp->b_rptr == FLUSHR) {
   1132 			flushq(q, FLUSHDATA);	/* XXX doesn't flush M_DELAY */
   1133 			*mp->b_rptr &= ~FLUSHR;	/* it has been flushed */
   1134 		}
   1135 		if (*mp->b_rptr == FLUSHW) {
   1136 			flushq(WR(q), FLUSHDATA);
   1137 			qreply(q, mp);	/* give the read queues a crack at it */
   1138 		} else
   1139 			freemsg(mp);
   1140 		break;
   1141 
   1142 	case M_DATA:
   1143 		if (conskbd.conskbd_bypassed == B_FALSE) {
   1144 
   1145 			fe = (Firm_event *)mp->b_rptr;
   1146 
   1147 			/*
   1148 			 * This is a workaround.
   1149 			 *
   1150 			 * According to HID specification, there are the
   1151 			 * following keycode mapping between PS2 and USB,
   1152 			 *
   1153 			 *	PS2 AT-101 keycode(29)  --->    USB(49)
   1154 			 *	PS2 AT-102 keycode(42)  --->    USB(50)
   1155 			 *
   1156 			 * However, the two keys, AT-101(29) and AT-102(42),
   1157 			 * have the same scancode,0x2B, in PS2 scancode SET1
   1158 			 * which we are using. The Kb8042 driver always
   1159 			 * recognizes the two keys as PS2(29) so that we could
   1160 			 * not know which is being pressed or released when we
   1161 			 * receive scancode 0x2B. Fortunately, the two keys can
   1162 			 * not co-exist in a specific layout. In other words,
   1163 			 * in the table of keycode-to-symbol mapping, either
   1164 			 * entry 49 or 50 is a hole. So, if we're processing a
   1165 			 * keycode 49, we look at the entry for 49.  If it's
   1166 			 * HOLE, remap the key to 50; If we're processing a 50,
   1167 			 * look at the entry for 50.  If it's HOLE, we remap
   1168 			 * the key to 49.
   1169 			 */
   1170 			if (fe->id == 49 || fe->id == 50) {
   1171 				if (conskbd_keyindex->k_normal[50] == HOLE)
   1172 					fe->id = 49;
   1173 				else
   1174 					fe->id = 50;
   1175 			}
   1176 
   1177 			/*
   1178 			 * Remember key state of each key of lower physical
   1179 			 * keyboard. When a keyboard is umplumbed from conskbd,
   1180 			 * we will check all key states. By then,  we will fake
   1181 			 * a KEY_RELEASED message for each key in KEY_PRESSED
   1182 			 * state. Otherwise, upper module will treat these keys
   1183 			 * as held-down for ever.
   1184 			 */
   1185 			iocp = (struct iocblk *)mp->b_rptr;
   1186 			lqs = (conskbd_lower_queue_t *)q->q_ptr;
   1187 			if (fe->value)
   1188 				lqs->lqs_key_state[fe->id] = KEY_PRESSED;
   1189 			else
   1190 				lqs->lqs_key_state[fe->id] = KEY_RELEASED;
   1191 
   1192 			kbtrans_streams_key(conskbd.conskbd_kbtrans,
   1193 			    fe->id, fe->value ? KEY_PRESSED : KEY_RELEASED);
   1194