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, NULL } 229 }; 230 231 /* 232 * This is the driver initialization routine. 233 */ 234 int 235 _init() 236 { 237 int rv; 238 239 rv = mod_install(&modlinkage); 240 return (rv); 241 } 242 243 244 int 245 _fini(void) 246 { 247 return (mod_remove(&modlinkage)); 248 } 249 250 251 int 252 _info(struct modinfo *modinfop) 253 { 254 return (mod_info(&modlinkage, modinfop)); 255 } 256 257 static int 258 mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 259 { 260 struct mouse_state *state; 261 mblk_t *mp; 262 int instance = ddi_get_instance(dip); 263 static ddi_device_acc_attr_t attr = { 264 DDI_DEVICE_ATTR_V0, 265 DDI_NEVERSWAP_ACC, 266 DDI_STRICTORDER_ACC, 267 }; 268 int rc; 269 270 271 if (cmd == DDI_RESUME) { 272 state = (struct mouse_state *)ddi_get_driver_private(dip); 273 274 /* Ready to handle inbound data from mouse8042_intr */ 275 state->ready = 1; 276 277 /* 278 * Send a 0xaa 0x00 upstream. 279 * This causes the vuid module to reset the mouse. 280 */ 281 if (state->ms_rqp != NULL) { 282 if (mp = allocb(1, BPRI_MED)) { 283 *mp->b_wptr++ = 0xaa; 284 putnext(state->ms_rqp, mp); 285 } 286 if (mp = allocb(1, BPRI_MED)) { 287 *mp->b_wptr++ = 0x0; 288 putnext(state->ms_rqp, mp); 289 } 290 } 291 return (DDI_SUCCESS); 292 } 293 294 if (cmd != DDI_ATTACH) 295 return (DDI_FAILURE); 296 297 if (mouse8042_dip != NULL) 298 return (DDI_FAILURE); 299 300 /* allocate and initialize state structure */ 301 state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP); 302 state->ms_opened = B_FALSE; 303 state->reset_state = MSE_RESET_IDLE; 304 state->reset_tid = 0; 305 state->bc_id = 0; 306 ddi_set_driver_private(dip, state); 307 308 /* 309 * In order to support virtual keyboard/mouse, we should distinguish 310 * between internal virtual open and external physical open. 311 * 312 * When the physical devices are opened by application, they will 313 * be unlinked from the virtual device and their data stream will 314 * not be sent to the virtual device. When the opened physical 315 * devices are closed, they will be relinked to the virtual devices. 316 * 317 * All these automatic switch between virtual and physical are 318 * transparent. 319 * 320 * So we change minor node numbering scheme to be: 321 * external node minor num == instance * 2 322 * internal node minor num == instance * 2 + 1 323 */ 324 rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2, 325 DDI_NT_MOUSE, NULL); 326 if (rc != DDI_SUCCESS) { 327 goto fail_1; 328 } 329 330 if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR, 331 instance * 2 + 1) != DDI_SUCCESS) { 332 goto fail_2; 333 } 334 335 rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr, 336 (offset_t)0, (offset_t)0, &attr, &state->ms_handle); 337 if (rc != DDI_SUCCESS) { 338 goto fail_2; 339 } 340 341 rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie); 342 if (rc != DDI_SUCCESS) { 343 goto fail_3; 344 } 345 346 mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER, 347 state->ms_iblock_cookie); 348 mutex_init(&state->reset_mutex, NULL, MUTEX_DRIVER, 349 state->ms_iblock_cookie); 350 cv_init(&state->reset_cv, NULL, CV_DRIVER, NULL); 351 352 rc = ddi_add_intr(dip, 0, 353 (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL, 354 mouse8042_intr, (caddr_t)state); 355 if (rc != DDI_SUCCESS) { 356 goto fail_3; 357 } 358 359 mouse8042_dip = dip; 360 361 /* Ready to handle inbound data from mouse8042_intr */ 362 state->ready = 1; 363 364 /* Now that we're attached, announce our presence to the world. */ 365 ddi_report_dev(dip); 366 return (DDI_SUCCESS); 367 368 fail_3: 369 ddi_regs_map_free(&state->ms_handle); 370 371 fail_2: 372 ddi_remove_minor_node(dip, NULL); 373 374 fail_1: 375 kmem_free(state, sizeof (struct mouse_state)); 376 return (rc); 377 } 378 379 /*ARGSUSED*/ 380 static int 381 mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 382 { 383 struct mouse_state *state; 384 385 state = ddi_get_driver_private(dip); 386 387 switch (cmd) { 388 case DDI_SUSPEND: 389 /* Ignore all data from mouse8042_intr until we fully resume */ 390 state->ready = 0; 391 return (DDI_SUCCESS); 392 393 case DDI_DETACH: 394 ddi_remove_intr(dip, 0, state->ms_iblock_cookie); 395 mouse8042_dip = NULL; 396 cv_destroy(&state->reset_cv); 397 mutex_destroy(&state->reset_mutex); 398 mutex_destroy(&state->ms_mutex); 399 ddi_prop_remove_all(dip); 400 ddi_regs_map_free(&state->ms_handle); 401 ddi_remove_minor_node(dip, NULL); 402 kmem_free(state, sizeof (struct mouse_state)); 403 return (DDI_SUCCESS); 404 405 default: 406 return (DDI_FAILURE); 407 } 408 } 409 410 411 /* ARGSUSED */ 412 static int 413 mouse8042_getinfo( 414 dev_info_t *dip, 415 ddi_info_cmd_t infocmd, 416 void *arg, 417 void **result) 418 { 419 dev_t dev = (dev_t)arg; 420 minor_t minor = getminor(dev); 421 int instance = MOUSE8042_MINOR_TO_INSTANCE(minor); 422 423 switch (infocmd) { 424 case DDI_INFO_DEVT2DEVINFO: 425 if (mouse8042_dip == NULL) 426 return (DDI_FAILURE); 427 428 *result = (void *)mouse8042_dip; 429 break; 430 case DDI_INFO_DEVT2INSTANCE: 431 *result = (void *)(uintptr_t)instance; 432 break; 433 default: 434 return (DDI_FAILURE); 435 } 436 return (DDI_SUCCESS); 437 } 438 439 /*ARGSUSED*/ 440 static int 441 mouse8042_open( 442 queue_t *q, 443 dev_t *devp, 444 int flag, 445 int sflag, 446 cred_t *cred_p) 447 { 448 struct mouse_state *state; 449 minor_t minor = getminor(*devp); 450 int rval; 451 452 if (mouse8042_dip == NULL) 453 return (ENXIO); 454 455 state = ddi_get_driver_private(mouse8042_dip); 456 457 mutex_enter(&state->ms_mutex); 458 459 if (state->ms_opened) { 460 /* 461 * Exit if the same minor node is already open 462 */ 463 if (state->ms_minor == minor) { 464 mutex_exit(&state->ms_mutex); 465 return (0); 466 } 467 468 /* 469 * Check whether it is switch between physical and virtual 470 * 471 * Opening from virtual while the device is being physically 472 * opened by an application should not happen. So we ASSERT 473 * this in DEBUG version, and return error in the non-DEBUG 474 * case. 475 */ 476 ASSERT(!MOUSE8042_INTERNAL_OPEN(minor)); 477 478 if (MOUSE8042_INTERNAL_OPEN(minor)) { 479 mutex_exit(&state->ms_mutex); 480 return (EINVAL); 481 } 482 483 /* 484 * Opening the physical one while it is being underneath 485 * the virtual one. 486 * 487 * consconfig_unlink is called to unlink this device from 488 * the virtual one, thus the old stream serving for this 489 * device under the virtual one is closed, and then the 490 * lower driver's close routine (here is mouse8042_close) 491 * is also called to accomplish the whole stream close. 492 * Here we have to drop the lock because mouse8042_close 493 * also needs the lock. 494 * 495 * For mouse, the old stream is: 496 * consms->["pushmod"->]"mouse_vp driver" 497 * 498 * After the consconfig_unlink returns, the old stream is closed 499 * and we grab the lock again to reopen this device as normal. 500 */ 501 mutex_exit(&state->ms_mutex); 502 503 /* 504 * If unlink fails, fail the physical open. 505 */ 506 if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip), 507 MOUSE8042_INTERNAL_MINOR(minor))) != 0) { 508 return (rval); 509 } 510 511 mutex_enter(&state->ms_mutex); 512 } 513 514 515 q->q_ptr = (caddr_t)state; 516 WR(q)->q_ptr = (caddr_t)state; 517 state->ms_rqp = q; 518 state->ms_wqp = WR(q); 519 520 qprocson(q); 521 522 state->ms_minor = minor; 523 state->ms_opened = B_TRUE; 524 525 mutex_exit(&state->ms_mutex); 526 527 return (0); 528 } 529 530 531 /*ARGSUSED*/ 532 static int 533 mouse8042_close(queue_t *q, int flag, cred_t *cred_p) 534 { 535 struct mouse_state *state; 536 minor_t minor; 537 538 state = (struct mouse_state *)q->q_ptr; 539 540 /* 541 * Disable queue processing now, so that another reset cannot get in 542 * after we wait for the current reset (if any) to complete. 543 */ 544 qprocsoff(q); 545 546 mutex_enter(&state->reset_mutex); 547 while (state->reset_state != MSE_RESET_IDLE) { 548 /* 549 * Waiting for the previous reset to finish is 550 * non-interruptible. Some upper-level clients 551 * cannot deal with EINTR and will not close the 552 * STREAM properly, resulting in failure to reopen it 553 * within the same process. 554 */ 555 cv_wait(&state->reset_cv, &state->reset_mutex); 556 } 557 558 if (state->reset_tid != 0) { 559 (void) quntimeout(q, state->reset_tid); 560 state->reset_tid = 0; 561 } 562 563 if (state->reply_mp != NULL) { 564 freemsg(state->reply_mp); 565 state->reply_mp = NULL; 566 } 567 568 if (state->reset_ack_mp != NULL) { 569 freemsg(state->reset_ack_mp); 570 state->reset_ack_mp = NULL; 571 } 572 573 mutex_exit(&state->reset_mutex); 574 575 mutex_enter(&state->ms_mutex); 576 577 if (state->bc_id != 0) { 578 (void) qunbufcall(q, state->bc_id); 579 state->bc_id = 0; 580 } 581 582 q->q_ptr = NULL; 583 WR(q)->q_ptr = NULL; 584 state->ms_rqp = NULL; 585 state->ms_wqp = NULL; 586 587 state->ms_opened = B_FALSE; 588 589 minor = state->ms_minor; 590 591 mutex_exit(&state->ms_mutex); 592 593 if (!MOUSE8042_INTERNAL_OPEN(minor)) { 594 /* 595 * Closing physical PS/2 mouse 596 * 597 * Link it back to virtual mouse, and 598 * mouse8042_open will be called as a result 599 * of the consconfig_link call. Do NOT try 600 * this if the mouse is about to be detached! 601 * 602 * If linking back fails, this specific mouse 603 * will not be available underneath the virtual 604 * mouse, and can only be accessed via physical 605 * open. 606 */ 607 consconfig_link(ddi_driver_major(mouse8042_dip), 608 MOUSE8042_INTERNAL_MINOR(minor)); 609 } 610 611 return (0); 612 } 613 614 static void 615 mouse8042_iocnack( 616 queue_t *qp, 617 mblk_t *mp, 618 struct iocblk *iocp, 619 int error, 620 int rval) 621 { 622 mp->b_datap->db_type = M_IOCNAK; 623 iocp->ioc_rval = rval; 624 iocp->ioc_error = error; 625 qreply(qp, mp); 626 } 627 628 static void 629 mouse8042_reset_timeout(void *argp) 630 { 631 struct mouse_state *state = (struct mouse_state *)argp; 632 mblk_t *mp; 633 634 mutex_enter(&state->reset_mutex); 635 636 /* 637 * If the interrupt handler hasn't completed the reset handling 638 * (reset_state would be IDLE or FAILED in that case), then 639 * drop the 8042 lock, and send a faked retry reply upstream, 640 * then enable the queue for further message processing. 641 */ 642 if (state->reset_state != MSE_RESET_IDLE && 643 state->reset_state != MSE_RESET_FAILED) { 644 645 state->reset_tid = 0; 646 state->reset_state = MSE_RESET_IDLE; 647 cv_signal(&state->reset_cv); 648 649 (void) ddi_get8(state->ms_handle, state->ms_addr + 650 I8042_UNLOCK); 651 652 mp = state->reply_mp; 653 *mp->b_wptr++ = MSERESEND; 654 state->reply_mp = NULL; 655 656 if (state->ms_rqp != NULL) 657 putnext(state->ms_rqp, mp); 658 else 659 freemsg(mp); 660 661 ASSERT(state->ms_wqp != NULL); 662 663 enableok(state->ms_wqp); 664 qenable(state->ms_wqp); 665 } 666 667 mutex_exit(&state->reset_mutex); 668 } 669 670 /* 671 * Returns 1 if the caller should put the message (bp) back on the queue 672 */ 673 static int 674 mouse8042_initiate_reset(queue_t *q, mblk_t *mp, struct mouse_state *state) 675 { 676 mutex_enter(&state->reset_mutex); 677 /* 678 * If we're in the middle of a reset, put the message back on the queue 679 * for processing later. 680 */ 681 if (state->reset_state != MSE_RESET_IDLE) { 682 /* 683 * We noenable the queue again here in case it was backenabled 684 * by an upper-level module. 685 */ 686 noenable(q); 687 688 mutex_exit(&state->reset_mutex); 689 return (1); 690 } 691 692 /* 693 * Drop the reset state lock before allocating the response message and 694 * grabbing the 8042 exclusive-access lock (since those operations 695 * may take an extended period of time to complete). 696 */ 697 mutex_exit(&state->reset_mutex); 698 699 if (state->reply_mp == NULL) 700 state->reply_mp = allocb(2, BPRI_MED); 701 if (state->reset_ack_mp == NULL) 702 state->reset_ack_mp = allocb(1, BPRI_MED); 703 704 if (state->reply_mp == NULL || state->reset_ack_mp == NULL) { 705 /* 706 * Allocation failed -- set up a bufcall to enable the queue 707 * whenever there is enough memory to allocate the response 708 * message. 709 */ 710 state->bc_id = qbufcall(q, (state->reply_mp == NULL) ? 2 : 1, 711 BPRI_MED, (void (*)(void *))qenable, q); 712 713 if (state->bc_id == 0) { 714 /* 715 * If the qbufcall failed, we cannot proceed, so use the 716 * message we were sent to respond with an error. 717 */ 718 *mp->b_rptr = MSEERROR; 719 mp->b_wptr = mp->b_rptr + 1; 720 qreply(q, mp); 721 return (0); 722 } 723 724 return (1); 725 } else { 726 /* Bufcall completed successfully (or wasn't needed) */ 727 state->bc_id = 0; 728 } 729 730 /* 731 * Gain exclusive access to the 8042 for the duration of the reset. 732 * The unlock will occur when the reset has either completed or timed 733 * out. 734 */ 735 (void) ddi_get8(state->ms_handle, 736 state->ms_addr + I8042_LOCK); 737 738 mutex_enter(&state->reset_mutex); 739 740 state->reset_state = MSE_RESET_PRE; 741 noenable(q); 742 743 state->reset_tid = qtimeout(q, 744 mouse8042_reset_timeout, 745 state, 746 drv_usectohz( 747 MOUSE8042_RESET_TIMEOUT_USECS)); 748 749 ddi_put8(state->ms_handle, 750 state->ms_addr + 751 I8042_INT_OUTPUT_DATA, MSERESET); 752 753 mp->b_rptr++; 754 755 mutex_exit(&state->reset_mutex); 756 return (1); 757 } 758 759 /* 760 * Returns 1 if the caller should stop processing messages 761 */ 762 static int 763 mouse8042_process_data_msg(queue_t *q, mblk_t *mp, struct mouse_state *state) 764 { 765 mblk_t *bp; 766 mblk_t *next; 767 768 bp = mp; 769 do { 770 while (bp->b_rptr < bp->b_wptr) { 771 /* 772 * Detect an attempt to reset the mouse. Lock out any 773 * further mouse writes until the reset has completed. 774 */ 775 if (*bp->b_rptr == MSERESET) { 776 777 /* 778 * If we couldn't allocate memory and we 779 * we couldn't register a bufcall, 780 * mouse8042_initiate_reset returns 0 and 781 * has already used the message to send an 782 * error reply back upstream, so there is no 783 * need to deallocate or put this message back 784 * on the queue. 785 */ 786 if (mouse8042_initiate_reset(q, bp, state) == 0) 787 return (1); 788 789 /* 790 * If there's no data remaining in this block, 791 * free this block and put the following blocks 792 * of this message back on the queue. If putting 793 * the rest of the message back on the queue 794 * fails, free the the message. 795 */ 796 if (MBLKL(bp) == 0) { 797 next = bp->b_cont; 798 freeb(bp); 799 bp = next; 800 } 801 if (bp != NULL) { 802 if (!putbq(q, bp)) 803 freemsg(bp); 804 } 805 806 return (1); 807 808 } 809 ddi_put8(state->ms_handle, 810 state->ms_addr + I8042_INT_OUTPUT_DATA, 811 *bp->b_rptr++); 812 } 813 next = bp->b_cont; 814 freeb(bp); 815 } while ((bp = next) != NULL); 816 817 return (0); 818 } 819 820 static int 821 mouse8042_process_msg(queue_t *q, mblk_t *mp, struct mouse_state *state) 822 { 823 struct iocblk *iocbp; 824 int rv = 0; 825 826 iocbp = (struct iocblk *)mp->b_rptr; 827 828 switch (mp->b_datap->db_type) { 829 case M_FLUSH: 830 if (*mp->b_rptr & FLUSHW) { 831 flushq(q, FLUSHDATA); 832 *mp->b_rptr &= ~FLUSHW; 833 } 834 if (*mp->b_rptr & FLUSHR) { 835 qreply(q, mp); 836 } else 837 freemsg(mp); 838 break; 839 case M_IOCTL: 840 mouse8042_iocnack(q, mp, iocbp, EINVAL, 0); 841 break; 842 case M_IOCDATA: 843 mouse8042_iocnack(q, mp, iocbp, EINVAL, 0); 844 break; 845 case M_DATA: 846 rv = mouse8042_process_data_msg(q, mp, state); 847 break; 848 default: 849 freemsg(mp); 850 break; 851 } 852 853 return (rv); 854 } 855 856 /* 857 * This is the main mouse input routine. Commands and parameters 858 * from upstream are sent to the mouse device immediately, unless 859 * the mouse is in the process of being reset, in which case 860 * commands are queued and executed later in the service procedure. 861 */ 862 static int 863 mouse8042_wput(queue_t *q, mblk_t *mp) 864 { 865 struct mouse_state *state; 866 state = (struct mouse_state *)q->q_ptr; 867 868 /* 869 * Process all messages immediately, unless a reset is in 870 * progress. If a reset is in progress, deflect processing to 871 * the service procedure. 872 */ 873 if (state->reset_state != MSE_RESET_IDLE) 874 return (putq(q, mp)); 875 876 /* 877 * If there are still messages outstanding in the queue that 878 * the service procedure hasn't processed yet, put this 879 * message in the queue also, to ensure proper message 880 * ordering. 881 */ 882 if (q->q_first) 883 return (putq(q, mp)); 884 885 (void) mouse8042_process_msg(q, mp, state); 886 887 return (0); 888 } 889 890 static int 891 mouse8042_wsrv(queue_t *qp) 892 { 893 mblk_t *mp; 894 struct mouse_state *state; 895 state = (struct mouse_state *)qp->q_ptr; 896 897 while ((mp = getq(qp)) != NULL) { 898 if (mouse8042_process_msg(qp, mp, state) != 0) 899 break; 900 } 901 902 return (0); 903 } 904 905 /* 906 * Returns the next reset state, given the current state and the byte 907 * received from the mouse. Error and Resend codes are handled by the 908 * caller. 909 */ 910 static mouse8042_reset_state_e 911 mouse8042_reset_fsm(mouse8042_reset_state_e reset_state, uint8_t mdata) 912 { 913 switch (reset_state) { 914 case MSE_RESET_PRE: /* RESET sent, now we expect an ACK */ 915 if (mdata == MSE_ACK) /* Got the ACK */ 916 return (MSE_RESET_ACK); 917 break; 918 919 case MSE_RESET_ACK: /* ACK received; now we expect 0xAA */ 920 if (mdata == MSE_AA) /* Got the 0xAA */ 921 return (MSE_RESET_AA); 922 break; 923 924 case MSE_RESET_AA: /* 0xAA received; now we expect 0x00 */ 925 if (mdata == MSE_00) 926 return (MSE_RESET_IDLE); 927 break; 928 } 929 930 return (reset_state); 931 } 932 933 static uint_t 934 mouse8042_intr(caddr_t arg) 935 { 936 unsigned char mdata; 937 mblk_t *mp; 938 struct mouse_state *state = (struct mouse_state *)arg; 939 int rc; 940 941 mutex_enter(&state->ms_mutex); 942 943 rc = DDI_INTR_UNCLAIMED; 944 945 for (;;) { 946 947 if (ddi_get8(state->ms_handle, 948 state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) { 949 break; 950 } 951 952 mdata = ddi_get8(state->ms_handle, 953 state->ms_addr + I8042_INT_INPUT_DATA); 954 955 rc = DDI_INTR_CLAIMED; 956 957 /* 958 * If we're not ready for this data, discard it. 959 */ 960 if (!state->ready) 961 continue; 962 963 mutex_enter(&state->reset_mutex); 964 if (state->reset_state != MSE_RESET_IDLE) { 965 966 if (mdata == MSEERROR || mdata == MSERESET) { 967 state->reset_state = MSE_RESET_FAILED; 968 } else { 969 state->reset_state = 970 mouse8042_reset_fsm(state->reset_state, 971 mdata); 972 } 973 974 if (state->reset_state == MSE_RESET_ACK) { 975 976 /* 977 * We received an ACK from the mouse, so 978 * send it upstream immediately so that 979 * consumers depending on the immediate 980 * ACK don't time out. 981 */ 982 if (state->reset_ack_mp != NULL) { 983 984 mp = state->reset_ack_mp; 985 986 state->reset_ack_mp = NULL; 987 988 if (state->ms_rqp != NULL) { 989 *mp->b_wptr++ = MSE_ACK; 990 putnext(state->ms_rqp, mp); 991 } else 992 freemsg(mp); 993 } 994 995 if (state->ms_wqp != NULL) { 996 enableok(state->ms_wqp); 997 qenable(state->ms_wqp); 998 } 999 1000 } else if (state->reset_state == MSE_RESET_IDLE || 1001 state->reset_state == MSE_RESET_FAILED) { 1002 1003 /* 1004 * If we transitioned back to the idle reset state (or 1005 * the reset failed), disable the timeout, release the 1006 * 8042 exclusive-access lock, then send the response 1007 * the the upper-level modules. Finally, enable the 1008 * queue and schedule queue service procedures so that 1009 * upper-level modules can process the response. 1010 * Otherwise, if we're still in the middle of the 1011 * reset sequence, do not send the data up (since the 1012 * response is sent at the end of the sequence, or 1013 * on timeout/error). 1014 */ 1015 1016 mutex_exit(&state->reset_mutex); 1017 (void) quntimeout(state->ms_wqp, 1018 state->reset_tid); 1019 mutex_enter(&state->reset_mutex); 1020 1021 (void) ddi_get8(state->ms_handle, 1022 state->ms_addr + I8042_UNLOCK); 1023 1024 state->reset_tid = 0; 1025 if (state->reply_mp != NULL) { 1026 mp = state->reply_mp; 1027 if (state->reset_state == 1028 MSE_RESET_FAILED) { 1029 *mp->b_wptr++ = mdata; 1030 } else { 1031 *mp->b_wptr++ = MSE_AA; 1032 *mp->b_wptr++ = MSE_00; 1033 } 1034 state->reply_mp = NULL; 1035 } else { 1036 mp = NULL; 1037 } 1038 1039 state->reset_state = MSE_RESET_IDLE; 1040 cv_signal(&state->reset_cv); 1041 1042 if (mp != NULL) { 1043 if (state->ms_rqp != NULL) 1044 putnext(state->ms_rqp, mp); 1045 else 1046 freemsg(mp); 1047 } 1048 1049 if (state->ms_wqp != NULL) { 1050 enableok(state->ms_wqp); 1051 qenable(state->ms_wqp); 1052 } 1053 } 1054 1055 mutex_exit(&state->reset_mutex); 1056 mutex_exit(&state->ms_mutex); 1057 return (rc); 1058 } 1059 mutex_exit(&state->reset_mutex); 1060 1061 if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) { 1062 *mp->b_wptr++ = mdata; 1063 putnext(state->ms_rqp, mp); 1064 } 1065 } 1066 mutex_exit(&state->ms_mutex); 1067 1068 return (rc); 1069 }