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