Home | History | Annotate | Download | only in io
      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