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 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  22 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T       */
  23 /*        All Rights Reserved   */
  24 
  25 /*
  26  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 
  31 /*
  32  * PS/2 type Mouse Module - Streams
  33  */
  34 
  35 #include <sys/param.h>
  36 #include <sys/types.h>
  37 #include <sys/kmem.h>
  38 #include <sys/signal.h>
  39 #include <sys/errno.h>
  40 #include <sys/file.h>
  41 #include <sys/termio.h>
  42 #include <sys/stream.h>
  43 #include <sys/stropts.h>
  44 #include <sys/strtty.h>
  45 #include <sys/strsun.h>
  46 #include <sys/debug.h>
  47 #include <sys/ddi.h>
  48 #include <sys/stat.h>
  49 #include <sys/cmn_err.h>
  50 #include <sys/sunddi.h>
  51 
  52 #include <sys/promif.h>
  53 #include <sys/cred.h>
  54 
  55 #include <sys/i8042.h>
  56 #include <sys/note.h>
  57 #include <sys/mouse.h>
  58 
  59 #define DRIVER_NAME(dip)        ddi_driver_name(dip)
  60 
  61 #define MOUSE8042_INTERNAL_OPEN(minor)  (((minor) & 0x1) == 1)
  62 #define MOUSE8042_MINOR_TO_INSTANCE(minor)      ((minor) / 2)
  63 #define MOUSE8042_INTERNAL_MINOR(minor)         ((minor) + 1)
  64 
  65 #define MOUSE8042_RESET_TIMEOUT_USECS   500000  /* 500 ms */
  66 
  67 extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
  68 extern void consconfig_link(major_t major, minor_t minor);
  69 extern int consconfig_unlink(major_t major, minor_t minor);
  70 
  71 
  72 /*
  73  *
  74  * Local Static Data
  75  *
  76  */
  77 
  78 /*
  79  * We only support one instance.  Yes, it's theoretically possible to
  80  * plug in more than one, but it's not worth the implementation cost.
  81  *
  82  * The introduction of USB keyboards might make it worth reassessing
  83  * this decision, as they might free up the keyboard port for a second
  84  * PS/2 style mouse.
  85  */
  86 static dev_info_t *mouse8042_dip;
  87 
  88 /*
  89  * RESET states
  90  */
  91 typedef enum {
  92         MSE_RESET_IDLE, /* No reset in progress */
  93         MSE_RESET_PRE,  /* Send reset, waiting for ACK */
  94         MSE_RESET_ACK,  /* Got ACK, waiting for 0xAA */
  95         MSE_RESET_AA,   /* Got 0xAA, waiting for 0x00 */
  96         MSE_RESET_FAILED
  97 } mouse8042_reset_state_e;
  98 
  99 struct mouse_state {
 100         queue_t *ms_rqp;
 101         queue_t *ms_wqp;
 102         ddi_iblock_cookie_t     ms_iblock_cookie;
 103         ddi_acc_handle_t        ms_handle;
 104         uint8_t                 *ms_addr;
 105         kmutex_t                ms_mutex;
 106 
 107         minor_t                 ms_minor;
 108         boolean_t               ms_opened;
 109         kmutex_t                reset_mutex;
 110         kcondvar_t              reset_cv;
 111         mouse8042_reset_state_e reset_state;
 112         timeout_id_t            reset_tid;
 113         int                     ready;
 114         mblk_t                  *reply_mp;
 115         mblk_t                  *reset_ack_mp;
 116         bufcall_id_t            bc_id;
 117 };
 118 
 119 static uint_t mouse8042_intr(caddr_t arg);
 120 static int mouse8042_open(queue_t *q, dev_t *devp, int flag, int sflag,
 121                 cred_t *cred_p);
 122 static int mouse8042_close(queue_t *q, int flag, cred_t *cred_p);
 123 static int mouse8042_wsrv(queue_t *qp);
 124 static int mouse8042_wput(queue_t *q, mblk_t *mp);
 125 
 126 static int mouse8042_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
 127                 void *arg, void **result);
 128 static int mouse8042_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
 129 static int mouse8042_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
 130 
 131 
 132 /*
 133  * Streams module info.
 134  */
 135 #define MODULE_NAME     "mouse8042"
 136 
 137 static struct module_info       mouse8042_minfo = {
 138         23,             /* Module ID number */
 139         MODULE_NAME,
 140         0, INFPSZ,      /* minimum & maximum packet sizes */
 141         256, 128        /* hi and low water marks */
 142 };
 143 
 144 static struct qinit mouse8042_rinit = {
 145         NULL,           /* put */
 146         NULL,           /* service */
 147         mouse8042_open,
 148         mouse8042_close,
 149         NULL,           /* admin */
 150         &mouse8042_minfo,
 151         NULL            /* statistics */
 152 };
 153 
 154 static struct qinit mouse8042_winit = {
 155         mouse8042_wput, /* put */
 156         mouse8042_wsrv, /* service */
 157         NULL,           /* open */
 158         NULL,           /* close */
 159         NULL,           /* admin */
 160         &mouse8042_minfo,
 161         NULL            /* statistics */
 162 };
 163 
 164 static struct streamtab mouse8042_strinfo = {
 165         &mouse8042_rinit,
 166         &mouse8042_winit,
 167         NULL,           /* muxrinit */
 168         NULL,           /* muxwinit */
 169 };
 170 
 171 /*
 172  * Local Function Declarations
 173  */
 174 
 175 static struct cb_ops    mouse8042_cb_ops = {
 176         nodev,                  /* open */
 177         nodev,                  /* close */
 178         nodev,                  /* strategy */
 179         nodev,                  /* print */
 180         nodev,                  /* dump */
 181         nodev,                  /* read */
 182         nodev,                  /* write */
 183         nodev,                  /* ioctl */
 184         nodev,                  /* devmap */
 185         nodev,                  /* mmap */
 186         nodev,                  /* segmap */
 187         nochpoll,               /* poll */
 188         ddi_prop_op,            /* cb_prop_op */
 189         &mouse8042_strinfo, /* streamtab  */
 190         D_MP | D_NEW
 191 };
 192 
 193 
 194 static struct dev_ops   mouse8042_ops = {
 195         DEVO_REV,               /* devo_rev, */
 196         0,                      /* refcnt  */
 197         mouse8042_getinfo,      /* getinfo */
 198         nulldev,                /* identify */
 199         nulldev,                /* probe */
 200         mouse8042_attach,       /* attach */
 201         mouse8042_detach,       /* detach */
 202         nodev,                  /* reset */
 203         &mouse8042_cb_ops,  /* driver operations */
 204         (struct bus_ops *)0,    /* bus operations */
 205         NULL,                   /* power */
 206         ddi_quiesce_not_needed,         /* quiesce */
 207 };
 208 
 209 /*
 210  * This is the loadable module wrapper.
 211  */
 212 #include <sys/modctl.h>
 213 
 214 extern struct mod_ops mod_driverops;
 215 
 216 /*
 217  * Module linkage information for the kernel.
 218  */
 219 
 220 static struct modldrv modldrv = {
 221         &mod_driverops, /* Type of module.  This one is a driver */
 222         "PS/2 Mouse",
 223         &mouse8042_ops,     /* driver ops */
 224 };
 225 
 226 static struct modlinkage modlinkage = {
 227         MODREV_1,
 228         (void *)&modldrv,
 229         NULL
 230 };
 231 
 232 /*
 233  * This is the driver initialization routine.
 234  */
 235 int
 236 _init()
 237 {
 238         int     rv;
 239 
 240         rv = mod_install(&modlinkage);
 241         return (rv);
 242 }
 243 
 244 
 245 int
 246 _fini(void)
 247 {
 248         return (mod_remove(&modlinkage));
 249 }
 250 
 251 
 252 int
 253 _info(struct modinfo *modinfop)
 254 {
 255         return (mod_info(&modlinkage, modinfop));
 256 }
 257 
 258 static int
 259 mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 260 {
 261         struct mouse_state *state;
 262         mblk_t *mp;
 263         int instance = ddi_get_instance(dip);
 264         static ddi_device_acc_attr_t attr = {
 265                 DDI_DEVICE_ATTR_V0,
 266                 DDI_NEVERSWAP_ACC,
 267                 DDI_STRICTORDER_ACC,
 268         };
 269         int rc;
 270 
 271 
 272         if (cmd == DDI_RESUME) {
 273                 state = (struct mouse_state *)ddi_get_driver_private(dip);
 274 
 275                 /* Ready to handle inbound data from mouse8042_intr */
 276                 state->ready = 1;
 277 
 278                 /*
 279                  * Send a 0xaa 0x00 upstream.
 280                  * This causes the vuid module to reset the mouse.
 281                  */
 282                 if (state->ms_rqp != NULL) {
 283                         if (mp = allocb(1, BPRI_MED)) {
 284                                 *mp->b_wptr++ = 0xaa;
 285                                 putnext(state->ms_rqp, mp);
 286                         }
 287                         if (mp = allocb(1, BPRI_MED)) {
 288                                 *mp->b_wptr++ = 0x0;
 289                                 putnext(state->ms_rqp, mp);
 290                         }
 291                 }
 292                 return (DDI_SUCCESS);
 293         }
 294 
 295         if (cmd != DDI_ATTACH)
 296                 return (DDI_FAILURE);
 297 
 298         if (mouse8042_dip != NULL)
 299                 return (DDI_FAILURE);
 300 
 301         /* allocate and initialize state structure */
 302         state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP);
 303         state->ms_opened = B_FALSE;
 304         state->reset_state = MSE_RESET_IDLE;
 305         state->reset_tid = 0;
 306         state->bc_id = 0;
 307         ddi_set_driver_private(dip, state);
 308 
 309         /*
 310          * In order to support virtual keyboard/mouse, we should distinguish
 311          * between internal virtual open and external physical open.
 312          *
 313          * When the physical devices are opened by application, they will
 314          * be unlinked from the virtual device and their data stream will
 315          * not be sent to the virtual device. When the opened physical
 316          * devices are closed, they will be relinked to the virtual devices.
 317          *
 318          * All these automatic switch between virtual and physical are
 319          * transparent.
 320          *
 321          * So we change minor node numbering scheme to be:
 322          *      external node minor num == instance * 2
 323          *      internal node minor num == instance * 2 + 1
 324          */
 325         rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2,
 326             DDI_NT_MOUSE, NULL);
 327         if (rc != DDI_SUCCESS) {
 328                 goto fail_1;
 329         }
 330 
 331         if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
 332             instance * 2 + 1) != DDI_SUCCESS) {
 333                 goto fail_2;
 334         }
 335 
 336         rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr,
 337             (offset_t)0, (offset_t)0, &attr, &state->ms_handle);
 338         if (rc != DDI_SUCCESS) {
 339                 goto fail_2;
 340         }
 341 
 342         rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie);
 343         if (rc != DDI_SUCCESS) {
 344                 goto fail_3;
 345         }
 346 
 347         mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER,
 348             state->ms_iblock_cookie);
 349         mutex_init(&state->reset_mutex, NULL, MUTEX_DRIVER,
 350             state->ms_iblock_cookie);
 351         cv_init(&state->reset_cv, NULL, CV_DRIVER, NULL);
 352 
 353         rc = ddi_add_intr(dip, 0,
 354             (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL,
 355             mouse8042_intr, (caddr_t)state);
 356         if (rc != DDI_SUCCESS) {
 357                 goto fail_3;
 358         }
 359 
 360         mouse8042_dip = dip;
 361 
 362         /* Ready to handle inbound data from mouse8042_intr */
 363         state->ready = 1;
 364 
 365         /* Now that we're attached, announce our presence to the world. */
 366         ddi_report_dev(dip);
 367         return (DDI_SUCCESS);
 368 
 369 fail_3:
 370         ddi_regs_map_free(&state->ms_handle);
 371 
 372 fail_2:
 373         ddi_remove_minor_node(dip, NULL);
 374 
 375 fail_1:
 376         kmem_free(state, sizeof (struct mouse_state));
 377         return (rc);
 378 }
 379 
 380 /*ARGSUSED*/
 381 static int
 382 mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 383 {
 384         struct mouse_state *state;
 385 
 386         state = ddi_get_driver_private(dip);
 387 
 388         switch (cmd) {
 389         case DDI_SUSPEND:
 390                 /* Ignore all data from mouse8042_intr until we fully resume */
 391                 state->ready = 0;
 392                 return (DDI_SUCCESS);
 393 
 394         case DDI_DETACH:
 395                 ddi_remove_intr(dip, 0, state->ms_iblock_cookie);
 396                 mouse8042_dip = NULL;
 397                 cv_destroy(&state->reset_cv);
 398                 mutex_destroy(&state->reset_mutex);
 399                 mutex_destroy(&state->ms_mutex);
 400                 ddi_prop_remove_all(dip);
 401                 ddi_regs_map_free(&state->ms_handle);
 402                 ddi_remove_minor_node(dip, NULL);
 403                 kmem_free(state, sizeof (struct mouse_state));
 404                 return (DDI_SUCCESS);
 405 
 406         default:
 407                 return (DDI_FAILURE);
 408         }
 409 }
 410 
 411 
 412 /* ARGSUSED */
 413 static int
 414 mouse8042_getinfo(
 415     dev_info_t *dip,
 416     ddi_info_cmd_t infocmd,
 417     void *arg,
 418     void **result)
 419 {
 420         dev_t dev = (dev_t)arg;
 421         minor_t minor = getminor(dev);
 422         int     instance = MOUSE8042_MINOR_TO_INSTANCE(minor);
 423 
 424         switch (infocmd) {
 425         case DDI_INFO_DEVT2DEVINFO:
 426                 if (mouse8042_dip == NULL)
 427                         return (DDI_FAILURE);
 428 
 429                 *result = (void *)mouse8042_dip;
 430                 break;
 431         case DDI_INFO_DEVT2INSTANCE:
 432                 *result = (void *)(uintptr_t)instance;
 433                 break;
 434         default:
 435                 return (DDI_FAILURE);
 436         }
 437         return (DDI_SUCCESS);
 438 }
 439 
 440 /*ARGSUSED*/
 441 static int
 442 mouse8042_open(
 443         queue_t *q,
 444         dev_t   *devp,
 445         int     flag,
 446         int     sflag,
 447         cred_t  *cred_p)
 448 {
 449         struct mouse_state *state;
 450         minor_t minor = getminor(*devp);
 451         int rval;
 452 
 453         if (mouse8042_dip == NULL)
 454                 return (ENXIO);
 455 
 456         state = ddi_get_driver_private(mouse8042_dip);
 457 
 458         mutex_enter(&state->ms_mutex);
 459 
 460         if (state->ms_opened) {
 461                 /*
 462                  * Exit if the same minor node is already open
 463                  */
 464                 if (state->ms_minor == minor) {
 465                         mutex_exit(&state->ms_mutex);
 466                         return (0);
 467                 }
 468 
 469                 /*
 470                  * Check whether it is switch between physical and virtual
 471                  *
 472                  * Opening from virtual while the device is being physically
 473                  * opened by an application should not happen. So we ASSERT
 474                  * this in DEBUG version, and return error in the non-DEBUG
 475                  * case.
 476                  */
 477                 ASSERT(!MOUSE8042_INTERNAL_OPEN(minor));
 478 
 479                 if (MOUSE8042_INTERNAL_OPEN(minor)) {
 480                         mutex_exit(&state->ms_mutex);
 481                         return (EINVAL);
 482                 }
 483 
 484                 /*
 485                  * Opening the physical one while it is being underneath
 486                  * the virtual one.
 487                  *
 488                  * consconfig_unlink is called to unlink this device from
 489                  * the virtual one, thus the old stream serving for this
 490                  * device under the virtual one is closed, and then the
 491                  * lower driver's close routine (here is mouse8042_close)
 492                  * is also called to accomplish the whole stream close.
 493                  * Here we have to drop the lock because mouse8042_close
 494                  * also needs the lock.
 495                  *
 496                  * For mouse, the old stream is:
 497                  *      consms->["pushmod"->]"mouse_vp driver"
 498                  *
 499                  * After the consconfig_unlink returns, the old stream is closed
 500                  * and we grab the lock again to reopen this device as normal.
 501                  */
 502                 mutex_exit(&state->ms_mutex);
 503 
 504                 /*
 505                  * If unlink fails, fail the physical open.
 506                  */
 507                 if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip),
 508                     MOUSE8042_INTERNAL_MINOR(minor))) != 0) {
 509                         return (rval);
 510                 }
 511 
 512                 mutex_enter(&state->ms_mutex);
 513         }
 514 
 515 
 516         q->q_ptr = (caddr_t)state;
 517         WR(q)->q_ptr = (caddr_t)state;
 518         state->ms_rqp = q;
 519         state->ms_wqp = WR(q);
 520 
 521         qprocson(q);
 522 
 523         state->ms_minor = minor;
 524         state->ms_opened = B_TRUE;
 525 
 526         mutex_exit(&state->ms_mutex);
 527 
 528         return (0);
 529 }
 530 
 531 
 532 /*ARGSUSED*/
 533 static int
 534 mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
 535 {
 536         struct mouse_state *state;
 537         minor_t minor;
 538 
 539         state = (struct mouse_state *)q->q_ptr;
 540 
 541         /*
 542          * Disable queue processing now, so that another reset cannot get in
 543          * after we wait for the current reset (if any) to complete.
 544          */
 545         qprocsoff(q);
 546 
 547         mutex_enter(&state->reset_mutex);
 548         while (state->reset_state != MSE_RESET_IDLE) {
 549                 /*
 550                  * Waiting for the previous reset to finish is
 551                  * non-interruptible.  Some upper-level clients
 552                  * cannot deal with EINTR and will not close the
 553                  * STREAM properly, resulting in failure to reopen it
 554                  * within the same process.
 555                  */
 556                 cv_wait(&state->reset_cv, &state->reset_mutex);
 557         }
 558 
 559         if (state->reset_tid != 0) {
 560                 (void) quntimeout(q, state->reset_tid);
 561                 state->reset_tid = 0;
 562         }
 563 
 564         if (state->reply_mp != NULL) {
 565                 freemsg(state->reply_mp);
 566                 state->reply_mp = NULL;
 567         }
 568 
 569         if (state->reset_ack_mp != NULL) {
 570                 freemsg(state->reset_ack_mp);
 571                 state->reset_ack_mp = NULL;
 572         }
 573 
 574         mutex_exit(&state->reset_mutex);
 575 
 576         mutex_enter(&state->ms_mutex);
 577 
 578         if (state->bc_id != 0) {
 579                 (void) qunbufcall(q, state->bc_id);
 580                 state->bc_id = 0;
 581         }
 582 
 583         q->q_ptr = NULL;
 584         WR(q)->q_ptr = NULL;
 585         state->ms_rqp = NULL;
 586         state->ms_wqp = NULL;
 587 
 588         state->ms_opened = B_FALSE;
 589 
 590         minor = state->ms_minor;
 591 
 592         mutex_exit(&state->ms_mutex);
 593 
 594         if (!MOUSE8042_INTERNAL_OPEN(minor)) {
 595                 /*
 596                  * Closing physical PS/2 mouse
 597                  *
 598                  * Link it back to virtual mouse, and
 599                  * mouse8042_open will be called as a result
 600                  * of the consconfig_link call.  Do NOT try
 601                  * this if the mouse is about to be detached!
 602                  *
 603                  * If linking back fails, this specific mouse
 604                  * will not be available underneath the virtual
 605                  * mouse, and can only be accessed via physical
 606                  * open.
 607                  */
 608                 consconfig_link(ddi_driver_major(mouse8042_dip),
 609                     MOUSE8042_INTERNAL_MINOR(minor));
 610         }
 611 
 612         return (0);
 613 }
 614 
 615 static void
 616 mouse8042_iocnack(
 617     queue_t *qp,
 618     mblk_t *mp,
 619     struct iocblk *iocp,
 620     int error,
 621     int rval)
 622 {
 623         mp->b_datap->db_type = M_IOCNAK;
 624         iocp->ioc_rval = rval;
 625         iocp->ioc_error = error;
 626         qreply(qp, mp);
 627 }
 628 
 629 static void
 630 mouse8042_reset_timeout(void *argp)
 631 {
 632         struct mouse_state *state = (struct mouse_state *)argp;
 633         mblk_t *mp;
 634 
 635         mutex_enter(&state->reset_mutex);
 636 
 637         /*
 638          * If the interrupt handler hasn't completed the reset handling
 639          * (reset_state would be IDLE or FAILED in that case), then
 640          * drop the 8042 lock, and send a faked retry reply upstream,
 641          * then enable the queue for further message processing.
 642          */
 643         if (state->reset_state != MSE_RESET_IDLE &&
 644             state->reset_state != MSE_RESET_FAILED) {
 645 
 646                 state->reset_tid = 0;
 647                 state->reset_state = MSE_RESET_IDLE;
 648                 cv_signal(&state->reset_cv);
 649 
 650                 (void) ddi_get8(state->ms_handle, state->ms_addr +
 651                     I8042_UNLOCK);
 652 
 653                 mp = state->reply_mp;
 654                 *mp->b_wptr++ = MSERESEND;
 655                 state->reply_mp = NULL;
 656 
 657                 if (state->ms_rqp != NULL)
 658                         putnext(state->ms_rqp, mp);
 659                 else
 660                         freemsg(mp);
 661 
 662                 ASSERT(state->ms_wqp != NULL);
 663 
 664                 enableok(state->ms_wqp);
 665                 qenable(state->ms_wqp);
 666         }
 667 
 668         mutex_exit(&state->reset_mutex);
 669 }
 670 
 671 /*
 672  * Returns 1 if the caller should put the message (bp) back on the queue
 673  */
 674 static int
 675 mouse8042_initiate_reset(queue_t *q, mblk_t *mp, struct mouse_state *state)
 676 {
 677         mutex_enter(&state->reset_mutex);
 678         /*
 679          * If we're in the middle of a reset, put the message back on the queue
 680          * for processing later.
 681          */
 682         if (state->reset_state != MSE_RESET_IDLE) {
 683                 /*
 684                  * We noenable the queue again here in case it was backenabled
 685                  * by an upper-level module.
 686                  */
 687                 noenable(q);
 688 
 689                 mutex_exit(&state->reset_mutex);
 690                 return (1);
 691         }
 692 
 693         /*
 694          * Drop the reset state lock before allocating the response message and
 695          * grabbing the 8042 exclusive-access lock (since those operations
 696          * may take an extended period of time to complete).
 697          */
 698         mutex_exit(&state->reset_mutex);
 699 
 700         if (state->reply_mp == NULL)
 701                 state->reply_mp = allocb(2, BPRI_MED);
 702         if (state->reset_ack_mp == NULL)
 703                 state->reset_ack_mp = allocb(1, BPRI_MED);
 704 
 705         if (state->reply_mp == NULL || state->reset_ack_mp == NULL) {
 706                 /*
 707                  * Allocation failed -- set up a bufcall to enable the queue
 708                  * whenever there is enough memory to allocate the response
 709                  * message.
 710                  */
 711                 state->bc_id = qbufcall(q, (state->reply_mp == NULL) ? 2 : 1,
 712                     BPRI_MED, (void (*)(void *))qenable, q);
 713 
 714                 if (state->bc_id == 0) {
 715                         /*
 716                          * If the qbufcall failed, we cannot proceed, so use the
 717                          * message we were sent to respond with an error.
 718                          */
 719                         *mp->b_rptr = MSEERROR;
 720                         mp->b_wptr = mp->b_rptr + 1;
 721                         qreply(q, mp);
 722                         return (0);
 723                 }
 724 
 725                 return (1);
 726         } else {
 727                 /* Bufcall completed successfully (or wasn't needed) */
 728                 state->bc_id = 0;
 729         }
 730 
 731         /*
 732          * Gain exclusive access to the 8042 for the duration of the reset.
 733          * The unlock will occur when the reset has either completed or timed
 734          * out.
 735          */
 736         (void) ddi_get8(state->ms_handle,
 737             state->ms_addr + I8042_LOCK);
 738 
 739         mutex_enter(&state->reset_mutex);
 740 
 741         state->reset_state = MSE_RESET_PRE;
 742         noenable(q);
 743 
 744         state->reset_tid = qtimeout(q,
 745             mouse8042_reset_timeout,
 746             state,
 747             drv_usectohz(
 748             MOUSE8042_RESET_TIMEOUT_USECS));
 749 
 750         ddi_put8(state->ms_handle,
 751             state->ms_addr +
 752             I8042_INT_OUTPUT_DATA, MSERESET);
 753 
 754         mp->b_rptr++;
 755 
 756         mutex_exit(&state->reset_mutex);
 757         return (1);
 758 }
 759 
 760 /*
 761  * Returns 1 if the caller should stop processing messages
 762  */
 763 static int
 764 mouse8042_process_data_msg(queue_t *q, mblk_t *mp, struct mouse_state *state)
 765 {
 766         mblk_t *bp;
 767         mblk_t *next;
 768 
 769         bp = mp;
 770         do {
 771                 while (bp->b_rptr < bp->b_wptr) {
 772                         /*
 773                          * Detect an attempt to reset the mouse.  Lock out any
 774                          * further mouse writes until the reset has completed.
 775                          */
 776                         if (*bp->b_rptr == MSERESET) {
 777 
 778                                 /*
 779                                  * If we couldn't allocate memory and we
 780                                  * we couldn't register a bufcall,
 781                                  * mouse8042_initiate_reset returns 0 and
 782                                  * has already used the message to send an
 783                                  * error reply back upstream, so there is no
 784                                  * need to deallocate or put this message back
 785                                  * on the queue.
 786                                  */
 787                                 if (mouse8042_initiate_reset(q, bp, state) == 0)
 788                                         return (1);
 789 
 790                                 /*
 791                                  * If there's no data remaining in this block,
 792                                  * free this block and put the following blocks
 793                                  * of this message back on the queue. If putting
 794                                  * the rest of the message back on the queue
 795                                  * fails, free the the message.
 796                                  */
 797                                 if (MBLKL(bp) == 0) {
 798                                         next = bp->b_cont;
 799                                         freeb(bp);
 800                                         bp = next;
 801                                 }
 802                                 if (bp != NULL) {
 803                                         if (!putbq(q, bp))
 804                                                 freemsg(bp);
 805                                 }
 806 
 807                                 return (1);
 808 
 809                         }
 810                         ddi_put8(state->ms_handle,
 811                             state->ms_addr + I8042_INT_OUTPUT_DATA,
 812                             *bp->b_rptr++);
 813                 }
 814                 next = bp->b_cont;
 815                 freeb(bp);
 816         } while ((bp = next) != NULL);
 817 
 818         return (0);
 819 }
 820 
 821 static int
 822 mouse8042_process_msg(queue_t *q, mblk_t *mp, struct mouse_state *state)
 823 {
 824         struct iocblk *iocbp;
 825         int rv = 0;
 826 
 827         iocbp = (struct iocblk *)mp->b_rptr;
 828 
 829         switch (mp->b_datap->db_type) {
 830         case M_FLUSH:
 831                 if (*mp->b_rptr & FLUSHW) {
 832                         flushq(q, FLUSHDATA);
 833                         *mp->b_rptr &= ~FLUSHW;
 834                 }
 835                 if (*mp->b_rptr & FLUSHR) {
 836                         qreply(q, mp);
 837                 } else
 838                         freemsg(mp);
 839                 break;
 840         case M_IOCTL:
 841                 mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
 842                 break;
 843         case M_IOCDATA:
 844                 mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
 845                 break;
 846         case M_DATA:
 847                 rv = mouse8042_process_data_msg(q, mp, state);
 848                 break;
 849         default:
 850                 freemsg(mp);
 851                 break;
 852         }
 853 
 854         return (rv);
 855 }
 856 
 857 /*
 858  * This is the main mouse input routine.  Commands and parameters
 859  * from upstream are sent to the mouse device immediately, unless
 860  * the mouse is in the process of being reset, in which case
 861  * commands are queued and executed later in the service procedure.
 862  */
 863 static int
 864 mouse8042_wput(queue_t *q, mblk_t *mp)
 865 {
 866         struct mouse_state *state;
 867         state = (struct mouse_state *)q->q_ptr;
 868 
 869         /*
 870          * Process all messages immediately, unless a reset is in
 871          * progress.  If a reset is in progress, deflect processing to
 872          * the service procedure.
 873          */
 874         if (state->reset_state != MSE_RESET_IDLE)
 875                 return (putq(q, mp));
 876 
 877         /*
 878          * If there are still messages outstanding in the queue that
 879          * the service procedure hasn't processed yet, put this
 880          * message in the queue also, to ensure proper message
 881          * ordering.
 882          */
 883         if (q->q_first)
 884                 return (putq(q, mp));
 885 
 886         (void) mouse8042_process_msg(q, mp, state);
 887 
 888         return (0);
 889 }
 890 
 891 static int
 892 mouse8042_wsrv(queue_t *qp)
 893 {
 894         mblk_t *mp;
 895         struct mouse_state *state;
 896         state = (struct mouse_state *)qp->q_ptr;
 897 
 898         while ((mp = getq(qp)) != NULL) {
 899                 if (mouse8042_process_msg(qp, mp, state) != 0)
 900                         break;
 901         }
 902 
 903         return (0);
 904 }
 905 
 906 /*
 907  * Returns the next reset state, given the current state and the byte
 908  * received from the mouse.  Error and Resend codes are handled by the
 909  * caller.
 910  */
 911 static mouse8042_reset_state_e
 912 mouse8042_reset_fsm(mouse8042_reset_state_e reset_state, uint8_t mdata)
 913 {
 914         switch (reset_state) {
 915         case MSE_RESET_PRE:     /* RESET sent, now we expect an ACK */
 916                 if (mdata == MSE_ACK)   /* Got the ACK */
 917                         return (MSE_RESET_ACK);
 918                 break;
 919 
 920         case MSE_RESET_ACK:     /* ACK received; now we expect 0xAA */
 921                 if (mdata == MSE_AA)    /* Got the 0xAA */
 922                         return (MSE_RESET_AA);
 923                 break;
 924 
 925         case MSE_RESET_AA:      /* 0xAA received; now we expect 0x00 */
 926                 if (mdata == MSE_00)
 927                         return (MSE_RESET_IDLE);
 928                 break;
 929         }
 930 
 931         return (reset_state);
 932 }
 933 
 934 static uint_t
 935 mouse8042_intr(caddr_t arg)
 936 {
 937         unsigned char    mdata;
 938         mblk_t *mp;
 939         struct mouse_state *state = (struct mouse_state *)arg;
 940         int rc;
 941 
 942         mutex_enter(&state->ms_mutex);
 943 
 944         rc = DDI_INTR_UNCLAIMED;
 945 
 946         for (;;) {
 947 
 948                 if (ddi_get8(state->ms_handle,
 949                     state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) {
 950                         break;
 951                 }
 952 
 953                 mdata = ddi_get8(state->ms_handle,
 954                     state->ms_addr + I8042_INT_INPUT_DATA);
 955 
 956                 rc = DDI_INTR_CLAIMED;
 957 
 958                 /*
 959                  * If we're not ready for this data, discard it.
 960                  */
 961                 if (!state->ready)
 962                         continue;
 963 
 964                 mutex_enter(&state->reset_mutex);
 965                 if (state->reset_state != MSE_RESET_IDLE) {
 966 
 967                         if (mdata == MSEERROR || mdata == MSERESET) {
 968                                 state->reset_state = MSE_RESET_FAILED;
 969                         } else {
 970                                 state->reset_state =
 971                                     mouse8042_reset_fsm(state->reset_state,
 972                                     mdata);
 973                         }
 974 
 975                         if (state->reset_state == MSE_RESET_ACK) {
 976 
 977                         /*
 978                          * We received an ACK from the mouse, so
 979                          * send it upstream immediately so that
 980                          * consumers depending on the immediate
 981                          * ACK don't time out.
 982                          */
 983                                 if (state->reset_ack_mp != NULL) {
 984 
 985                                         mp = state->reset_ack_mp;
 986 
 987                                         state->reset_ack_mp = NULL;
 988 
 989                                         if (state->ms_rqp != NULL) {
 990                                                 *mp->b_wptr++ = MSE_ACK;
 991                                                 putnext(state->ms_rqp, mp);
 992                                         } else
 993                                                 freemsg(mp);
 994                                 }
 995 
 996                                 if (state->ms_wqp != NULL) {
 997                                         enableok(state->ms_wqp);
 998                                         qenable(state->ms_wqp);
 999                                 }
1000 
1001                         } else if (state->reset_state == MSE_RESET_IDLE ||
1002                             state->reset_state == MSE_RESET_FAILED) {
1003 
1004                         /*
1005                          * If we transitioned back to the idle reset state (or
1006                          * the reset failed), disable the timeout, release the
1007                          * 8042 exclusive-access lock, then send the response
1008                          * the the upper-level modules. Finally, enable the
1009                          * queue and schedule queue service procedures so that
1010                          * upper-level modules can process the response.
1011                          * Otherwise, if we're still in the middle of the
1012                          * reset sequence, do not send the data up (since the
1013                          * response is sent at the end of the sequence, or
1014                          * on timeout/error).
1015                          */
1016 
1017                                 mutex_exit(&state->reset_mutex);
1018                                 (void) quntimeout(state->ms_wqp,
1019                                     state->reset_tid);
1020                                 mutex_enter(&state->reset_mutex);
1021 
1022                                 (void) ddi_get8(state->ms_handle,
1023                                     state->ms_addr + I8042_UNLOCK);
1024 
1025                                 state->reset_tid = 0;
1026                                 if (state->reply_mp != NULL) {
1027                                         mp = state->reply_mp;
1028                                         if (state->reset_state ==
1029                                             MSE_RESET_FAILED) {
1030                                                 *mp->b_wptr++ = mdata;
1031                                         } else {
1032                                                 *mp->b_wptr++ = MSE_AA;
1033                                                 *mp->b_wptr++ = MSE_00;
1034                                         }
1035                                         state->reply_mp = NULL;
1036                                 } else {
1037                                         mp = NULL;
1038                                 }
1039 
1040                                 state->reset_state = MSE_RESET_IDLE;
1041                                 cv_signal(&state->reset_cv);
1042 
1043                                 if (mp != NULL) {
1044                                         if (state->ms_rqp != NULL)
1045                                                 putnext(state->ms_rqp, mp);
1046                                         else
1047                                                 freemsg(mp);
1048                                 }
1049 
1050                                 if (state->ms_wqp != NULL) {
1051                                         enableok(state->ms_wqp);
1052                                         qenable(state->ms_wqp);
1053                                 }
1054                         }
1055 
1056                         mutex_exit(&state->reset_mutex);
1057                         mutex_exit(&state->ms_mutex);
1058                         return (rc);
1059                 }
1060                 mutex_exit(&state->reset_mutex);
1061 
1062                 if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) {
1063                         *mp->b_wptr++ = mdata;
1064                         putnext(state->ms_rqp, mp);
1065                 }
1066         }
1067         mutex_exit(&state->ms_mutex);
1068 
1069         return (rc);
1070 }