xref: /illumos-gate/usr/src/uts/common/io/i8042.c (revision 86ef0a63)
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(__x86)
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(__x86)
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(__x86)
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