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 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
   1687