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