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