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