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