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