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