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 } 1071