1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/ddi.h> 28 #include <sys/inline.h> 29 #include <sys/conf.h> 30 #include <sys/sunddi.h> 31 #include <sys/sunndi.h> 32 #include <sys/i8042.h> 33 #include <sys/kmem.h> 34 #include <sys/promif.h> /* for prom_printf */ 35 #include <sys/note.h> 36 37 /* 38 * Note: For x86, this driver is used to create keyboard/mouse nodes when 39 * booting with ACPI enumeration turned off (acpi-enum=off). 40 */ 41 42 /* 43 * Unfortunately, soft interrupts are implemented poorly. Each additional 44 * soft interrupt user impacts the performance of all existing soft interrupt 45 * users. This is not the case on SPARC, however. 46 */ 47 #ifdef __sparc 48 #define USE_SOFT_INTRS 49 #else 50 #undef USE_SOFT_INTRS 51 #endif 52 53 /* 54 * The command bytes are different for x86 and for SPARC because on x86, 55 * all modern 8042s can properly translate scan code set 2 codes to 56 * scan code set 1. On SPARC systems that have 8042s (e.g. Tadpole laptops), 57 * setting the "translation" bit in the command byte has no effect. 58 * This is potentially dangerous if, in the future, new SPARC systems uses 8042s 59 * that implement the scan code translation when the translation bit is set. 60 * 61 * On SPARC, kb8042 will attempt to detect which scan code set the keyboard 62 * is using. In order for that code to work, the real scan code set must be the 63 * set that is returned by the keyboard (and not a different set that is 64 * translated by the 8042). (e.g. If the translation bit were enabled here, 65 * and the keyboard returned scan code set 2 when kb8042 queried it, kb8042 66 * would not be able to know with certainty that the scan codes it will receive 67 * are set 2 scancodes, or set 1 translations made by the 8042). 68 */ 69 70 /* 71 * 8042 Command Byte Layout: 72 * 73 * 0x80: 0 = Reserved, must be zero. 74 * 0x40: 1 = Translate to XT codes. (0=No translation) 75 * 0x20: 1 = Disable aux (mouse) port. (0=Enable port) 76 * 0x10: 1 = Disable main (keyboard) port. (0=Enable port) 77 * 0x08: 0 = Reserved, must be zero. 78 * 0x04: 1 = System flag, 1 means passed self-test. 79 * Caution: setting this bit to zero causes some 80 * systems (HP Kayak XA) to fail to reboot without 81 * a hard reset. 82 * 0x02: 0 = Disable aux port interrupts. (1=Enable aux port interrupts) 83 * 0x01: 0 = Disable main port interrupts. (1=Enable main port interrupts) 84 * 85 */ 86 #if defined(__sparc) 87 #define I8042_CMD_DISABLE_ALL 0x34 88 #define I8042_CMD_ENABLE_ALL 0x07 89 #elif defined(__i386) || defined(__amd64) 90 #define I8042_CMD_DISABLE_ALL 0x74 91 #define I8042_CMD_ENABLE_ALL 0x47 92 #endif 93 94 #define BUFSIZ 64 95 96 /* 97 * Child nodes, used to determine which to create at bus_config time 98 */ 99 #define I8042_KEYBOARD 2 100 #define I8042_MOUSE 1 101 102 enum i8042_ports { 103 MAIN_PORT = 0, 104 AUX_PORT 105 }; 106 107 #define NUM_PORTS 2 108 109 /* 110 * Only register at most MAX_INTERRUPTS interrupt handlers, 111 * regardless of the number of interrupts in the prom node. 112 * This is important, as registering for all interrupts on 113 * some systems (e.g. Tadpole laptops) results in a flood 114 * of spurious interrupts (for Tadpole, the first 2 interrupts 115 * are for the keyboard and mouse, respectively, and the 116 * third is for a proprietary device that is also accessed 117 * via the same I/O addresses.) 118 */ 119 #define MAX_INTERRUPTS 2 120 121 /* 122 * One of these for each port - main (keyboard) and aux (mouse). 123 */ 124 struct i8042_port { 125 boolean_t initialized; 126 dev_info_t *dip; 127 int inumber; 128 enum i8042_ports which; /* main or aux port */ 129 #if defined(USE_SOFT_INTRS) 130 ddi_softint_handle_t soft_hdl; 131 boolean_t soft_intr_enabled; 132 #else 133 kmutex_t intr_mutex; 134 #endif 135 uint_t (*intr_func)(caddr_t arg1, caddr_t arg2); 136 caddr_t intr_arg1; 137 caddr_t intr_arg2; 138 struct i8042 *i8042_global; 139 /* 140 * wptr is next byte to write 141 */ 142 int wptr; 143 /* 144 * rptr is next byte to read, == wptr means empty 145 * NB: At full, one byte is unused. 146 */ 147 int rptr; 148 int overruns; 149 unsigned char buf[BUFSIZ]; 150 151 /* 152 * Used during i8042_rep_put8 to intercept the 8042 response in 153 * i8042_intr() 154 */ 155 boolean_t intercept_complete; 156 boolean_t intr_intercept_enabled; 157 uint8_t intercept[2]; 158 uint8_t intercepted_byte; 159 kcondvar_t intercept_cv; 160 kmutex_t intercept_mutex; 161 }; 162 163 /* 164 * Describes entire 8042 device. 165 */ 166 struct i8042 { 167 dev_info_t *dip; 168 struct i8042_port i8042_ports[NUM_PORTS]; 169 kmutex_t i8042_mutex; 170 kmutex_t i8042_out_mutex; 171 boolean_t initialized; 172 ddi_acc_handle_t io_handle; 173 uint8_t *io_addr; 174 int nintrs; 175 ddi_iblock_cookie_t *iblock_cookies; 176 uint_t init_state; 177 /* Initialization states: */ 178 #define I8042_INIT_BASIC 0x00000001 179 #define I8042_INIT_REGS_MAPPED 0x00000002 180 #define I8042_INIT_MUTEXES 0x00000004 181 #define I8042_INIT_INTRS_ENABLED 0x00000010 182 uint_t intrs_added; 183 #ifdef __sparc 184 timeout_id_t timeout_id; 185 #endif 186 #ifdef DEBUG 187 /* 188 * intr_thread is set to curthread in i8042_intr and is 189 * tested against curthread in i8402_rep_put8(). 190 */ 191 kthread_t *intr_thread; 192 #endif 193 ddi_softint_handle_t intercept_sih; 194 }; 195 196 /* 197 * i8042 hardware register definitions 198 */ 199 200 /* 201 * These are I/O registers, relative to the device's base (normally 0x60). 202 */ 203 #define I8042_DATA 0x00 /* read/write data here */ 204 #define I8042_STAT 0x04 /* read status here */ 205 #define I8042_CMD 0x04 /* write commands here */ 206 207 /* 208 * These are bits in I8042_STAT. 209 */ 210 #define I8042_STAT_OUTBF 0x01 /* Output (to host) buffer full */ 211 #define I8042_STAT_INBF 0x02 /* Input (from host) buffer full */ 212 #define I8042_STAT_AUXBF 0x20 /* Output buffer data is from aux */ 213 214 /* 215 * These are commands to the i8042 itself (as distinct from the devices 216 * attached to it). 217 */ 218 #define I8042_CMD_RCB 0x20 /* Read command byte (we don't use) */ 219 #define I8042_CMD_WCB 0x60 /* Write command byte */ 220 #define I8042_CMD_WRITE_AUX 0xD4 /* Send next data byte to aux port */ 221 222 /* 223 * Maximum number of times to loop while clearing pending data from the 224 * keyboard controller. 225 */ 226 #define MAX_JUNK_ITERATIONS 1000 227 228 /* 229 * Maximum time to wait for the keyboard to become ready to accept data 230 * (maximum time = MAX_WAIT_ITERATIONS * USECS_PER_WAIT (default is 250ms)) 231 */ 232 #define MAX_WAIT_ITERATIONS 25000 233 #define USECS_PER_WAIT 10 234 235 236 #ifdef __sparc 237 238 #define PLATFORM_MATCH(s) (strncmp(ddi_get_name(ddi_root_node()), \ 239 (s), strlen(s)) == 0) 240 241 /* 242 * On some older SPARC platforms that have problems with the 243 * interrupt line attached to the PS/2 keyboard/mouse, it 244 * may be necessary to change the operating mode of the nexus 245 * to a polling-based (instead of interrupt-based) method. 246 * this variable is present to enable a worst-case workaround so 247 * owners of these systems can still retain a working keyboard. 248 * 249 * The `i8042_polled_mode' variable can be used to force polled 250 * mode for platforms that have this issue, but for which 251 * automatic relief is not implemented. 252 * 253 * In the off chance that one of the platforms is misidentified 254 * as requiried polling mode, `i8042_force_interrupt_mode' can 255 * be set to force the nexus to use interrupts. 256 */ 257 #define I8042_MIN_POLL_INTERVAL 1000 /* usecs */ 258 int i8042_poll_interval = 8000; /* usecs */ 259 int i8042_fast_poll_interval; /* usecs */ 260 int i8042_slow_poll_interval; /* usecs */ 261 262 boolean_t i8042_polled_mode = B_FALSE; 263 boolean_t i8042_force_interrupt_mode = B_FALSE; 264 #endif /* __sparc */ 265 266 int max_wait_iterations = MAX_WAIT_ITERATIONS; 267 268 #ifdef DEBUG 269 int i8042_debug = 0; 270 #endif 271 272 /* 273 * function prototypes for bus ops routines: 274 */ 275 static int i8042_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 276 off_t offset, off_t len, caddr_t *addrp); 277 static int i8042_ctlops(dev_info_t *dip, dev_info_t *rdip, 278 ddi_ctl_enum_t op, void *arg, void *result); 279 280 /* 281 * function prototypes for dev ops routines: 282 */ 283 static int i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 284 static int i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 285 static int i8042_intr_ops(dev_info_t *dip, dev_info_t *rdip, 286 ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result); 287 static int i8042_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, 288 void *, dev_info_t **); 289 static int i8042_bus_unconfig(dev_info_t *, uint_t, 290 ddi_bus_config_op_t, void *); 291 #ifdef __sparc 292 static int i8042_build_interrupts_property(dev_info_t *dip); 293 static boolean_t i8042_is_polling_platform(void); 294 #endif 295 296 /* 297 * bus ops and dev ops structures: 298 */ 299 static struct bus_ops i8042_bus_ops = { 300 BUSO_REV, 301 i8042_map, 302 NULL, 303 NULL, 304 NULL, 305 NULL, /* ddi_map_fault */ 306 NULL, /* ddi_dma_map */ 307 NULL, /* ddi_dma_allochdl */ 308 NULL, /* ddi_dma_freehdl */ 309 NULL, /* ddi_dma_bindhdl */ 310 NULL, /* ddi_dma_unbindhdl */ 311 NULL, /* ddi_dma_flush */ 312 NULL, /* ddi_dma_win */ 313 NULL, /* ddi_dma_mctl */ 314 i8042_ctlops, 315 ddi_bus_prop_op, 316 NULL, /* (*bus_get_eventcookie)(); */ 317 NULL, /* (*bus_add_eventcall)(); */ 318 NULL, /* (*bus_remove_eventcall)(); */ 319 NULL, /* (*bus_post_event)(); */ 320 NULL, /* bus_intr_ctl */ 321 i8042_bus_config, /* bus_config */ 322 i8042_bus_unconfig, /* bus_unconfig */ 323 NULL, /* bus_fm_init */ 324 NULL, /* bus_fm_fini */ 325 NULL, /* bus_fm_access_enter */ 326 NULL, /* bus_fm_access_exit */ 327 NULL, /* bus_power */ 328 i8042_intr_ops /* bus_intr_op */ 329 }; 330 331 static struct dev_ops i8042_ops = { 332 DEVO_REV, 333 0, 334 ddi_no_info, 335 nulldev, 336 0, 337 i8042_attach, 338 i8042_detach, 339 nodev, 340 (struct cb_ops *)0, 341 &i8042_bus_ops, 342 NULL, 343 ddi_quiesce_not_needed, 344 }; 345 346 347 /* 348 * module definitions: 349 */ 350 #include <sys/modctl.h> 351 extern struct mod_ops mod_driverops; 352 353 static struct modldrv modldrv = { 354 &mod_driverops, /* Type of module. This one is a driver */ 355 "i8042 nexus driver", /* Name of module. */ 356 &i8042_ops, /* driver ops */ 357 }; 358 359 static struct modlinkage modlinkage = { 360 MODREV_1, (void *)&modldrv, NULL 361 }; 362 363 int 364 _init(void) 365 { 366 int e; 367 368 /* 369 * Install the module. 370 */ 371 e = mod_install(&modlinkage); 372 return (e); 373 } 374 375 int 376 _fini(void) 377 { 378 int e; 379 380 /* 381 * Remove the module. 382 */ 383 e = mod_remove(&modlinkage); 384 if (e != 0) 385 return (e); 386 387 return (e); 388 } 389 390 int 391 _info(struct modinfo *modinfop) 392 { 393 return (mod_info(&modlinkage, modinfop)); 394 } 395 396 #define DRIVER_NAME(dip) ddi_driver_name(dip) 397 398 static void i8042_timeout(void *arg); 399 static unsigned int i8042_intr(caddr_t arg); 400 static void i8042_write_command_byte(struct i8042 *, unsigned char); 401 static uint8_t i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr); 402 static void i8042_put8(ddi_acc_impl_t *handlep, uint8_t *addr, 403 uint8_t value); 404 static void i8042_put8_nolock(ddi_acc_impl_t *handlep, uint8_t *addr, 405 uint8_t value); 406 static void i8042_rep_put8(ddi_acc_impl_t *handlep, uint8_t *haddr, 407 uint8_t *daddr, size_t repcount, uint_t flags); 408 static void i8042_send(struct i8042 *global, int reg, unsigned char cmd); 409 static uint_t i8042_intercept_softint(caddr_t arg1, caddr_t arg2); 410 411 unsigned int i8042_unclaimed_interrupts = 0; 412 413 static void 414 i8042_discard_junk_data(struct i8042 *global) 415 { 416 /* Discard any junk data that may have been left around */ 417 for (;;) { 418 unsigned char stat; 419 420 stat = ddi_get8(global->io_handle, 421 global->io_addr + I8042_STAT); 422 if (! (stat & I8042_STAT_OUTBF)) 423 break; 424 (void) ddi_get8(global->io_handle, 425 global->io_addr + I8042_DATA); 426 427 } 428 } 429 430 static int 431 i8042_cleanup(struct i8042 *global) 432 { 433 int which_port, i; 434 struct i8042_port *port; 435 436 ASSERT(global != NULL); 437 438 if (global->initialized == B_TRUE) { 439 /* 440 * If any children still have regs mapped or interrupts 441 * registered, return immediate failure (and do nothing). 442 */ 443 mutex_enter(&global->i8042_mutex); 444 445 for (which_port = 0; which_port < NUM_PORTS; which_port++) { 446 port = &global->i8042_ports[which_port]; 447 448 if (port->initialized == B_TRUE) { 449 mutex_exit(&global->i8042_mutex); 450 return (DDI_FAILURE); 451 } 452 #if defined(USE_SOFT_INTRS) 453 if (port->soft_hdl != 0) { 454 mutex_exit(&global->i8042_mutex); 455 return (DDI_FAILURE); 456 } 457 #else 458 mutex_enter(&port->intr_mutex); 459 if (port->intr_func != NULL) { 460 mutex_exit(&port->intr_mutex); 461 mutex_exit(&global->i8042_mutex); 462 return (DDI_FAILURE); 463 } 464 mutex_exit(&port->intr_mutex); 465 #endif 466 } 467 global->initialized = B_FALSE; 468 469 mutex_exit(&global->i8042_mutex); 470 } 471 472 #ifdef __sparc 473 /* If there may be an outstanding timeout, cancel it */ 474 if (global->timeout_id != 0) { 475 (void) untimeout(global->timeout_id); 476 } 477 #endif 478 479 /* Stop the controller from generating interrupts */ 480 if (global->init_state & I8042_INIT_INTRS_ENABLED) 481 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL); 482 483 if (global->intrs_added) { 484 /* 485 * Remove the interrupts in the reverse order in 486 * which they were added 487 */ 488 for (i = global->nintrs - 1; i >= 0; i--) { 489 if (global->intrs_added & (1 << i)) 490 ddi_remove_intr(global->dip, i, 491 global->iblock_cookies[i]); 492 } 493 } 494 495 (void) ddi_intr_remove_softint(global->intercept_sih); 496 497 498 if (global->init_state & I8042_INIT_MUTEXES) { 499 for (which_port = 0; which_port < NUM_PORTS; which_port++) { 500 #ifndef USE_SOFT_INTRS 501 port = &global->i8042_ports[which_port]; 502 mutex_destroy(&port->intr_mutex); 503 #endif 504 mutex_destroy(&port->intercept_mutex); 505 cv_destroy(&port->intercept_cv); 506 } 507 mutex_destroy(&global->i8042_out_mutex); 508 mutex_destroy(&global->i8042_mutex); 509 } 510 511 if (global->init_state & I8042_INIT_REGS_MAPPED) 512 ddi_regs_map_free(&global->io_handle); 513 514 if (global->init_state & I8042_INIT_BASIC) { 515 ddi_set_driver_private(global->dip, (caddr_t)NULL); 516 if (global->nintrs > 0) { 517 kmem_free(global->iblock_cookies, global->nintrs * 518 sizeof (ddi_iblock_cookie_t)); 519 } 520 kmem_free(global, sizeof (struct i8042)); 521 } 522 523 return (DDI_SUCCESS); 524 } 525 526 #define OBF_WAIT_COUNT 1000 /* in granules of 10uS */ 527 528 /* 529 * Wait for the 8042 to fill the 'output' (from 8042 to host) 530 * buffer. If 8042 fails to fill the output buffer within an 531 * allowed time, return 1 (which means there is no data available), 532 * otherwise return 0 533 */ 534 static int 535 i8042_wait_obf(struct i8042 *global) 536 { 537 int timer = 0; 538 539 while (!(ddi_get8(global->io_handle, global->io_addr + I8042_STAT) & 540 I8042_STAT_OUTBF)) { 541 if (++timer > OBF_WAIT_COUNT) 542 return (1); 543 drv_usecwait(10); 544 } 545 return (0); 546 } 547 548 /* 549 * Drain all queued bytes from the 8042. 550 * Return 0 for no error, <> 0 if there was an error. 551 */ 552 static int 553 i8042_purge_outbuf(struct i8042 *global) 554 { 555 int i; 556 557 for (i = 0; i < MAX_JUNK_ITERATIONS; i++) { 558 if (i8042_wait_obf(global)) 559 break; 560 (void) ddi_get8(global->io_handle, 561 global->io_addr + I8042_DATA); 562 } 563 564 /* 565 * If we hit the maximum number of iterations, then there 566 * was a serious problem (e.g. our hardware may not be 567 * present or working properly). 568 */ 569 return (i == MAX_JUNK_ITERATIONS); 570 } 571 572 static int 573 i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 574 { 575 struct i8042_port *port; 576 enum i8042_ports which_port; 577 int i; 578 #if !defined(USE_SOFT_INTRS) 579 ddi_iblock_cookie_t cookie; 580 #endif 581 static ddi_device_acc_attr_t attr = { 582 DDI_DEVICE_ATTR_V0, 583 DDI_NEVERSWAP_ACC, 584 DDI_STRICTORDER_ACC, 585 }; 586 struct i8042 *global; 587 #ifdef __sparc 588 int interval; 589 #endif 590 591 switch (cmd) { 592 case DDI_RESUME: 593 global = (struct i8042 *)ddi_get_driver_private(dip); 594 i8042_discard_junk_data(global); 595 i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL); 596 return (DDI_SUCCESS); 597 598 case DDI_ATTACH: 599 /* Handled in the main function block */ 600 break; 601 602 default: 603 return (DDI_FAILURE); 604 } 605 606 /* 607 * DDI_ATTACH processing 608 */ 609 610 global = (struct i8042 *)kmem_zalloc(sizeof (struct i8042), KM_SLEEP); 611 ddi_set_driver_private(dip, (caddr_t)global); 612 global->dip = dip; 613 global->initialized = B_FALSE; 614 615 global->init_state |= I8042_INIT_BASIC; 616 617 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&global->io_addr, 618 (offset_t)0, (offset_t)0, &attr, &global->io_handle) 619 != DDI_SUCCESS) 620 goto fail; 621 622 global->init_state |= I8042_INIT_REGS_MAPPED; 623 624 /* 625 * Get the number of interrupts for this nexus 626 */ 627 if (ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE) 628 goto fail; 629 630 #ifdef __sparc 631 if ((i8042_polled_mode || i8042_is_polling_platform()) && 632 !i8042_force_interrupt_mode) { 633 /* 634 * If we're on a platform that has known 635 * interrupt issues with the keyboard/mouse, 636 * use polled mode. 637 */ 638 i8042_polled_mode = B_TRUE; 639 global->nintrs = 0; 640 } else if (global->nintrs == 0) { 641 /* 642 * If there are no interrupts on the i8042 node, 643 * we may be on a brain-dead platform that only 644 * has interrupts properties on i8042's children 645 * (e.g. some UltraII-based boards) 646 * In this case, scan first-level children, and 647 * build a list of interrupts that each child uses, 648 * then create an `interrupts' property on the nexus node 649 * that contains the interrupts used by all children 650 */ 651 if (i8042_build_interrupts_property(dip) == DDI_FAILURE || 652 ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE || 653 global->nintrs == 0) { 654 cmn_err(CE_WARN, "i8042#%d: No interrupts defined!", 655 ddi_get_instance(global->dip)); 656 goto fail; 657 } 658 } 659 #else 660 if (global->nintrs == 0) { 661 cmn_err(CE_WARN, "i8042#%d: No interrupts defined!", 662 ddi_get_instance(global->dip)); 663 goto fail; 664 } 665 #endif 666 667 if (global->nintrs > MAX_INTERRUPTS) 668 global->nintrs = MAX_INTERRUPTS; 669 670 if (global->nintrs > 0) { 671 global->iblock_cookies = kmem_zalloc(global->nintrs * 672 sizeof (ddi_iblock_cookie_t), KM_NOSLEEP); 673 674 for (i = 0; i < global->nintrs; i++) { 675 if (ddi_get_iblock_cookie(dip, i, 676 &global->iblock_cookies[i]) != DDI_SUCCESS) 677 goto fail; 678 } 679 } else 680 global->iblock_cookies = NULL; 681 682 mutex_init(&global->i8042_mutex, NULL, MUTEX_DRIVER, 683 (global->nintrs > 0) ? global->iblock_cookies[0] : NULL); 684 685 mutex_init(&global->i8042_out_mutex, NULL, MUTEX_DRIVER, NULL); 686 687 for (which_port = 0; which_port < NUM_PORTS; ++which_port) { 688 port = &global->i8042_ports[which_port]; 689 port->initialized = B_FALSE; 690 port->i8042_global = global; 691 port->which = which_port; 692 port->intr_intercept_enabled = B_FALSE; 693 cv_init(&port->intercept_cv, NULL, CV_DRIVER, NULL); 694 #if defined(USE_SOFT_INTRS) 695 port->soft_hdl = 0; 696 #else 697 698 mutex_init(&port->intercept_mutex, NULL, MUTEX_DRIVER, 699 (void *)DDI_INTR_SOFTPRI_DEFAULT); 700 701 /* 702 * Assume that the interrupt block cookie for port <n> 703 * is iblock_cookies[<n>] (a 1:1 mapping). If there are not 704 * enough interrupts to cover the number of ports, use 705 * the cookie from interrupt 0. 706 */ 707 if (global->nintrs > 0) { 708 cookie = global->iblock_cookies[ 709 (which_port < global->nintrs) ? which_port : 0]; 710 711 mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER, 712 cookie); 713 714 } else { 715 mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER, NULL); 716 mutex_init(&port->intercept_mutex, NULL, MUTEX_DRIVER, 717 NULL); 718 } 719 720 #endif 721 } 722 723 global->init_state |= I8042_INIT_MUTEXES; 724 725 /* 726 * Disable input and interrupts from both the main and aux ports. 727 * 728 * It is difficult if not impossible to read the command byte in 729 * a completely clean way. Reading the command byte may cause 730 * an interrupt, and there is no way to suppress interrupts without 731 * writing the command byte. On a PC we might rely on the fact 732 * that IRQ 1 is disabled and guaranteed not shared, but on 733 * other platforms the interrupt line might be shared and so 734 * causing an interrupt could be bad. 735 * 736 * Since we can't read the command byte and update it, we 737 * just set it to static values. 738 */ 739 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL); 740 741 global->init_state &= ~I8042_INIT_INTRS_ENABLED; 742 743 /* Discard any junk data that may have been left around */ 744 if (i8042_purge_outbuf(global) != 0) 745 goto fail; 746 747 748 if (ddi_intr_add_softint(dip, &global->intercept_sih, 749 DDI_INTR_SOFTPRI_DEFAULT, i8042_intercept_softint, global) 750 != DDI_SUCCESS) 751 goto fail; 752 753 /* 754 * Assume the number of interrupts is less that the number of 755 * bits in the variable used to keep track of which interrupt 756 * was added. 757 */ 758 ASSERT(global->nintrs <= (sizeof (global->intrs_added) * NBBY)); 759 760 for (i = 0; i < global->nintrs; i++) { 761 /* 762 * The 8042 handles all interrupts, because all 763 * device access goes through the same I/O addresses. 764 */ 765 if (ddi_add_intr(dip, i, 766 (ddi_iblock_cookie_t *)NULL, 767 (ddi_idevice_cookie_t *)NULL, 768 i8042_intr, (caddr_t)global) != DDI_SUCCESS) 769 goto fail; 770 771 global->intrs_added |= (1 << i); 772 } 773 774 global->initialized = B_TRUE; 775 776 /* 777 * Enable the main and aux data ports and interrupts 778 */ 779 i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL); 780 global->init_state |= I8042_INIT_INTRS_ENABLED; 781 782 #ifdef __sparc 783 if (i8042_polled_mode) { 784 /* 785 * Do not allow anyone to set the polling interval 786 * to an interval more frequent than I8042_MIN_POLL_INTERVAL -- 787 * it could hose the system. 788 */ 789 interval = i8042_poll_interval; 790 if (interval < I8042_MIN_POLL_INTERVAL) 791 interval = I8042_MIN_POLL_INTERVAL; 792 i8042_fast_poll_interval = interval; 793 i8042_slow_poll_interval = interval << 3; 794 795 global->timeout_id = timeout(i8042_timeout, global, 796 drv_usectohz(i8042_slow_poll_interval)); 797 } 798 #endif 799 800 return (DDI_SUCCESS); 801 802 fail: 803 /* cleanup will succeed because no children have attached yet */ 804 (void) i8042_cleanup(global); 805 return (DDI_FAILURE); 806 } 807 808 /*ARGSUSED*/ 809 static int 810 i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 811 { 812 struct i8042 *global = (struct i8042 *)ddi_get_driver_private(dip); 813 814 ASSERT(global != NULL); 815 816 switch (cmd) { 817 case DDI_SUSPEND: 818 /* 819 * Do not disable the keyboard controller for x86 suspend, as 820 * the keyboard can be used to bring the system out of 821 * suspend. 822 */ 823 #ifdef __sparc 824 /* Disable interrupts and controller devices before suspend */ 825 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL); 826 #endif 827 return (DDI_SUCCESS); 828 829 case DDI_DETACH: 830 /* DETACH can only succeed if cleanup succeeds */ 831 return (i8042_cleanup(global)); 832 833 default: 834 return (DDI_FAILURE); 835 } 836 } 837 838 /* 839 * The primary interface to us from our children is via virtual registers. 840 * This is the entry point that allows our children to "map" these 841 * virtual registers. 842 */ 843 static int 844 i8042_map( 845 dev_info_t *dip, 846 dev_info_t *rdip, 847 ddi_map_req_t *mp, 848 off_t offset, 849 off_t len, 850 caddr_t *addrp) 851 { 852 struct i8042_port *port; 853 struct i8042 *global; 854 enum i8042_ports which_port; 855 int *iprop; 856 unsigned int iprop_len; 857 int rnumber; 858 ddi_acc_hdl_t *handle; 859 ddi_acc_impl_t *ap; 860 861 global = ddi_get_driver_private(dip); 862 863 switch (mp->map_type) { 864 case DDI_MT_REGSPEC: 865 which_port = *(int *)mp->map_obj.rp; 866 break; 867 868 case DDI_MT_RNUMBER: 869 rnumber = mp->map_obj.rnumber; 870 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 871 DDI_PROP_DONTPASS, "reg", &iprop, &iprop_len) != 872 DDI_SUCCESS) { 873 #if defined(DEBUG) 874 cmn_err(CE_WARN, "%s #%d: Missing 'reg' on %s@%s", 875 DRIVER_NAME(dip), ddi_get_instance(dip), 876 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 877 #endif 878 return (DDI_FAILURE); 879 } 880 #if defined(DEBUG) 881 if (iprop_len != 1) { 882 cmn_err(CE_WARN, "%s #%d: Malformed 'reg' on %s@%s", 883 DRIVER_NAME(dip), ddi_get_instance(dip), 884 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 885 return (DDI_FAILURE); 886 } 887 if (rnumber < 0 || rnumber >= iprop_len) { 888 cmn_err(CE_WARN, "%s #%d: bad map request for %s@%s", 889 DRIVER_NAME(dip), ddi_get_instance(dip), 890 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 891 return (DDI_FAILURE); 892 } 893 #endif 894 which_port = iprop[rnumber]; 895 ddi_prop_free((void *)iprop); 896 #if defined(DEBUG) 897 if (which_port != MAIN_PORT && which_port != AUX_PORT) { 898 cmn_err(CE_WARN, 899 "%s #%d: bad 'reg' value %d on %s@%s", 900 DRIVER_NAME(dip), ddi_get_instance(dip), 901 which_port, 902 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 903 return (DDI_FAILURE); 904 } 905 #endif 906 break; 907 908 default: 909 #if defined(DEBUG) 910 cmn_err(CE_WARN, "%s #%d: unknown map type %d for %s@%s", 911 DRIVER_NAME(dip), ddi_get_instance(dip), 912 mp->map_type, 913 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 914 #endif 915 return (DDI_FAILURE); 916 } 917 918 #if defined(DEBUG) 919 if (offset != 0 || len != 0) { 920 cmn_err(CE_WARN, 921 "%s #%d: partial mapping attempt for %s@%s ignored", 922 DRIVER_NAME(dip), ddi_get_instance(dip), 923 ddi_node_name(rdip), ddi_get_name_addr(rdip)); 924 } 925 #endif 926 927 port = &global->i8042_ports[which_port]; 928 929 switch (mp->map_op) { 930 case DDI_MO_MAP_LOCKED: 931 #if defined(USE_SOFT_INTRS) 932 port->soft_intr_enabled = B_FALSE; 933 #else 934 port->intr_func = NULL; 935 #endif 936 port->wptr = 0; 937 port->rptr = 0; 938 port->dip = dip; 939 port->inumber = 0; 940 port->initialized = B_TRUE; 941 942 handle = mp->map_handlep; 943 handle->ah_bus_private = port; 944 handle->ah_addr = 0; 945 ap = (ddi_acc_impl_t *)handle->ah_platform_private; 946 /* 947 * Support get8, put8 and _rep_put8 948 */ 949 ap->ahi_put8 = i8042_put8; 950 ap->ahi_get8 = i8042_get8; 951 ap->ahi_put16 = NULL; 952 ap->ahi_get16 = NULL; 953 ap->ahi_put32 = NULL; 954 ap->ahi_get32 = NULL; 955 ap->ahi_put64 = NULL; 956 ap->ahi_get64 = NULL; 957 ap->ahi_rep_put8 = i8042_rep_put8; 958 ap->ahi_rep_get8 = NULL; 959 ap->ahi_rep_put16 = NULL; 960 ap->ahi_rep_get16 = NULL; 961 ap->ahi_rep_put32 = NULL; 962 ap->ahi_rep_get32 = NULL; 963 ap->ahi_rep_put64 = NULL; 964 ap->ahi_rep_get64 = NULL; 965 *addrp = 0; 966 return (DDI_SUCCESS); 967 968 case DDI_MO_UNMAP: 969 port->initialized = B_FALSE; 970 return (DDI_SUCCESS); 971 972 default: 973 cmn_err(CE_WARN, "%s: map operation %d not supported", 974 DRIVER_NAME(dip), mp->map_op); 975 return (DDI_FAILURE); 976 } 977 } 978 979 #ifdef __sparc 980 static void 981 i8042_timeout(void *arg) 982 { 983 struct i8042 *i8042_p = (struct i8042 *)arg; 984 int interval; 985 986 /* 987 * Allow the polling speed to be changed on the fly -- 988 * catch it here and update the intervals used. 989 */ 990 if (i8042_fast_poll_interval != i8042_poll_interval) { 991 interval = i8042_poll_interval; 992 if (interval < I8042_MIN_POLL_INTERVAL) 993 interval = I8042_MIN_POLL_INTERVAL; 994 i8042_fast_poll_interval = interval; 995 i8042_slow_poll_interval = interval << 3; 996 } 997 998 /* 999 * If the ISR returned true, start polling at a faster rate to 1000 * increate responsiveness. Once the keyboard or mouse go idle, 1001 * the ISR will return UNCLAIMED, and we'll go back to the slower 1002 * polling rate. This gives some positive hysteresis (but not 1003 * negative, since we go back to the slower polling interval after 1004 * only one UNCLAIMED). This has shown to be responsive enough, 1005 * even for fast typers. 1006 */ 1007 interval = (i8042_intr((caddr_t)i8042_p) == DDI_INTR_CLAIMED) ? 1008 i8042_fast_poll_interval : i8042_slow_poll_interval; 1009 1010 if (i8042_polled_mode) 1011 i8042_p->timeout_id = timeout(i8042_timeout, arg, 1012 drv_usectohz(interval)); 1013 else 1014 i8042_p->timeout_id = 0; 1015 } 1016 #endif 1017 1018 /* 1019 * i8042 hardware interrupt routine. Called for both main and aux port 1020 * interrupts. 1021 */ 1022 static unsigned int 1023 i8042_intr(caddr_t arg) 1024 { 1025 struct i8042 *global = (struct i8042 *)arg; 1026 enum i8042_ports which_port; 1027 unsigned char stat; 1028 unsigned char byte; 1029 int new_wptr; 1030 struct i8042_port *port; 1031 1032 #ifdef DEBUG 1033 global->intr_thread = curthread; 1034 #endif 1035 mutex_enter(&global->i8042_mutex); 1036 1037 stat = ddi_get8(global->io_handle, global->io_addr + I8042_STAT); 1038 1039 if (! (stat & I8042_STAT_OUTBF)) { 1040 ++i8042_unclaimed_interrupts; 1041 mutex_exit(&global->i8042_mutex); 1042 #ifdef DEBUG 1043 global->intr_thread = NULL; 1044 #endif 1045 return (DDI_INTR_UNCLAIMED); 1046 } 1047 1048 byte = ddi_get8(global->io_handle, global->io_addr + I8042_DATA); 1049 1050 which_port = (stat & I8042_STAT_AUXBF) ? AUX_PORT : MAIN_PORT; 1051 1052 port = &global->i8042_ports[which_port]; 1053 1054 if (! port->initialized) { 1055 mutex_exit(&global->i8042_mutex); 1056 #ifdef DEBUG 1057 global->intr_thread = NULL; 1058 #endif 1059 return (DDI_INTR_CLAIMED); 1060 } 1061 1062 /* 1063 * If interception is enabled, and the byte matches what is being 1064 * waited for, clear the interception flag and trigger a softintr 1065 * that will signal the waiter, then exit the interrupt handler 1066 * without passing the byte to the child's interrupt handler. 1067 */ 1068 if (port->intr_intercept_enabled && (port->intercept[0] == byte || 1069 port->intercept[1] == byte)) { 1070 port->intercepted_byte = byte; 1071 port->intr_intercept_enabled = B_FALSE; 1072 (void) ddi_intr_trigger_softint(global->intercept_sih, port); 1073 mutex_exit(&global->i8042_mutex); 1074 #ifdef DEBUG 1075 global->intr_thread = NULL; 1076 #endif 1077 return (DDI_INTR_CLAIMED); 1078 } 1079 1080 new_wptr = (port->wptr + 1) % BUFSIZ; 1081 if (new_wptr == port->rptr) { 1082 port->overruns++; 1083 #if defined(DEBUG) 1084 if (port->overruns % 50 == 1) { 1085 cmn_err(CE_WARN, "i8042/%d: %d overruns\n", 1086 which_port, port->overruns); 1087 } 1088 #endif 1089 1090 mutex_exit(&global->i8042_mutex); 1091 1092 #ifdef DEBUG 1093 global->intr_thread = NULL; 1094 #endif 1095 return (DDI_INTR_CLAIMED); 1096 } 1097 1098 port->buf[port->wptr] = byte; 1099 port->wptr = new_wptr; 1100 1101 #if defined(USE_SOFT_INTRS) 1102 if (port->soft_intr_enabled) 1103 (void) ddi_intr_trigger_softint(port->soft_hdl, 1104 port->intr_arg2); 1105 #endif 1106 1107 mutex_exit(&global->i8042_mutex); 1108 1109 #if !defined(USE_SOFT_INTRS) 1110 mutex_enter(&port->intr_mutex); 1111 if (port->intr_func != NULL) 1112 port->intr_func(port->intr_arg1, NULL); 1113