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 2009 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          * has_glock is 1 if this child has the [put8] exclusive-access lock.
 152          */
 153         volatile boolean_t      has_glock;
 154 };
 155 
 156 /*
 157  * Describes entire 8042 device.
 158  */
 159 struct i8042 {
 160         dev_info_t              *dip;
 161         struct i8042_port       i8042_ports[NUM_PORTS];
 162         kmutex_t                i8042_mutex;
 163         kmutex_t                i8042_out_mutex;
 164         boolean_t               initialized;
 165         ddi_acc_handle_t        io_handle;
 166         uint8_t                 *io_addr;
 167         int                     nintrs;
 168         ddi_iblock_cookie_t     *iblock_cookies;
 169         uint_t                  init_state;
 170 /* Initialization states: */
 171 #define I8042_INIT_BASIC                0x00000001
 172 #define I8042_INIT_REGS_MAPPED          0x00000002
 173 #define I8042_INIT_MUTEXES              0x00000004
 174 #define I8042_INIT_INTRS_ENABLED        0x00000010
 175         uint_t                  intrs_added;
 176 #ifdef __sparc
 177         timeout_id_t            timeout_id;
 178 #endif
 179         /*
 180          * glock is 1 if any child has the [put8] exclusive-access lock
 181          * glock_cv is associated with the condition `glock == 0'
 182          */
 183         volatile int            glock;
 184         /*
 185          * Callers awaiting exclusive access in i8042_put8 sleep on glock_cv
 186          * and are signaled when another child relinquishes exclusive access.
 187          */
 188         kcondvar_t              glock_cv;
 189 };
 190 
 191 /*
 192  * i8042 hardware register definitions
 193  */
 194 
 195 /*
 196  * These are I/O registers, relative to the device's base (normally 0x60).
 197  */
 198 #define I8042_DATA      0x00    /* read/write data here */
 199 #define I8042_STAT      0x04    /* read status here */
 200 #define I8042_CMD       0x04    /* write commands here */
 201 
 202 /*
 203  * These are bits in I8042_STAT.
 204  */
 205 #define I8042_STAT_OUTBF        0x01    /* Output (to host) buffer full */
 206 #define I8042_STAT_INBF         0x02    /* Input (from host) buffer full */
 207 #define I8042_STAT_AUXBF        0x20    /* Output buffer data is from aux */
 208 
 209 /*
 210  * These are commands to the i8042 itself (as distinct from the devices
 211  * attached to it).
 212  */
 213 #define I8042_CMD_RCB           0x20    /* Read command byte (we don't use) */
 214 #define I8042_CMD_WCB           0x60    /* Write command byte */
 215 #define I8042_CMD_WRITE_AUX     0xD4    /* Send next data byte to aux port */
 216 
 217 /*
 218  * Maximum number of times to loop while clearing pending data from the
 219  * keyboard controller.
 220  */
 221 #define MAX_JUNK_ITERATIONS     1000
 222 
 223 /*
 224  * Maximum time to wait for the keyboard to become ready to accept data
 225  * (maximum time = MAX_WAIT_ITERATIONS * USECS_PER_WAIT (default is 250ms))
 226  */
 227 #define MAX_WAIT_ITERATIONS     25000
 228 #define USECS_PER_WAIT          10
 229 
 230 
 231 #ifdef __sparc
 232 
 233 #define PLATFORM_MATCH(s) (strncmp(ddi_get_name(ddi_root_node()), \
 234         (s), strlen(s)) == 0)
 235 
 236 /*
 237  * On some older SPARC platforms that have problems with the
 238  * interrupt line attached to the PS/2 keyboard/mouse, it
 239  * may be necessary to change the operating mode of the nexus
 240  * to a polling-based (instead of interrupt-based) method.
 241  * this variable is present to enable a worst-case workaround so
 242  * owners of these systems can still retain a working keyboard.
 243  *
 244  * The `i8042_polled_mode' variable can be used to force polled
 245  * mode for platforms that have this issue, but for which
 246  * automatic relief is not implemented.
 247  *
 248  * In the off chance that one of the platforms is misidentified
 249  * as requiried polling mode, `i8042_force_interrupt_mode' can
 250  * be set to force the nexus to use interrupts.
 251  */
 252 #define I8042_MIN_POLL_INTERVAL 1000    /* usecs */
 253 int i8042_poll_interval = 8000;         /* usecs */
 254 int i8042_fast_poll_interval;           /* usecs */
 255 int i8042_slow_poll_interval;           /* usecs */
 256 
 257 boolean_t i8042_polled_mode = B_FALSE;
 258 boolean_t i8042_force_interrupt_mode = B_FALSE;
 259 #endif /* __sparc */
 260 
 261 int max_wait_iterations = MAX_WAIT_ITERATIONS;
 262 
 263 #ifdef DEBUG
 264 int i8042_debug = 0;
 265 #endif
 266 
 267 /*
 268  * function prototypes for bus ops routines:
 269  */
 270 static int i8042_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
 271         off_t offset, off_t len, caddr_t *addrp);
 272 static int i8042_ctlops(dev_info_t *dip, dev_info_t *rdip,
 273         ddi_ctl_enum_t op, void *arg, void *result);
 274 
 275 /*
 276  * function prototypes for dev ops routines:
 277  */
 278 static int i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 279 static int i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
 280 static  int i8042_intr_ops(dev_info_t *dip, dev_info_t *rdip,
 281         ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
 282 static int i8042_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
 283     void *, dev_info_t **);
 284 static int i8042_bus_unconfig(dev_info_t *, uint_t,
 285     ddi_bus_config_op_t, void *);
 286 #ifdef __sparc
 287 static int i8042_build_interrupts_property(dev_info_t *dip);
 288 static boolean_t i8042_is_polling_platform(void);
 289 #endif
 290 
 291 /*
 292  * bus ops and dev ops structures:
 293  */
 294 static struct bus_ops i8042_bus_ops = {
 295         BUSO_REV,
 296         i8042_map,
 297         NULL,
 298         NULL,
 299         NULL,
 300         NULL,           /* ddi_map_fault */
 301         NULL,           /* ddi_dma_map */
 302         NULL,           /* ddi_dma_allochdl */
 303         NULL,           /* ddi_dma_freehdl */
 304         NULL,           /* ddi_dma_bindhdl */
 305         NULL,           /* ddi_dma_unbindhdl */
 306         NULL,           /* ddi_dma_flush */
 307         NULL,           /* ddi_dma_win */
 308         NULL,           /* ddi_dma_mctl */
 309         i8042_ctlops,
 310         ddi_bus_prop_op,
 311         NULL,                   /* (*bus_get_eventcookie)();    */
 312         NULL,                   /* (*bus_add_eventcall)();      */
 313         NULL,                   /* (*bus_remove_eventcall)();   */
 314         NULL,                   /* (*bus_post_event)();         */
 315         NULL,                   /* bus_intr_ctl */
 316         i8042_bus_config,       /* bus_config */
 317         i8042_bus_unconfig,     /* bus_unconfig */
 318         NULL,                   /* bus_fm_init */
 319         NULL,                   /* bus_fm_fini */
 320         NULL,                   /* bus_fm_access_enter */
 321         NULL,                   /* bus_fm_access_exit */
 322         NULL,                   /* bus_power */
 323         i8042_intr_ops          /* bus_intr_op */
 324 };
 325 
 326 static struct dev_ops i8042_ops = {
 327         DEVO_REV,
 328         0,
 329         ddi_no_info,
 330         nulldev,
 331         0,
 332         i8042_attach,
 333         i8042_detach,
 334         nodev,
 335         (struct cb_ops *)0,
 336         &i8042_bus_ops,
 337         NULL,
 338         ddi_quiesce_not_needed,
 339 };
 340 
 341 
 342 /*
 343  * module definitions:
 344  */
 345 #include <sys/modctl.h>
 346 extern struct mod_ops mod_driverops;
 347 
 348 static struct modldrv modldrv = {
 349         &mod_driverops,     /* Type of module.  This one is a driver */
 350         "i8042 nexus driver",   /* Name of module. */
 351         &i8042_ops,         /* driver ops */
 352 };
 353 
 354 static struct modlinkage modlinkage = {
 355         MODREV_1, { (void *)&modldrv, NULL }
 356 };
 357 
 358 int
 359 _init(void)
 360 {
 361         int e;
 362 
 363         /*
 364          * Install the module.
 365          */
 366         e = mod_install(&modlinkage);
 367         return (e);
 368 }
 369 
 370 int
 371 _fini(void)
 372 {
 373         int e;
 374 
 375         /*
 376          * Remove the module.
 377          */
 378         e = mod_remove(&modlinkage);
 379         if (e != 0)
 380                 return (e);
 381 
 382         return (e);
 383 }
 384 
 385 int
 386 _info(struct modinfo *modinfop)
 387 {
 388         return (mod_info(&modlinkage, modinfop));
 389 }
 390 
 391 #define DRIVER_NAME(dip)        ddi_driver_name(dip)
 392 
 393 static void i8042_timeout(void *arg);
 394 static unsigned int i8042_intr(caddr_t arg);
 395 static void i8042_write_command_byte(struct i8042 *, unsigned char);
 396 static uint8_t i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr);
 397 static void i8042_put8(ddi_acc_impl_t *handlep, uint8_t *addr,
 398     uint8_t value);
 399 static void i8042_send(struct i8042 *global, int reg, unsigned char cmd);
 400 static uint8_t i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr);
 401 
 402 unsigned int i8042_unclaimed_interrupts = 0;
 403 
 404 static void
 405 i8042_discard_junk_data(struct i8042 *global)
 406 {
 407         /* Discard any junk data that may have been left around */
 408         for (;;) {
 409                 unsigned char           stat;
 410 
 411                 stat = ddi_get8(global->io_handle,
 412                     global->io_addr + I8042_STAT);
 413                 if (! (stat & I8042_STAT_OUTBF))
 414                         break;
 415                 (void) ddi_get8(global->io_handle,
 416                     global->io_addr + I8042_DATA);
 417 
 418         }
 419 }
 420 
 421 static int
 422 i8042_cleanup(struct i8042 *global)
 423 {
 424         int which_port, i;
 425         struct i8042_port *port;
 426 
 427         ASSERT(global != NULL);
 428 
 429         if (global->initialized == B_TRUE) {
 430                 /*
 431                  * If any children still have regs mapped or interrupts
 432                  * registered, return immediate failure (and do nothing).
 433                  */
 434                 mutex_enter(&global->i8042_mutex);
 435 
 436                 for (which_port = 0; which_port < NUM_PORTS; which_port++) {
 437                         port = &global->i8042_ports[which_port];
 438 
 439                         if (port->initialized == B_TRUE) {
 440                                 mutex_exit(&global->i8042_mutex);
 441                                 return (DDI_FAILURE);
 442                         }
 443 #if defined(USE_SOFT_INTRS)
 444                         if (port->soft_hdl != 0) {
 445                                 mutex_exit(&global->i8042_mutex);
 446                                 return (DDI_FAILURE);
 447                         }
 448 #else
 449                         mutex_enter(&port->intr_mutex);
 450                         if (port->intr_func != NULL) {
 451                                 mutex_exit(&port->intr_mutex);
 452                                 mutex_exit(&global->i8042_mutex);
 453                                 return (DDI_FAILURE);
 454                         }
 455                         mutex_exit(&port->intr_mutex);
 456 #endif
 457                 }
 458                 global->initialized = B_FALSE;
 459 
 460                 mutex_exit(&global->i8042_mutex);
 461         }
 462 
 463 #ifdef __sparc
 464         /* If there may be an outstanding timeout, cancel it */
 465         if (global->timeout_id != 0) {
 466                 (void) untimeout(global->timeout_id);
 467         }
 468 #endif
 469 
 470         /* Stop the controller from generating interrupts */
 471         if (global->init_state & I8042_INIT_INTRS_ENABLED)
 472                 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
 473 
 474         if (global->intrs_added) {
 475                 /*
 476                  * Remove the interrupts in the reverse order in
 477                  * which they were added
 478                  */
 479                 for (i = global->nintrs - 1; i >= 0; i--) {
 480                         if (global->intrs_added & (1 << i))
 481                                 ddi_remove_intr(global->dip, i,
 482                                     global->iblock_cookies[i]);
 483                 }
 484         }
 485 
 486 
 487         if (global->init_state & I8042_INIT_MUTEXES) {
 488                 for (which_port = 0; which_port < NUM_PORTS; which_port++) {
 489 #ifndef USE_SOFT_INTRS
 490                         port = &global->i8042_ports[which_port];
 491                         mutex_destroy(&port->intr_mutex);
 492 #endif
 493                 }
 494                 cv_destroy(&global->glock_cv);
 495                 mutex_destroy(&global->i8042_out_mutex);
 496                 mutex_destroy(&global->i8042_mutex);
 497         }
 498 
 499         if (global->init_state & I8042_INIT_REGS_MAPPED)
 500                 ddi_regs_map_free(&global->io_handle);
 501 
 502         if (global->init_state & I8042_INIT_BASIC) {
 503                 ddi_set_driver_private(global->dip, (caddr_t)NULL);
 504                 if (global->nintrs > 0) {
 505                         kmem_free(global->iblock_cookies, global->nintrs *
 506                             sizeof (ddi_iblock_cookie_t));
 507                 }
 508                 kmem_free(global, sizeof (struct i8042));
 509         }
 510 
 511         return (DDI_SUCCESS);
 512 }
 513 
 514 #define OBF_WAIT_COUNT 1000     /* in granules of 10uS */
 515 
 516 /*
 517  * Wait for the 8042 to fill the 'output' (from 8042 to host)
 518  * buffer.  If 8042 fails to fill the output buffer within an
 519  * allowed time, return 1 (which means there is no data available),
 520  * otherwise return 0
 521  */
 522 static int
 523 i8042_wait_obf(struct i8042 *global)
 524 {
 525         int timer = 0;
 526 
 527         while (!(ddi_get8(global->io_handle, global->io_addr + I8042_STAT) &
 528             I8042_STAT_OUTBF)) {
 529                 if (++timer > OBF_WAIT_COUNT)
 530                         return (1);
 531                 drv_usecwait(10);
 532         }
 533         return (0);
 534 }
 535 
 536 
 537 /*
 538  * Drain all queued bytes from the 8042.
 539  * Return 0 for no error, <> 0 if there was an error.
 540  */
 541 static int
 542 i8042_purge_outbuf(struct i8042 *global)
 543 {
 544         int     i;
 545 
 546         for (i = 0; i < MAX_JUNK_ITERATIONS; i++) {
 547                 if (i8042_wait_obf(global))
 548                         break;
 549                 (void) ddi_get8(global->io_handle,
 550                     global->io_addr + I8042_DATA);
 551         }
 552 
 553         /*
 554          * If we hit the maximum number of iterations, then there
 555          * was a serious problem (e.g. our hardware may not be
 556          * present or working properly).
 557          */
 558         return (i == MAX_JUNK_ITERATIONS);
 559 }
 560 
 561 static int
 562 i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 563 {
 564         struct i8042_port       *port;
 565         enum i8042_ports        which_port;
 566         int                     i;
 567 #if !defined(USE_SOFT_INTRS)
 568         ddi_iblock_cookie_t     cookie;
 569 #endif
 570         static ddi_device_acc_attr_t attr = {
 571                 DDI_DEVICE_ATTR_V0,
 572                 DDI_NEVERSWAP_ACC,
 573                 DDI_STRICTORDER_ACC,
 574         };
 575         struct i8042 *global;
 576 #ifdef __sparc
 577         int                     interval;
 578 #endif
 579 
 580         switch (cmd) {
 581         case DDI_RESUME:
 582                 global = (struct i8042 *)ddi_get_driver_private(dip);
 583                 i8042_discard_junk_data(global);
 584                 i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL);
 585                 return (DDI_SUCCESS);
 586 
 587         case DDI_ATTACH:
 588                 /* Handled in the main function block */
 589                 break;
 590 
 591         default:
 592                 return (DDI_FAILURE);
 593         }
 594 
 595         /*
 596          * DDI_ATTACH processing
 597          */
 598 
 599         global = (struct i8042 *)kmem_zalloc(sizeof (struct i8042), KM_SLEEP);
 600         ddi_set_driver_private(dip, (caddr_t)global);
 601         global->dip = dip;
 602         global->initialized = B_FALSE;
 603 
 604         global->init_state |= I8042_INIT_BASIC;
 605 
 606         if (ddi_regs_map_setup(dip, 0, (caddr_t *)&global->io_addr,
 607             (offset_t)0, (offset_t)0, &attr, &global->io_handle)
 608             != DDI_SUCCESS)
 609                 goto fail;
 610 
 611         global->init_state |= I8042_INIT_REGS_MAPPED;
 612 
 613         /*
 614          * Get the number of interrupts for this nexus
 615          */
 616         if (ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE)
 617                 goto fail;
 618 
 619 #ifdef __sparc
 620         if ((i8042_polled_mode || i8042_is_polling_platform()) &&
 621             !i8042_force_interrupt_mode) {
 622                 /*
 623                  * If we're on a platform that has known
 624                  * interrupt issues with the keyboard/mouse,
 625                  * use polled mode.
 626                  */
 627                 i8042_polled_mode = B_TRUE;
 628                 global->nintrs = 0;
 629         } else if (global->nintrs == 0) {
 630                 /*
 631                  * If there are no interrupts on the i8042 node,
 632                  * we may be on a brain-dead platform that only
 633                  * has interrupts properties on i8042's children
 634                  * (e.g. some UltraII-based boards)
 635                  * In this case, scan first-level children, and
 636                  * build a list of interrupts that each child uses,
 637                  * then create an `interrupts' property on the nexus node
 638                  * that contains the interrupts used by all children
 639                  */
 640                 if (i8042_build_interrupts_property(dip) == DDI_FAILURE ||
 641                     ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE ||
 642                     global->nintrs == 0) {
 643                         cmn_err(CE_WARN, "i8042#%d: No interrupts defined!",
 644                             ddi_get_instance(global->dip));
 645                         goto fail;
 646                 }
 647         }
 648 #else
 649         if (global->nintrs == 0) {
 650                 cmn_err(CE_WARN, "i8042#%d: No interrupts defined!",
 651                     ddi_get_instance(global->dip));
 652                 goto fail;
 653         }
 654 #endif
 655 
 656         if (global->nintrs > MAX_INTERRUPTS)
 657                 global->nintrs = MAX_INTERRUPTS;
 658 
 659         if (global->nintrs > 0) {
 660                 global->iblock_cookies = kmem_zalloc(global->nintrs *
 661                     sizeof (ddi_iblock_cookie_t), KM_NOSLEEP);
 662 
 663                 for (i = 0; i < global->nintrs; i++) {
 664                         if (ddi_get_iblock_cookie(dip, i,
 665                             &global->iblock_cookies[i]) != DDI_SUCCESS)
 666                                 goto fail;
 667                 }
 668         } else
 669                 global->iblock_cookies = NULL;
 670 
 671         mutex_init(&global->i8042_mutex, NULL, MUTEX_DRIVER,
 672             (global->nintrs > 0) ? global->iblock_cookies[0] : NULL);
 673 
 674         mutex_init(&global->i8042_out_mutex, NULL, MUTEX_DRIVER, NULL);
 675 
 676         cv_init(&global->glock_cv, NULL, CV_DRIVER, NULL);
 677 
 678         for (which_port = 0; which_port < NUM_PORTS; ++which_port) {
 679                 port = &global->i8042_ports[which_port];
 680                 port->initialized = B_FALSE;
 681                 port->i8042_global = global;
 682                 port->which = which_port;
 683 #if defined(USE_SOFT_INTRS)
 684                 port->soft_hdl = 0;
 685 #else
 686 
 687                 /*
 688                  * Assume that the interrupt block cookie for port <n>
 689                  * is iblock_cookies[<n>] (a 1:1 mapping).  If there are not
 690                  * enough interrupts to cover the number of ports, use
 691                  * the cookie from interrupt 0.
 692                  */
 693                 if (global->nintrs > 0) {
 694                         cookie = global->iblock_cookies[
 695                             (which_port < global->nintrs) ? which_port : 0];
 696 
 697                         mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER,
 698                             cookie);
 699 
 700                 } else {
 701                         mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER, NULL);
 702                 }
 703 
 704 #endif
 705         }
 706 
 707         global->init_state |= I8042_INIT_MUTEXES;
 708 
 709         /*
 710          * Disable input and interrupts from both the main and aux ports.
 711          *
 712          * It is difficult if not impossible to read the command byte in
 713          * a completely clean way.  Reading the command byte may cause
 714          * an interrupt, and there is no way to suppress interrupts without
 715          * writing the command byte.  On a PC we might rely on the fact
 716          * that IRQ 1 is disabled and guaranteed not shared, but on
 717          * other platforms the interrupt line might be shared and so
 718          * causing an interrupt could be bad.
 719          *
 720          * Since we can't read the command byte and update it, we
 721          * just set it to static values.
 722          */
 723         i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
 724 
 725         global->init_state &= ~I8042_INIT_INTRS_ENABLED;
 726 
 727         /* Discard any junk data that may have been left around */
 728         if (i8042_purge_outbuf(global) != 0)
 729                 goto fail;
 730 
 731 
 732         /*
 733          * Assume the number of interrupts is less that the number of
 734          * bits in the variable used to keep track of which interrupt
 735          * was added.
 736          */
 737         ASSERT(global->nintrs <= (sizeof (global->intrs_added) * NBBY));
 738 
 739         for (i = 0; i < global->nintrs; i++) {
 740                 /*
 741                  * The 8042 handles all interrupts, because all
 742                  * device access goes through the same I/O addresses.
 743                  */
 744                 if (ddi_add_intr(dip, i,
 745                     (ddi_iblock_cookie_t *)NULL,
 746                     (ddi_idevice_cookie_t *)NULL,
 747                     i8042_intr, (caddr_t)global) != DDI_SUCCESS)
 748                         goto fail;
 749 
 750                 global->intrs_added |= (1 << i);
 751         }
 752 
 753         global->initialized = B_TRUE;
 754 
 755         /*
 756          * Enable the main and aux data ports and interrupts
 757          */
 758         i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL);
 759         global->init_state |= I8042_INIT_INTRS_ENABLED;
 760 
 761 #ifdef __sparc
 762         if (i8042_polled_mode) {
 763                 /*
 764                  * Do not allow anyone to set the polling interval
 765                  * to an interval more frequent than I8042_MIN_POLL_INTERVAL --
 766                  * it could hose the system.
 767                  */
 768                 interval = i8042_poll_interval;
 769                 if (interval < I8042_MIN_POLL_INTERVAL)
 770                         interval = I8042_MIN_POLL_INTERVAL;
 771                 i8042_fast_poll_interval = interval;
 772                 i8042_slow_poll_interval = interval << 3;
 773 
 774                 global->timeout_id = timeout(i8042_timeout, global,
 775                     drv_usectohz(i8042_slow_poll_interval));
 776         }
 777 #endif
 778 
 779         return (DDI_SUCCESS);
 780 
 781 fail:
 782         /* cleanup will succeed because no children have attached yet */
 783         (void) i8042_cleanup(global);
 784         return (DDI_FAILURE);
 785 }
 786 
 787 /*ARGSUSED*/
 788 static int
 789 i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 790 {
 791         struct i8042 *global = (struct i8042 *)ddi_get_driver_private(dip);
 792 
 793         ASSERT(global != NULL);
 794 
 795         switch (cmd) {
 796         case DDI_SUSPEND:
 797                 /*
 798                  * Do not disable the keyboard controller for x86 suspend, as
 799                  * the keyboard can be used to bring the system out of
 800                  * suspend.
 801                  */
 802 #ifdef __sparc
 803                 /* Disable interrupts and controller devices before suspend */
 804                 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
 805 #endif
 806                 return (DDI_SUCCESS);
 807 
 808         case DDI_DETACH:
 809                 /* DETACH can only succeed if cleanup succeeds */
 810                 return (i8042_cleanup(global));
 811 
 812         default:
 813                 return (DDI_FAILURE);
 814         }
 815 }
 816 
 817 /*
 818  * The primary interface to us from our children is via virtual registers.
 819  * This is the entry point that allows our children to "map" these
 820  * virtual registers.
 821  */
 822 static int
 823 i8042_map(
 824         dev_info_t *dip,
 825         dev_info_t *rdip,
 826         ddi_map_req_t *mp,
 827         off_t offset,
 828         off_t len,
 829         caddr_t *addrp)
 830 {
 831         struct i8042_port       *port;
 832         struct i8042            *global;
 833         enum i8042_ports        which_port;
 834         int                     *iprop;
 835         unsigned int            iprop_len;
 836         int                     rnumber;
 837         ddi_acc_hdl_t           *handle;
 838         ddi_acc_impl_t          *ap;
 839 
 840         global = ddi_get_driver_private(dip);
 841 
 842         switch (mp->map_type) {
 843         case DDI_MT_REGSPEC:
 844                 which_port = *(int *)mp->map_obj.rp;
 845                 break;
 846 
 847         case DDI_MT_RNUMBER:
 848                 rnumber = mp->map_obj.rnumber;
 849                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
 850                     DDI_PROP_DONTPASS, "reg", &iprop, &iprop_len) !=
 851                     DDI_SUCCESS) {
 852 #if defined(DEBUG)
 853                         cmn_err(CE_WARN, "%s #%d:  Missing 'reg' on %s@%s",
 854                             DRIVER_NAME(dip), ddi_get_instance(dip),
 855                             ddi_node_name(rdip), ddi_get_name_addr(rdip));
 856 #endif
 857                         return (DDI_FAILURE);
 858                 }
 859 #if defined(DEBUG)
 860                 if (iprop_len != 1) {
 861                         cmn_err(CE_WARN, "%s #%d:  Malformed 'reg' on %s@%s",
 862                             DRIVER_NAME(dip), ddi_get_instance(dip),
 863                             ddi_node_name(rdip), ddi_get_name_addr(rdip));
 864                         return (DDI_FAILURE);
 865                 }
 866                 if (rnumber < 0 || rnumber >= iprop_len) {
 867                         cmn_err(CE_WARN, "%s #%d:  bad map request for %s@%s",
 868                             DRIVER_NAME(dip), ddi_get_instance(dip),
 869                             ddi_node_name(rdip), ddi_get_name_addr(rdip));
 870                         return (DDI_FAILURE);
 871                 }
 872 #endif
 873                 which_port = iprop[rnumber];
 874                 ddi_prop_free((void *)iprop);
 875 #if defined(DEBUG)
 876                 if (which_port != MAIN_PORT && which_port != AUX_PORT) {
 877                         cmn_err(CE_WARN,
 878                             "%s #%d:  bad 'reg' value %d on %s@%s",
 879                             DRIVER_NAME(dip), ddi_get_instance(dip),
 880                             which_port,
 881                             ddi_node_name(rdip), ddi_get_name_addr(rdip));
 882                         return (DDI_FAILURE);
 883                 }
 884 #endif
 885                 break;
 886 
 887         default:
 888 #if defined(DEBUG)
 889                 cmn_err(CE_WARN, "%s #%d:  unknown map type %d for %s@%s",
 890                     DRIVER_NAME(dip), ddi_get_instance(dip),
 891                     mp->map_type,
 892                     ddi_node_name(rdip), ddi_get_name_addr(rdip));
 893 #endif
 894                 return (DDI_FAILURE);
 895         }
 896 
 897 #if defined(DEBUG)
 898         if (offset != 0 || len != 0) {
 899                 cmn_err(CE_WARN,
 900                     "%s #%d:  partial mapping attempt for %s@%s ignored",
 901                     DRIVER_NAME(dip), ddi_get_instance(dip),
 902                     ddi_node_name(rdip), ddi_get_name_addr(rdip));
 903         }
 904 #endif
 905 
 906         port = &global->i8042_ports[which_port];
 907 
 908         switch (mp->map_op) {
 909         case DDI_MO_MAP_LOCKED:
 910 #if defined(USE_SOFT_INTRS)
 911                 port->soft_intr_enabled = B_FALSE;
 912 #else
 913                 port->intr_func = NULL;
 914 #endif
 915                 port->wptr = 0;
 916                 port->rptr = 0;
 917                 port->dip = dip;
 918                 port->inumber = 0;
 919                 port->has_glock = B_FALSE;
 920                 port->initialized = B_TRUE;
 921 
 922                 handle = mp->map_handlep;
 923                 handle->ah_bus_private = port;
 924                 handle->ah_addr = 0;
 925                 ap = (ddi_acc_impl_t *)handle->ah_platform_private;
 926                 /*
 927                  * Support get8, put8 and _rep_put8
 928                  */
 929                 ap->ahi_put8 = i8042_put8;
 930                 ap->ahi_get8 = i8042_get8;
 931                 ap->ahi_put16 = NULL;
 932                 ap->ahi_get16 = NULL;
 933                 ap->ahi_put32 = NULL;
 934                 ap->ahi_get32 = NULL;
 935                 ap->ahi_put64 = NULL;
 936                 ap->ahi_get64 = NULL;
 937                 ap->ahi_rep_put8 = NULL;
 938                 ap->ahi_rep_get8 = NULL;
 939                 ap->ahi_rep_put16 = NULL;
 940                 ap->ahi_rep_get16 = NULL;
 941                 ap->ahi_rep_put32 = NULL;
 942                 ap->ahi_rep_get32 = NULL;
 943                 ap->ahi_rep_put64 = NULL;
 944                 ap->ahi_rep_get64 = NULL;
 945                 *addrp = 0;
 946                 return (DDI_SUCCESS);
 947 
 948         case DDI_MO_UNMAP:
 949                 port->initialized = B_FALSE;
 950                 return (DDI_SUCCESS);
 951 
 952         default:
 953                 cmn_err(CE_WARN, "%s:  map operation %d not supported",
 954                     DRIVER_NAME(dip), mp->map_op);
 955                 return (DDI_FAILURE);
 956         }
 957 }
 958 
 959 #ifdef __sparc
 960 static void
 961 i8042_timeout(void *arg)
 962 {
 963         struct i8042 *i8042_p = (struct i8042 *)arg;
 964         int interval;
 965 
 966         /*
 967          * Allow the polling speed to be changed on the fly --
 968          * catch it here and update the intervals used.
 969          */
 970         if (i8042_fast_poll_interval != i8042_poll_interval) {
 971                 interval = i8042_poll_interval;
 972                 if (interval < I8042_MIN_POLL_INTERVAL)
 973                         interval = I8042_MIN_POLL_INTERVAL;
 974                 i8042_fast_poll_interval = interval;
 975                 i8042_slow_poll_interval = interval << 3;
 976         }
 977 
 978         /*
 979          * If the ISR returned true, start polling at a faster rate to
 980          * increate responsiveness.  Once the keyboard or mouse go idle,
 981          * the ISR will return UNCLAIMED, and we'll go back to the slower
 982          * polling rate.  This gives some positive hysteresis (but not
 983          * negative, since we go back to the slower polling interval after
 984          * only one UNCLAIMED).  This has shown to be responsive enough,
 985          * even for fast typers.
 986          */
 987         interval = (i8042_intr((caddr_t)i8042_p) == DDI_INTR_CLAIMED) ?
 988             i8042_fast_poll_interval : i8042_slow_poll_interval;
 989 
 990         if (i8042_polled_mode)
 991                 i8042_p->timeout_id = timeout(i8042_timeout, arg,
 992                     drv_usectohz(interval));
 993         else
 994                 i8042_p->timeout_id = 0;
 995 }
 996 #endif
 997 
 998 /*
 999  * i8042 hardware interrupt routine.  Called for both main and aux port
1000  * interrupts.
1001  */
1002 static unsigned int
1003 i8042_intr(caddr_t arg)
1004 {
1005         struct i8042            *global = (struct i8042 *)arg;
1006         enum i8042_ports        which_port;
1007         unsigned char           stat;
1008         unsigned char           byte;
1009         int                     new_wptr;
1010         struct i8042_port       *port;
1011 
1012         mutex_enter(&global->i8042_mutex);
1013 
1014         stat = ddi_get8(global->io_handle, global->io_addr + I8042_STAT);
1015 
1016         if (! (stat & I8042_STAT_OUTBF)) {
1017                 ++i8042_unclaimed_interrupts;
1018                 mutex_exit(&global->i8042_mutex);
1019                 return (DDI_INTR_UNCLAIMED);
1020         }
1021 
1022         byte = ddi_get8(global->io_handle, global->io_addr + I8042_DATA);
1023 
1024         which_port = (stat & I8042_STAT_AUXBF) ? AUX_PORT : MAIN_PORT;
1025 
1026         port = &global->i8042_ports[which_port];
1027 
1028         if (! port->initialized) {
1029                 mutex_exit(&global->i8042_mutex);
1030                 return (DDI_INTR_CLAIMED);
1031         }
1032 
1033         new_wptr = (port->wptr + 1) % BUFSIZ;
1034         if (new_wptr == port->rptr) {
1035                 port->overruns++;
1036 #if defined(DEBUG)
1037                 if (port->overruns % 50 == 1) {
1038                         cmn_err(CE_WARN, "i8042/%d: %d overruns\n",
1039                             which_port, port->overruns);
1040                 }
1041 #endif
1042 
1043                 mutex_exit(&global->i8042_mutex);
1044                 return (DDI_INTR_CLAIMED);
1045         }
1046 
1047         port->buf[port->wptr] = byte;
1048         port->wptr = new_wptr;
1049 
1050 #if defined(USE_SOFT_INTRS)
1051         if (port->soft_intr_enabled)
1052                 (void) ddi_intr_trigger_softint(port->soft_hdl,
1053                     port->intr_arg2);
1054 #endif
1055 
1056         mutex_exit(&global->i8042_mutex);
1057 
1058 #if     !defined(USE_SOFT_INTRS)
1059         mutex_enter(&port->intr_mutex);
1060         if (port->intr_func != NULL)
1061                 port->intr_func(port->intr_arg1, NULL);
1062         mutex_exit(&port->intr_mutex);
1063 #endif
1064 
1065         return (DDI_INTR_CLAIMED);
1066 }
1067 
1068 static void
1069 i8042_write_command_byte(struct i8042 *global, unsigned char cb)
1070 {
1071         mutex_enter(&global->i8042_out_mutex);
1072         i8042_send(global, I8042_CMD, I8042_CMD_WCB);
1073         i8042_send(global, I8042_DATA, cb);
1074         mutex_exit(&global->i8042_out_mutex);
1075 }
1076 
1077 /*
1078  * Send a byte to either the i8042 command or data register, depending on
1079  * the argument.
1080  */
1081 static void
1082 i8042_send(struct i8042 *global, int reg, unsigned char val)
1083 {
1084         uint8_t stat;
1085         int tries = 0;
1086 
1087         /*
1088          * First, wait for the i8042 to be ready to accept data.
1089          */
1090         /*CONSTANTCONDITION*/
1091         while (1) {
1092                 stat = ddi_get8(global->io_handle,
1093                     global->io_addr + I8042_STAT);
1094 
1095                 if ((stat & I8042_STAT_INBF) == 0) {
1096                         ddi_put8(global->io_handle, global->io_addr+reg, val);
1097                         break;
1098                 }
1099 
1100                 /* Don't wait unless we're going to check again */
1101                 if (++tries >= max_wait_iterations)
1102                         break;
1103                 else
1104                         drv_usecwait(USECS_PER_WAIT);
1105         }
1106 
1107 #ifdef DEBUG
1108         if (tries >= MAX_WAIT_ITERATIONS)
1109                 cmn_err(CE_WARN, "i8042_send: timeout!");
1110 #endif
1111 }
1112 
1113 /*
1114  * Here's the interface to the virtual registers on the device.
1115  *
1116  * Normal interrupt-driven I/O:
1117  *
1118  * I8042_INT_INPUT_AVAIL        (r/o)
1119  *      Interrupt mode input bytes available?  Zero = No.
1120  * I8042_INT_INPUT_DATA         (r/o)
1121  *      Fetch interrupt mode input byte.
1122  * I8042_INT_OUTPUT_DATA        (w/o)
1123  *      Interrupt mode output byte.
1124  *
1125  * Polled I/O, used by (e.g.) kmdb, when normal system services are
1126  * unavailable:
1127  *
1128  * I8042_POLL_INPUT_AVAIL       (r/o)
1129  *      Polled mode input bytes available?  Zero = No.
1130  * I8042_POLL_INPUT_DATA        (r/o)
1131  *      Polled mode input byte.
1132  * I8042_POLL_OUTPUT_DATA       (w/o)
1133  *      Polled mode output byte.
1134  *
1135  * Note that in polled mode we cannot use cmn_err; only prom_printf is safe.
1136  */
1137 static uint8_t
1138 i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr)
1139 {
1140         struct i8042_port *port;
1141         struct i8042 *global;
1142         uint8_t ret;
1143         ddi_acc_hdl_t   *h;
1144         uint8_t stat;
1145 
1146         h = (ddi_acc_hdl_t *)handlep;
1147 
1148         port = (struct i8042_port *)h->ah_bus_private;
1149         global = port->i8042_global;
1150 
1151         switch ((uintptr_t)addr) {
1152         case I8042_LOCK:
1153                 ASSERT(port->has_glock != B_TRUE);   /* No reentrancy */
1154                 mutex_enter(&global->i8042_out_mutex);
1155                 /*
1156                  * Block other children requesting exclusive access here until
1157                  * the child possessing it relinquishes the lock.
1158                  */
1159                 while (global->glock) {
1160                         cv_wait(&global->glock_cv, &global->i8042_out_mutex);
1161                 }
1162                 port->has_glock = B_TRUE;
1163                 global->glock = 1;
1164                 mutex_exit(&global->i8042_out_mutex);
1165                 ret = 0;
1166                 break;
1167 
1168         case I8042_UNLOCK:
1169                 mutex_enter(&global->i8042_out_mutex);
1170                 ASSERT(global->glock != 0);
1171                 ASSERT(port->has_glock == B_TRUE);
1172                 port->has_glock = B_FALSE;
1173                 global->glock = 0;
1174                 /*
1175                  * Signal anyone waiting for exclusive access that it is now
1176                  * available.
1177                  */
1178                 cv_signal(&global->glock_cv);
1179                 mutex_exit(&global->i8042_out_mutex);
1180                 ret = 0;
1181                 break;
1182 
1183         case I8042_INT_INPUT_AVAIL:
1184                 mutex_enter(&global->i8042_mutex);
1185                 ret = port->rptr != port->wptr;
1186                 mutex_exit(&global->i8042_mutex);
1187                 return (ret);
1188 
1189         case I8042_INT_INPUT_DATA:
1190                 mutex_enter(&global->i8042_mutex);
1191 
1192                 if (port->rptr != port->wptr) {
1193                         ret = port->buf[port->rptr];
1194                         port->rptr = (port->rptr + 1) % BUFSIZ;
1195                 } else {
1196 #if defined(DEBUG)
1197                         cmn_err(CE_WARN,
1198                             "i8042:  Tried to read from empty buffer");
1199 #endif
1200                         ret = 0;
1201                 }
1202 
1203 
1204                 mutex_exit(&global->i8042_mutex);
1205 
1206                 break;
1207 
1208 #if defined(DEBUG)
1209         case I8042_INT_OUTPUT_DATA:
1210         case I8042_POLL_OUTPUT_DATA:
1211                 cmn_err(CE_WARN, "i8042:  read of write-only register 0x%p",
1212                     (void *)addr);
1213                 ret = 0;
1214                 break;
1215 #endif
1216 
1217         case I8042_POLL_INPUT_AVAIL:
1218                 if (port->rptr != port->wptr)
1219                         return (B_TRUE);
1220                 for (;;) {
1221                         stat = ddi_get8(global->io_handle,
1222                             global->io_addr + I8042_STAT);
1223                         if ((stat & I8042_STAT_OUTBF) == 0)
1224                                 return (B_FALSE);
1225                         switch (port->which) {
1226                         case MAIN_PORT:
1227                                 if ((stat & I8042_STAT_AUXBF) == 0)
1228                                         return (B_TRUE);
1229                                 break;
1230                         case AUX_PORT:
1231                                 if ((stat & I8042_STAT_AUXBF) != 0)
1232                                         return (B_TRUE);
1233                                 break;
1234                         default:
1235                                 cmn_err(CE_WARN, "data from unknown port: %d",
1236                                     port->which);
1237                         }
1238                         /*
1239                          * Data for wrong port pending; discard it.
1240                          */
1241                         (void) ddi_get8(global->io_handle,
1242                             global->io_addr + I8042_DATA);
1243                 }
1244 
1245                 /* NOTREACHED */
1246 
1247         case I8042_POLL_INPUT_DATA:
1248                 if (port->rptr != port->wptr) {
1249                         ret = port->buf[port->rptr];
1250                         port->rptr = (port->rptr + 1) % BUFSIZ;
1251                         return (ret);
1252                 }
1253 
1254                 stat = ddi_get8(global->io_handle,
1255                     global->io_addr + I8042_STAT);
1256                 if ((stat & I8042_STAT_OUTBF) == 0) {
1257 #if defined(DEBUG)
1258                         prom_printf("I8042_POLL_INPUT_DATA:  no data!\n");
1259 #endif
1260                         return (0);
1261                 }
1262                 ret = ddi_get8(global->io_handle,
1263                     global->io_addr + I8042_DATA);
1264                 switch (port->which) {
1265                 case MAIN_PORT:
1266                         if ((stat & I8042_STAT_AUXBF) == 0)
1267                                 return (ret);
1268                         break;
1269                 case AUX_PORT:
1270                         if ((stat & I8042_STAT_AUXBF) != 0)
1271                                 return (ret);
1272                         break;
1273                 }
1274 #if defined(DEBUG)
1275                 prom_printf("I8042_POLL_INPUT_DATA:  data for wrong port!\n");
1276 #endif
1277                 return (0);
1278 
1279         default:
1280 #if defined(DEBUG)
1281                 cmn_err(CE_WARN, "i8042:  read of undefined register 0x%p",
1282                     (void *)addr);
1283 #endif
1284                 ret = 0;
1285                 break;
1286         }
1287         return (ret);
1288 }
1289 
1290 static void
1291 i8042_put8(ddi_acc_impl_t *handlep, uint8_t *addr, uint8_t value)
1292 {
1293         struct i8042            *global;
1294         struct i8042_port       *port;
1295         ddi_acc_hdl_t           *h;
1296 
1297         h = (ddi_acc_hdl_t *)handlep;
1298         port = (struct i8042_port *)h->ah_bus_private;
1299         global = port->i8042_global;
1300 
1301         switch ((uintptr_t)addr) {
1302         case I8042_INT_OUTPUT_DATA:
1303         case I8042_POLL_OUTPUT_DATA:
1304 
1305                 if ((uintptr_t)addr == I8042_INT_OUTPUT_DATA) {
1306                         mutex_enter(&global->i8042_out_mutex);
1307 
1308                         /*
1309                          * If no child has exclusive access, then proceed with
1310                          * the put8 below.  If a child (not the one making the
1311                          * call) has exclusive access, wait for it to be
1312                          * relinquished.  The use of i8042_out_mutex prevents
1313                          * children seeking exclusive access from getting it
1314                          * while a child is writing to the 8042.
1315                          */
1316                         while (global->glock && !port->has_glock) {
1317                                 cv_wait(&global->glock_cv,
1318                                     &global->i8042_out_mutex);
1319                         }
1320                 }
1321 
1322                 if (port->which == AUX_PORT)
1323                         i8042_send(global, I8042_CMD, I8042_CMD_WRITE_AUX);
1324 
1325                 i8042_send(global, I8042_DATA, value);
1326 
1327                 if ((uintptr_t)addr == I8042_INT_OUTPUT_DATA)
1328                         mutex_exit(&global->i8042_out_mutex);
1329 
1330                 break;
1331 
1332 #if defined(DEBUG)
1333         case I8042_INT_INPUT_AVAIL:
1334         case I8042_INT_INPUT_DATA:
1335         case I8042_POLL_INPUT_AVAIL:
1336         case I8042_POLL_INPUT_DATA:
1337                 cmn_err(CE_WARN, "i8042:  write of read-only register 0x%p",
1338                     (void *)addr);
1339                 break;
1340 
1341         default:
1342                 cmn_err(CE_WARN, "i8042:  read of undefined register 0x%p",
1343                     (void *)addr);
1344                 break;
1345 #endif
1346         }
1347 }
1348 
1349 
1350 /* ARGSUSED */
1351 static int
1352 i8042_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
1353     ddi_intr_handle_impl_t *hdlp, void *result)
1354 {
1355         struct i8042_port *port;
1356 #if defined(USE_SOFT_INTRS)
1357         struct i8042    *global;
1358         int             ret;
1359 #endif
1360 
1361         switch (intr_op) {
1362         case DDI_INTROP_SUPPORTED_TYPES:
1363                 *(int *)result = DDI_INTR_TYPE_FIXED;
1364                 break;
1365         case DDI_INTROP_GETCAP:
1366                 if (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)
1367                     == DDI_FAILURE)
1368                         *(int *)result = 0;
1369                 break;
1370         case DDI_INTROP_NINTRS:
1371         case DDI_INTROP_NAVAIL:
1372                 *(int *)result = 1;
1373                 break;
1374         case DDI_INTROP_ALLOC:
1375                 *(int *)result = hdlp->ih_scratch1;
1376                 break;
1377         case DDI_INTROP_FREE:
1378                 break;
1379         case DDI_INTROP_GETPRI:
1380                 /* Hard coding it for x86 */
1381                 *(int *)result = 5;
1382                 break;
1383         case DDI_INTROP_ADDISR:
1384                 port = ddi_get_parent_data(rdip);
1385 
1386 #if defined(USE_SOFT_INTRS)
1387                 global = port->i8042_global;
1388                 ret = ddi_intr_add_softint(rdip, &port->soft_hdl,
1389                     I8042_SOFTINT_PRI, hdlp->ih_cb_func, hdlp->ih_cb_arg1);
1390 
1391                 if (ret != DDI_SUCCESS) {
1392 #if defined(DEBUG)
1393                         cmn_err(CE_WARN, "%s #%d:  "
1394                             "Cannot add soft interrupt for %s #%d, ret=%d.",
1395                             DRIVER_NAME(dip), ddi_get_instance(dip),
1396                             DRIVER_NAME(rdip), ddi_get_instance(rdip), ret);
1397 #endif  /* defined(DEBUG) */
1398                         return (ret);
1399                 }
1400 
1401 #else   /* defined(USE_SOFT_INTRS) */
1402                 mutex_enter(&port->intr_mutex);
1403                 port->intr_func = hdlp->ih_cb_func;
1404                 port->intr_arg1 = hdlp->ih_cb_arg1;
1405                 port->intr_arg2 = hdlp->ih_cb_arg2;
1406                 mutex_exit(&port->intr_mutex);
1407 #endif  /* defined(USE_SOFT_INTRS) */
1408                 break;
1409         case DDI_INTROP_REMISR:
1410                 port = ddi_get_parent_data(rdip);
1411 
1412 #if defined(USE_SOFT_INTRS)
1413                 global = port->i8042_global;
1414                 mutex_enter(&global->i8042_mutex);
1415                 port->soft_hdl = 0;
1416                 mutex_exit(&global->i8042_mutex);
1417 #else   /* defined(USE_SOFT_INTRS) */
1418                 mutex_enter(&port->intr_mutex);
1419                 port->intr_func = NULL;
1420                 mutex_exit(&port->intr_mutex);
1421 #endif  /* defined(USE_SOFT_INTRS) */
1422                 break;
1423         case DDI_INTROP_ENABLE:
1424                 port = ddi_get_parent_data(rdip);
1425 #if defined(USE_SOFT_INTRS)
1426                 global = port->i8042_global;
1427                 mutex_enter(&global->i8042_mutex);
1428                 port->soft_intr_enabled = B_TRUE;
1429                 if (port->wptr != port->rptr)
1430                         (void) ddi_intr_trigger_softint(port->soft_hdl,
1431                             port->intr_arg2);
1432                 mutex_exit(&global->i8042_mutex);
1433 #else   /* defined(USE_SOFT_INTRS) */
1434                 mutex_enter(&port->intr_mutex);
1435                 if (port->wptr != port->rptr)
1436                         port->intr_func(port->intr_arg1, port->intr_arg2);
1437                 mutex_exit(&port->intr_mutex);
1438 #endif  /* defined(USE_SOFT_INTRS) */
1439                 break;
1440         case DDI_INTROP_DISABLE:
1441 #if defined(USE_SOFT_INTRS)
1442                 port = ddi_get_parent_data(rdip);
1443                 global = port->i8042_global;
1444                 mutex_enter(&global->i8042_mutex);
1445                 port->soft_intr_enabled = B_FALSE;
1446                 (void) ddi_intr_remove_softint(port->soft_hdl);
1447                 mutex_exit(&global->i8042_mutex);
1448 #endif  /* defined(USE_SOFT_INTRS) */
1449                 break;
1450         default:
1451                 return (DDI_FAILURE);
1452         }
1453 
1454         return (DDI_SUCCESS);
1455 }
1456 
1457 static int
1458 i8042_ctlops(dev_info_t *dip, dev_info_t *rdip,
1459         ddi_ctl_enum_t op, void *arg, void *result)
1460 {
1461         int     *iprop;
1462         unsigned int    iprop_len;
1463         int     which_port;
1464         char    name[16];
1465         struct i8042    *global;
1466         dev_info_t      *child;
1467 
1468         global = ddi_get_driver_private(dip);
1469 
1470         switch (op) {
1471         case DDI_CTLOPS_INITCHILD:
1472                 child = (dev_info_t *)arg;
1473                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1474                     DDI_PROP_DONTPASS, "reg", &iprop, &iprop_len) !=
1475                     DDI_SUCCESS) {
1476 #if defined(DEBUG)
1477                         cmn_err(CE_WARN, "%s #%d:  Missing 'reg' on %s@???",
1478                             DRIVER_NAME(dip), ddi_get_instance(dip),
1479                             ddi_node_name(child));
1480 #endif
1481                         return (DDI_FAILURE);
1482                 }
1483                 which_port = iprop[0];
1484                 ddi_prop_free((void *)iprop);
1485 
1486                 (void) sprintf(name, "%d", which_port);
1487                 ddi_set_name_addr(child, name);
1488                 ddi_set_parent_data(child,
1489                     (caddr_t)&global->i8042_ports[which_port]);
1490                 return (DDI_SUCCESS);
1491 
1492         case DDI_CTLOPS_UNINITCHILD:
1493                 child = (dev_info_t *)arg;
1494                 ddi_set_name_addr(child, NULL);
1495                 ddi_set_parent_data(child, NULL);
1496                 return (DDI_SUCCESS);
1497 
1498         case DDI_CTLOPS_REPORTDEV:
1499                 cmn_err(CE_CONT, "?8042 device:  %s@%s, %s # %d\n",
1500                     ddi_node_name(rdip), ddi_get_name_addr(rdip),
1501                     DRIVER_NAME(rdip), ddi_get_instance(rdip));
1502                 return (DDI_SUCCESS);
1503 
1504         default:
1505                 return (ddi_ctlops(dip, rdip, op, arg, result));
1506         }
1507         /* NOTREACHED */
1508 }
1509 
1510 #if defined(__i386) || defined(__amd64)
1511 static dev_info_t *
1512 i8042_devi_findchild_by_node_name(dev_info_t *pdip, char *nodename)
1513 {
1514         dev_info_t *child;
1515 
1516         ASSERT(DEVI_BUSY_OWNED(pdip));
1517 
1518         if (nodename == NULL) {
1519                 return ((dev_info_t *)NULL);
1520         }
1521 
1522         for (child = ddi_get_child(pdip); child != NULL;
1523             child = ddi_get_next_sibling(child)) {
1524 
1525                 if (strcmp(ddi_node_name(child), nodename) == 0)
1526                         break;
1527         }
1528         return (child);
1529 }
1530 
1531 static void
1532 alloc_kb_mouse(dev_info_t *i8042_dip, int nodes_needed)
1533 {
1534         dev_info_t *xdip;
1535         int acpi_off = 0;
1536         char *acpi_prop;
1537 
1538         /* don't alloc unless acpi is off */
1539         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
1540             DDI_PROP_DONTPASS, "acpi-enum", &acpi_prop) == DDI_PROP_SUCCESS) {
1541                 if (strcmp("off", acpi_prop) == 0) {
1542                         acpi_off = 1;
1543                 }
1544                 ddi_prop_free(acpi_prop);
1545         }
1546         if (acpi_off == 0) {
1547                 return;
1548         }
1549 
1550         if (nodes_needed & I8042_MOUSE) {
1551                 /* mouse */
1552                 ndi_devi_alloc_sleep(i8042_dip, "mouse",
1553                     (pnode_t)DEVI_SID_NODEID, &xdip);
1554                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1555                     "reg", 1);
1556                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1557                     "interrupts", 2);
1558                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1559                     "compatible", "pnpPNP,f03");
1560                 /*
1561                  * The device_type property does not matter on SPARC.  Retain it
1562                  * on x86 for compatibility with the previous pseudo-prom.
1563                  */
1564                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1565                     "device_type", "mouse");
1566                 (void) ndi_devi_bind_driver(xdip, 0);
1567         }
1568 
1569         if (nodes_needed & I8042_KEYBOARD) {
1570                 /* keyboard */
1571                 ndi_devi_alloc_sleep(i8042_dip, "keyboard",
1572                     (pnode_t)DEVI_SID_NODEID, &xdip);
1573                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1574                     "reg", 0);
1575                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1576                     "interrupts", 1);
1577                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1578                     "compatible", "pnpPNP,303");
1579                 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1580                     "device_type", "keyboard");
1581                 (void) ndi_devi_bind_driver(xdip, 0);
1582         }
1583 }
1584 #endif
1585 
1586 static int
1587 i8042_bus_config(dev_info_t *parent, uint_t flags,
1588     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
1589 {
1590 #if defined(__i386) || defined(__amd64)
1591         int nodes_needed = 0;
1592         int circ;
1593 
1594         /*
1595          * On x86 systems, if ACPI is disabled, the only way the
1596          * keyboard and mouse can be enumerated is by creating them
1597          * manually.  The following code searches for the existence of
1598          * the keyboard and mouse nodes and creates them if they are not
1599          * found.
1600          */
1601         ndi_devi_enter(parent, &circ);
1602         if (i8042_devi_findchild_by_node_name(parent, "keyboard") == NULL)
1603                 nodes_needed |= I8042_KEYBOARD;
1604         if (i8042_devi_findchild_by_node_name(parent, "mouse") == NULL)
1605                 nodes_needed |= I8042_MOUSE;
1606 
1607         /* If the mouse and keyboard nodes do not already exist, create them */
1608         if (nodes_needed)
1609                 alloc_kb_mouse(parent, nodes_needed);
1610         ndi_devi_exit(parent, circ);
1611 #endif
1612         return (ndi_busop_bus_config(parent, flags, op, arg, childp, 0));
1613 }
1614 
1615 static int
1616 i8042_bus_unconfig(dev_info_t *parent, uint_t flags,
1617     ddi_bus_config_op_t op, void *arg)
1618 {
1619         /*
1620          * The NDI_UNCONFIG flag allows the reference count on this nexus to be
1621          * decremented when children's drivers are unloaded, enabling the nexus
1622          * itself to be unloaded.
1623          */
1624         return (ndi_busop_bus_unconfig(parent, flags | NDI_UNCONFIG, op, arg));
1625 }
1626 
1627 #ifdef __sparc
1628 static int
1629 i8042_build_interrupts_property(dev_info_t *dip)
1630 {
1631         dev_info_t *child = ddi_get_child(dip);
1632         uint_t nintr;
1633         int *intrs = NULL;
1634         int interrupts[MAX_INTERRUPTS];
1635         int i = 0;
1636 
1637         /* Walk the children of this node, scanning for interrupts properties */
1638         while (child != NULL && i < MAX_INTERRUPTS) {
1639 
1640                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1641                     DDI_PROP_DONTPASS, "interrupts", &intrs, &nintr)
1642                     == DDI_PROP_SUCCESS && intrs != NULL) {
1643 
1644                         while (nintr > 0 && i < MAX_INTERRUPTS) {
1645                                 interrupts[i++] = intrs[--nintr];
1646                         }
1647                         ddi_prop_free(intrs);
1648                 }
1649 
1650                 child = ddi_get_next_sibling(child);
1651         }
1652 
1653         if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "interrupts",
1654             interrupts, i) != DDI_PROP_SUCCESS) {
1655 
1656                 return (DDI_FAILURE);
1657         }
1658 
1659         /*
1660          * Oh, the humanity. On the platforms on which we need to
1661          * synthesize an interrupts property, we ALSO need to update the
1662          * device_type property, and set it to "serial" in order for the
1663          * correct interrupt PIL to be chosen by the framework.
1664          */
1665         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "device_type", "serial")
1666             != DDI_PROP_SUCCESS) {
1667 
1668                 return (DDI_FAILURE);
1669         }
1670 
1671         return (DDI_SUCCESS);
1672 }
1673 
1674 static boolean_t
1675 i8042_is_polling_platform(void)
1676 {
1677         /*
1678          * Returns true if this platform is one of the platforms
1679          * that has interrupt issues with the PS/2 keyboard/mouse.
1680          */
1681         if (PLATFORM_MATCH("SUNW,UltraAX-"))
1682                 return (B_TRUE);
1683         else
1684                 return (B_FALSE);
1685 }
1686 #endif