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