xref: /titanic_51/usr/src/uts/common/io/mouse8042.c (revision fd9cb95cbb2f626355a60efb9d02c5f0a33c10e6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
237c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
247c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
287c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * PS/2 type Mouse Module - Streams
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/param.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
407c478bd9Sstevel@tonic-gate #include <sys/signal.h>
417c478bd9Sstevel@tonic-gate #include <sys/errno.h>
427c478bd9Sstevel@tonic-gate #include <sys/file.h>
437c478bd9Sstevel@tonic-gate #include <sys/termio.h>
447c478bd9Sstevel@tonic-gate #include <sys/stream.h>
457c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
467c478bd9Sstevel@tonic-gate #include <sys/strtty.h>
477c478bd9Sstevel@tonic-gate #include <sys/debug.h>
487c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
497c478bd9Sstevel@tonic-gate #include <sys/stat.h>
507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
517c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #include <sys/promif.h>
547c478bd9Sstevel@tonic-gate #include <sys/cred.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <sys/i8042.h>
577c478bd9Sstevel@tonic-gate #include <sys/note.h>
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define	DRIVER_NAME(dip)	ddi_driver_name(dip)
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #ifdef	DEBUG
627c478bd9Sstevel@tonic-gate #define	MOUSE8042_DEBUG
637c478bd9Sstevel@tonic-gate #endif
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	MOUSE8042_INTERNAL_OPEN(minor)	(((minor) & 0x1) == 1)
667c478bd9Sstevel@tonic-gate #define	MOUSE8042_MINOR_TO_INSTANCE(minor)	((minor) / 2)
677c478bd9Sstevel@tonic-gate #define	MOUSE8042_INTERNAL_MINOR(minor)		((minor) + 1)
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
707c478bd9Sstevel@tonic-gate extern void consconfig_link(major_t major, minor_t minor);
717c478bd9Sstevel@tonic-gate extern int consconfig_unlink(major_t major, minor_t minor);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  *
767c478bd9Sstevel@tonic-gate  * Local Static Data
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate  * We only support one instance.  Yes, it's theoretically possible to
827c478bd9Sstevel@tonic-gate  * plug in more than one, but it's not worth the implementation cost.
837c478bd9Sstevel@tonic-gate  *
847c478bd9Sstevel@tonic-gate  * The introduction of USB keyboards might make it worth reassessing
857c478bd9Sstevel@tonic-gate  * this decision, as they might free up the keyboard port for a second
867c478bd9Sstevel@tonic-gate  * PS/2 style mouse.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate static dev_info_t *mouse8042_dip;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate struct mouse_state {
917c478bd9Sstevel@tonic-gate 	queue_t	*ms_rqp;
927c478bd9Sstevel@tonic-gate 	queue_t	*ms_wqp;
937c478bd9Sstevel@tonic-gate 	ddi_iblock_cookie_t	ms_iblock_cookie;
947c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	ms_handle;
957c478bd9Sstevel@tonic-gate 	uint8_t			*ms_addr;
967c478bd9Sstevel@tonic-gate 	kmutex_t		ms_mutex;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	minor_t			ms_minor;
997c478bd9Sstevel@tonic-gate 	boolean_t		ms_opened;
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
1037c478bd9Sstevel@tonic-gate int mouse8042_debug = 0;
1047c478bd9Sstevel@tonic-gate int mouse8042_debug_minimal = 0;
1057c478bd9Sstevel@tonic-gate #endif
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static uint_t mouse8042_intr(caddr_t arg);
1087c478bd9Sstevel@tonic-gate static int mouse8042_open(queue_t *q, dev_t *devp, int flag, int sflag,
1097c478bd9Sstevel@tonic-gate 		cred_t *cred_p);
1107c478bd9Sstevel@tonic-gate static int mouse8042_close(queue_t *q, int flag, cred_t *cred_p);
1117c478bd9Sstevel@tonic-gate static int mouse8042_wput(queue_t *q, mblk_t *mp);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static int mouse8042_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
1147c478bd9Sstevel@tonic-gate 		void *arg, void **result);
1157c478bd9Sstevel@tonic-gate static int mouse8042_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
1167c478bd9Sstevel@tonic-gate static int mouse8042_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * Streams module info.
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate #define	MODULE_NAME	"mouse8042"
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate static struct module_info	mouse8042_minfo = {
1257c478bd9Sstevel@tonic-gate 	23,		/* Module ID number */
1267c478bd9Sstevel@tonic-gate 	MODULE_NAME,
1277c478bd9Sstevel@tonic-gate 	0, INFPSZ,	/* minimum & maximum packet sizes */
1287c478bd9Sstevel@tonic-gate 	256, 128	/* hi and low water marks */
1297c478bd9Sstevel@tonic-gate };
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate static struct qinit mouse8042_rinit = {
1327c478bd9Sstevel@tonic-gate 	NULL,		/* put */
1337c478bd9Sstevel@tonic-gate 	NULL,		/* service */
1347c478bd9Sstevel@tonic-gate 	mouse8042_open,
1357c478bd9Sstevel@tonic-gate 	mouse8042_close,
1367c478bd9Sstevel@tonic-gate 	NULL,		/* admin */
1377c478bd9Sstevel@tonic-gate 	&mouse8042_minfo,
1387c478bd9Sstevel@tonic-gate 	NULL		/* statistics */
1397c478bd9Sstevel@tonic-gate };
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static struct qinit mouse8042_winit = {
1427c478bd9Sstevel@tonic-gate 	mouse8042_wput,	/* put */
1437c478bd9Sstevel@tonic-gate 	NULL,		/* service */
1447c478bd9Sstevel@tonic-gate 	NULL,		/* open */
1457c478bd9Sstevel@tonic-gate 	NULL,		/* close */
1467c478bd9Sstevel@tonic-gate 	NULL,		/* admin */
1477c478bd9Sstevel@tonic-gate 	&mouse8042_minfo,
1487c478bd9Sstevel@tonic-gate 	NULL		/* statistics */
1497c478bd9Sstevel@tonic-gate };
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate static struct streamtab mouse8042_strinfo = {
1527c478bd9Sstevel@tonic-gate 	&mouse8042_rinit,
1537c478bd9Sstevel@tonic-gate 	&mouse8042_winit,
1547c478bd9Sstevel@tonic-gate 	NULL,		/* muxrinit */
1557c478bd9Sstevel@tonic-gate 	NULL,		/* muxwinit */
1567c478bd9Sstevel@tonic-gate };
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate  * Local Function Declarations
1607c478bd9Sstevel@tonic-gate  */
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate static struct cb_ops	mouse8042_cb_ops = {
1637c478bd9Sstevel@tonic-gate 	nodev,			/* open */
1647c478bd9Sstevel@tonic-gate 	nodev,			/* close */
1657c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
1667c478bd9Sstevel@tonic-gate 	nodev,			/* print */
1677c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
1687c478bd9Sstevel@tonic-gate 	nodev,			/* read */
1697c478bd9Sstevel@tonic-gate 	nodev,			/* write */
1707c478bd9Sstevel@tonic-gate 	nodev,			/* ioctl */
1717c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
1727c478bd9Sstevel@tonic-gate 	nodev,			/* mmap */
1737c478bd9Sstevel@tonic-gate 	nodev,			/* segmap */
1747c478bd9Sstevel@tonic-gate 	nochpoll,		/* poll */
1757c478bd9Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
1767c478bd9Sstevel@tonic-gate 	&mouse8042_strinfo,	/* streamtab  */
1777c478bd9Sstevel@tonic-gate 	D_MP | D_NEW
1787c478bd9Sstevel@tonic-gate };
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static struct dev_ops	mouse8042_ops = {
1827c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev, */
1837c478bd9Sstevel@tonic-gate 	0,			/* refcnt  */
1847c478bd9Sstevel@tonic-gate 	mouse8042_getinfo,	/* getinfo */
1857c478bd9Sstevel@tonic-gate 	nulldev,		/* identify */
1867c478bd9Sstevel@tonic-gate 	nulldev,		/* probe */
1877c478bd9Sstevel@tonic-gate 	mouse8042_attach,	/* attach */
1887c478bd9Sstevel@tonic-gate 	mouse8042_detach,	/* detach */
1897c478bd9Sstevel@tonic-gate 	nodev,			/* reset */
1907c478bd9Sstevel@tonic-gate 	&mouse8042_cb_ops,	/* driver operations */
1917c478bd9Sstevel@tonic-gate 	(struct bus_ops *)0	/* bus operations */
1927c478bd9Sstevel@tonic-gate };
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * This is the loadable module wrapper.
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
2037c478bd9Sstevel@tonic-gate  */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
2067c478bd9Sstevel@tonic-gate 	&mod_driverops, /* Type of module.  This one is a driver */
2077c478bd9Sstevel@tonic-gate 	"PS/2 Mouse %I%, %E%",
2087c478bd9Sstevel@tonic-gate 	&mouse8042_ops,	/* driver ops */
2097c478bd9Sstevel@tonic-gate };
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
2127c478bd9Sstevel@tonic-gate 	MODREV_1,
2137c478bd9Sstevel@tonic-gate 	(void *)&modldrv,
2147c478bd9Sstevel@tonic-gate 	NULL
2157c478bd9Sstevel@tonic-gate };
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate  * This is the driver initialization routine.
2197c478bd9Sstevel@tonic-gate  */
2207c478bd9Sstevel@tonic-gate int
2217c478bd9Sstevel@tonic-gate _init()
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	int	rv;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	rv = mod_install(&modlinkage);
2267c478bd9Sstevel@tonic-gate 	return (rv);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate int
2317c478bd9Sstevel@tonic-gate _fini(void)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate int
2387c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate static int
2447c478bd9Sstevel@tonic-gate mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
247*fd9cb95cSsethg 	mblk_t *mp;
2487c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
2497c478bd9Sstevel@tonic-gate 	static ddi_device_acc_attr_t attr = {
2507c478bd9Sstevel@tonic-gate 		DDI_DEVICE_ATTR_V0,
2517c478bd9Sstevel@tonic-gate 		DDI_NEVERSWAP_ACC,
2527c478bd9Sstevel@tonic-gate 		DDI_STRICTORDER_ACC,
2537c478bd9Sstevel@tonic-gate 	};
2547c478bd9Sstevel@tonic-gate 	int rc;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
2587c478bd9Sstevel@tonic-gate 	if (mouse8042_debug) {
2597c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, MODULE_NAME "_attach entry\n");
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate #endif
2627c478bd9Sstevel@tonic-gate 
263*fd9cb95cSsethg 	if (cmd == DDI_RESUME) {
264*fd9cb95cSsethg 		state = (struct mouse_state *)ddi_get_driver_private(dip);
265*fd9cb95cSsethg 
266*fd9cb95cSsethg 		/*
267*fd9cb95cSsethg 		 * Send a 0xaa 0x00 upstream.
268*fd9cb95cSsethg 		 * This causes the vuid module to reset the mouse.
269*fd9cb95cSsethg 		 */
270*fd9cb95cSsethg 		if (state->ms_rqp != NULL) {
271*fd9cb95cSsethg 			if (mp = allocb(1, BPRI_MED)) {
272*fd9cb95cSsethg 				*mp->b_wptr++ = 0xaa;
273*fd9cb95cSsethg 				putnext(state->ms_rqp, mp);
274*fd9cb95cSsethg 			}
275*fd9cb95cSsethg 			if (mp = allocb(1, BPRI_MED)) {
276*fd9cb95cSsethg 				*mp->b_wptr++ = 0x0;
277*fd9cb95cSsethg 				putnext(state->ms_rqp, mp);
278*fd9cb95cSsethg 			}
279*fd9cb95cSsethg 		}
280*fd9cb95cSsethg 		return (DDI_SUCCESS);
281*fd9cb95cSsethg 	}
282*fd9cb95cSsethg 
2837c478bd9Sstevel@tonic-gate 	if (cmd != DDI_ATTACH)
2847c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (mouse8042_dip != NULL)
2877c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/* allocate and initialize state structure */
2907c478bd9Sstevel@tonic-gate 	state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP);
2917c478bd9Sstevel@tonic-gate 	state->ms_opened = B_FALSE;
2927c478bd9Sstevel@tonic-gate 	ddi_set_driver_private(dip, state);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/*
2957c478bd9Sstevel@tonic-gate 	 * In order to support virtual keyboard/mouse, we should distinguish
2967c478bd9Sstevel@tonic-gate 	 * between internal virtual open and external physical open.
2977c478bd9Sstevel@tonic-gate 	 *
2987c478bd9Sstevel@tonic-gate 	 * When the physical devices are opened by application, they will
2997c478bd9Sstevel@tonic-gate 	 * be unlinked from the virtual device and their data stream will
3007c478bd9Sstevel@tonic-gate 	 * not be sent to the virtual device. When the opened physical
3017c478bd9Sstevel@tonic-gate 	 * devices are closed, they will be relinked to the virtual devices.
3027c478bd9Sstevel@tonic-gate 	 *
3037c478bd9Sstevel@tonic-gate 	 * All these automatic switch between virtual and physical are
3047c478bd9Sstevel@tonic-gate 	 * transparent.
3057c478bd9Sstevel@tonic-gate 	 *
3067c478bd9Sstevel@tonic-gate 	 * So we change minor node numbering scheme to be:
3077c478bd9Sstevel@tonic-gate 	 * 	external node minor num == instance * 2
3087c478bd9Sstevel@tonic-gate 	 *	internal node minor num == instance * 2 + 1
3097c478bd9Sstevel@tonic-gate 	 */
310*fd9cb95cSsethg 	rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2,
3117c478bd9Sstevel@tonic-gate 	    DDI_NT_MOUSE, NULL);
3127c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
3137c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
3147c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT,
3157c478bd9Sstevel@tonic-gate 		    MODULE_NAME "_attach: ddi_create_minor_node failed\n");
3167c478bd9Sstevel@tonic-gate #endif
3177c478bd9Sstevel@tonic-gate 		goto fail_1;
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
3217c478bd9Sstevel@tonic-gate 		    instance * 2 + 1) != DDI_SUCCESS) {
3227c478bd9Sstevel@tonic-gate 		goto fail_2;
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr,
3267c478bd9Sstevel@tonic-gate 		(offset_t)0, (offset_t)0, &attr, &state->ms_handle);
3277c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
3287c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
3297c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, MODULE_NAME "_attach:  can't map registers");
3307c478bd9Sstevel@tonic-gate #endif
3317c478bd9Sstevel@tonic-gate 		goto fail_2;
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie);
3357c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
3367c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
3377c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
3387c478bd9Sstevel@tonic-gate 		    MODULE_NAME "_attach:  Can't get iblock cookie");
3397c478bd9Sstevel@tonic-gate #endif
3407c478bd9Sstevel@tonic-gate 		goto fail_3;
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER,
3447c478bd9Sstevel@tonic-gate 	    state->ms_iblock_cookie);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	rc = ddi_add_intr(dip, 0,
3477c478bd9Sstevel@tonic-gate 		(ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL,
3487c478bd9Sstevel@tonic-gate 		mouse8042_intr, (caddr_t)state);
3497c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
3507c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
3517c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, MODULE_NAME "_attach: cannot add interrupt");
3527c478bd9Sstevel@tonic-gate #endif
3537c478bd9Sstevel@tonic-gate 		goto fail_3;
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	mouse8042_dip = dip;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	/* Now that we're attached, announce our presence to the world. */
3597c478bd9Sstevel@tonic-gate 	ddi_report_dev(dip);
3607c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
3617c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "?%s #%d: version %s\n",
3627c478bd9Sstevel@tonic-gate 	    DRIVER_NAME(dip), ddi_get_instance(dip), "%I% (%E%)");
3637c478bd9Sstevel@tonic-gate #endif
3647c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate fail_3:
3677c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&state->ms_handle);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate fail_2:
3707c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate fail_1:
3737c478bd9Sstevel@tonic-gate 	kmem_free(state, sizeof (struct mouse_state));
3747c478bd9Sstevel@tonic-gate 	return (rc);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3787c478bd9Sstevel@tonic-gate static int
3797c478bd9Sstevel@tonic-gate mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	state = ddi_get_driver_private(dip);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	switch (cmd) {
386*fd9cb95cSsethg 	case DDI_SUSPEND:
387*fd9cb95cSsethg 		return (DDI_SUCCESS);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
3907c478bd9Sstevel@tonic-gate 		ddi_remove_intr(dip, 0, state->ms_iblock_cookie);
3917c478bd9Sstevel@tonic-gate 		mouse8042_dip = NULL;
3927c478bd9Sstevel@tonic-gate 		mutex_destroy(&state->ms_mutex);
3937c478bd9Sstevel@tonic-gate 		ddi_prop_remove_all(dip);
3947c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&state->ms_handle);
3957c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(dip, NULL);
3967c478bd9Sstevel@tonic-gate 		kmem_free(state, sizeof (struct mouse_state));
3977c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	default:
4007c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
4017c478bd9Sstevel@tonic-gate 		if (mouse8042_debug) {
4027c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
4037c478bd9Sstevel@tonic-gate 			    "mouse8042_detach: cmd = %d unknown\n", cmd);
4047c478bd9Sstevel@tonic-gate 		}
4057c478bd9Sstevel@tonic-gate #endif
4067c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate /* ARGSUSED */
4127c478bd9Sstevel@tonic-gate static int
4137c478bd9Sstevel@tonic-gate mouse8042_getinfo(
4147c478bd9Sstevel@tonic-gate     dev_info_t *dip,
4157c478bd9Sstevel@tonic-gate     ddi_info_cmd_t infocmd,
4167c478bd9Sstevel@tonic-gate     void *arg,
4177c478bd9Sstevel@tonic-gate     void **result)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate 	dev_t dev = (dev_t)arg;
4207c478bd9Sstevel@tonic-gate 	minor_t	minor = getminor(dev);
4217c478bd9Sstevel@tonic-gate 	int	instance = MOUSE8042_MINOR_TO_INSTANCE(minor);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
4247c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
4257c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_getinfo: call\n");
4267c478bd9Sstevel@tonic-gate #endif
4277c478bd9Sstevel@tonic-gate 	switch (infocmd) {
4287c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
4297c478bd9Sstevel@tonic-gate 		if (mouse8042_dip == NULL)
4307c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 		*result = (void *)mouse8042_dip;
4337c478bd9Sstevel@tonic-gate 		break;
4347c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
4357c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
4367c478bd9Sstevel@tonic-gate 		break;
4377c478bd9Sstevel@tonic-gate 	default:
4387c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4447c478bd9Sstevel@tonic-gate static int
4457c478bd9Sstevel@tonic-gate mouse8042_open(
4467c478bd9Sstevel@tonic-gate 	queue_t	*q,
4477c478bd9Sstevel@tonic-gate 	dev_t	*devp,
4487c478bd9Sstevel@tonic-gate 	int	flag,
4497c478bd9Sstevel@tonic-gate 	int	sflag,
4507c478bd9Sstevel@tonic-gate 	cred_t	*cred_p)
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
4537c478bd9Sstevel@tonic-gate 	minor_t	minor = getminor(*devp);
4547c478bd9Sstevel@tonic-gate 	int rval;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if (mouse8042_dip == NULL)
4577c478bd9Sstevel@tonic-gate 		return (ENXIO);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	state = ddi_get_driver_private(mouse8042_dip);
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
4627c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
4637c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_open:entered\n");
4647c478bd9Sstevel@tonic-gate #endif
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	if (state->ms_opened) {
4697c478bd9Sstevel@tonic-gate 		/*
4707c478bd9Sstevel@tonic-gate 		 * Exit if the same minor node is already open
4717c478bd9Sstevel@tonic-gate 		 */
4727c478bd9Sstevel@tonic-gate 		if (state->ms_minor == minor) {
4737c478bd9Sstevel@tonic-gate 			mutex_exit(&state->ms_mutex);
4747c478bd9Sstevel@tonic-gate 			return (0);
4757c478bd9Sstevel@tonic-gate 		}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 		/*
4787c478bd9Sstevel@tonic-gate 		 * Check whether it is switch between physical and virtual
4797c478bd9Sstevel@tonic-gate 		 *
4807c478bd9Sstevel@tonic-gate 		 * Opening from virtual while the device is being physically
4817c478bd9Sstevel@tonic-gate 		 * opened by an application should not happen. So we ASSERT
4827c478bd9Sstevel@tonic-gate 		 * this in DEBUG version, and return error in the non-DEBUG
4837c478bd9Sstevel@tonic-gate 		 * case.
4847c478bd9Sstevel@tonic-gate 		 */
4857c478bd9Sstevel@tonic-gate 		ASSERT(!MOUSE8042_INTERNAL_OPEN(minor));
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 		if (MOUSE8042_INTERNAL_OPEN(minor)) {
4887c478bd9Sstevel@tonic-gate 			mutex_exit(&state->ms_mutex);
4897c478bd9Sstevel@tonic-gate 			return (EINVAL);
4907c478bd9Sstevel@tonic-gate 		}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		/*
4937c478bd9Sstevel@tonic-gate 		 * Opening the physical one while it is being underneath
4947c478bd9Sstevel@tonic-gate 		 * the virtual one.
4957c478bd9Sstevel@tonic-gate 		 *
4967c478bd9Sstevel@tonic-gate 		 * consconfig_unlink is called to unlink this device from
4977c478bd9Sstevel@tonic-gate 		 * the virtual one, thus the old stream serving for this
4987c478bd9Sstevel@tonic-gate 		 * device under the virtual one is closed, and then the
4997c478bd9Sstevel@tonic-gate 		 * lower driver's close routine (here is mouse8042_close)
5007c478bd9Sstevel@tonic-gate 		 * is also called to accomplish the whole stream close.
5017c478bd9Sstevel@tonic-gate 		 * Here we have to drop the lock because mouse8042_close
5027c478bd9Sstevel@tonic-gate 		 * also needs the lock.
5037c478bd9Sstevel@tonic-gate 		 *
5047c478bd9Sstevel@tonic-gate 		 * For mouse, the old stream is:
5057c478bd9Sstevel@tonic-gate 		 *	consms->["pushmod"->]"mouse_vp driver"
5067c478bd9Sstevel@tonic-gate 		 *
5077c478bd9Sstevel@tonic-gate 		 * After the consconfig_unlink returns, the old stream is closed
5087c478bd9Sstevel@tonic-gate 		 * and we grab the lock again to reopen this device as normal.
5097c478bd9Sstevel@tonic-gate 		 */
5107c478bd9Sstevel@tonic-gate 		mutex_exit(&state->ms_mutex);
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		/*
5137c478bd9Sstevel@tonic-gate 		 * If unlink fails, fail the physical open.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip),
5167c478bd9Sstevel@tonic-gate 		    MOUSE8042_INTERNAL_MINOR(minor))) != 0) {
5177c478bd9Sstevel@tonic-gate 			return (rval);
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		mutex_enter(&state->ms_mutex);
5217c478bd9Sstevel@tonic-gate 	}
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	q->q_ptr = (caddr_t)state;
5257c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = (caddr_t)state;
5267c478bd9Sstevel@tonic-gate 	state->ms_rqp = q;
5277c478bd9Sstevel@tonic-gate 	state->ms_wqp = WR(q);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	qprocson(q);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	state->ms_minor = minor;
5327c478bd9Sstevel@tonic-gate 	state->ms_opened = B_TRUE;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	return (0);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5417c478bd9Sstevel@tonic-gate static int
5427c478bd9Sstevel@tonic-gate mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
5457c478bd9Sstevel@tonic-gate 	minor_t	minor;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	state = (struct mouse_state *)q->q_ptr;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
5507c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
5517c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_close:entered\n");
5527c478bd9Sstevel@tonic-gate #endif
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	qprocsoff(q);
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	q->q_ptr = NULL;
5597c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = NULL;
5607c478bd9Sstevel@tonic-gate 	state->ms_rqp = NULL;
5617c478bd9Sstevel@tonic-gate 	state->ms_wqp = NULL;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	state->ms_opened = B_FALSE;
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	minor = state->ms_minor;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	if (!MOUSE8042_INTERNAL_OPEN(minor)) {
5707c478bd9Sstevel@tonic-gate 		/*
5717c478bd9Sstevel@tonic-gate 		 * Closing physical PS/2 mouse
5727c478bd9Sstevel@tonic-gate 		 *
5737c478bd9Sstevel@tonic-gate 		 * Link it back to virtual mouse, and
5747c478bd9Sstevel@tonic-gate 		 * mouse8042_open will be called as a result
575*fd9cb95cSsethg 		 * of the consconfig_link call.  Do NOT try
576*fd9cb95cSsethg 		 * this if the mouse is about to be detached!
5777c478bd9Sstevel@tonic-gate 		 *
5787c478bd9Sstevel@tonic-gate 		 * If linking back fails, this specific mouse
5797c478bd9Sstevel@tonic-gate 		 * will not be available underneath the virtual
5807c478bd9Sstevel@tonic-gate 		 * mouse, and can only be accessed via physical
5817c478bd9Sstevel@tonic-gate 		 * open.
5827c478bd9Sstevel@tonic-gate 		 */
5837c478bd9Sstevel@tonic-gate 		consconfig_link(ddi_driver_major(mouse8042_dip),
5847c478bd9Sstevel@tonic-gate 		    MOUSE8042_INTERNAL_MINOR(minor));
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	return (0);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate static void
5917c478bd9Sstevel@tonic-gate mouse8042_iocnack(
5927c478bd9Sstevel@tonic-gate     queue_t *qp,
5937c478bd9Sstevel@tonic-gate     mblk_t *mp,
5947c478bd9Sstevel@tonic-gate     struct iocblk *iocp,
5957c478bd9Sstevel@tonic-gate     int error,
5967c478bd9Sstevel@tonic-gate     int rval)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_IOCNAK;
5997c478bd9Sstevel@tonic-gate 	iocp->ioc_rval = rval;
6007c478bd9Sstevel@tonic-gate 	iocp->ioc_error = error;
6017c478bd9Sstevel@tonic-gate 	qreply(qp, mp);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate static int
6057c478bd9Sstevel@tonic-gate mouse8042_wput(queue_t *q, mblk_t *mp)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	struct iocblk *iocbp;
6087c478bd9Sstevel@tonic-gate 	mblk_t *bp;
6097c478bd9Sstevel@tonic-gate 	mblk_t *next;
6107c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	state = (struct mouse_state *)q->q_ptr;
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
6157c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
6167c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_wput:entered\n");
6177c478bd9Sstevel@tonic-gate #endif
6187c478bd9Sstevel@tonic-gate 	iocbp = (struct iocblk *)mp->b_rptr;
6197c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
6207c478bd9Sstevel@tonic-gate 	case M_FLUSH:
6217c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
6227c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
6237c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_FLUSH\n");
6247c478bd9Sstevel@tonic-gate #endif
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW)
6277c478bd9Sstevel@tonic-gate 			flushq(q, FLUSHDATA);
6287c478bd9Sstevel@tonic-gate 		qreply(q, mp);
6297c478bd9Sstevel@tonic-gate 		break;
6307c478bd9Sstevel@tonic-gate 	case M_IOCTL:
6317c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
6327c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
6337c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_IOCTL\n");
6347c478bd9Sstevel@tonic-gate #endif
6357c478bd9Sstevel@tonic-gate 		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
6367c478bd9Sstevel@tonic-gate 		break;
6377c478bd9Sstevel@tonic-gate 	case M_IOCDATA:
6387c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
6397c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
6407c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_IOCDATA\n");
6417c478bd9Sstevel@tonic-gate #endif
6427c478bd9Sstevel@tonic-gate 		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
6437c478bd9Sstevel@tonic-gate 		break;
6447c478bd9Sstevel@tonic-gate 	case M_DATA:
6457c478bd9Sstevel@tonic-gate 		bp = mp;
6467c478bd9Sstevel@tonic-gate 		do {
6477c478bd9Sstevel@tonic-gate 			while (bp->b_rptr < bp->b_wptr) {
6487c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
6497c478bd9Sstevel@tonic-gate 				if (mouse8042_debug) {
6507c478bd9Sstevel@tonic-gate 					cmn_err(CE_CONT,
6517c478bd9Sstevel@tonic-gate 					    "mouse8042:  send %2x\n",
6527c478bd9Sstevel@tonic-gate 					    *bp->b_rptr);
6537c478bd9Sstevel@tonic-gate 				}
6547c478bd9Sstevel@tonic-gate 				if (mouse8042_debug_minimal) {
6557c478bd9Sstevel@tonic-gate 					cmn_err(CE_CONT, ">a:%2x ",
6567c478bd9Sstevel@tonic-gate 					    *bp->b_rptr);
6577c478bd9Sstevel@tonic-gate 				}
6587c478bd9Sstevel@tonic-gate #endif
6597c478bd9Sstevel@tonic-gate 				ddi_put8(state->ms_handle,
6607c478bd9Sstevel@tonic-gate 					state->ms_addr + I8042_INT_OUTPUT_DATA,
6617c478bd9Sstevel@tonic-gate 					*bp->b_rptr++);
6627c478bd9Sstevel@tonic-gate 			}
6637c478bd9Sstevel@tonic-gate 			next = bp->b_cont;
6647c478bd9Sstevel@tonic-gate 			freeb(bp);
6657c478bd9Sstevel@tonic-gate 		} while ((bp = next) != NULL);
6667c478bd9Sstevel@tonic-gate 		break;
6677c478bd9Sstevel@tonic-gate 	default:
6687c478bd9Sstevel@tonic-gate 		freemsg(mp);
6697c478bd9Sstevel@tonic-gate 		break;
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
6727c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
6737c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_wput:leaving\n");
6747c478bd9Sstevel@tonic-gate #endif
6757c478bd9Sstevel@tonic-gate 	return (0);	/* ignored */
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate static uint_t
6797c478bd9Sstevel@tonic-gate mouse8042_intr(caddr_t arg)
6807c478bd9Sstevel@tonic-gate {
6817c478bd9Sstevel@tonic-gate 	unsigned char    mdata;
6827c478bd9Sstevel@tonic-gate 	mblk_t *mp;
6837c478bd9Sstevel@tonic-gate 	struct mouse_state *state = (struct mouse_state *)arg;
6847c478bd9Sstevel@tonic-gate 	int rc;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
6897c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
6907c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_intr()\n");
6917c478bd9Sstevel@tonic-gate #endif
6927c478bd9Sstevel@tonic-gate 	rc = DDI_INTR_UNCLAIMED;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	for (;;) {
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 		if (ddi_get8(state->ms_handle,
6977c478bd9Sstevel@tonic-gate 			    state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) {
6987c478bd9Sstevel@tonic-gate 			break;
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		mdata = ddi_get8(state->ms_handle,
7027c478bd9Sstevel@tonic-gate 				state->ms_addr + I8042_INT_INPUT_DATA);
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
7057c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
7067c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_intr:  got %2x\n", mdata);
7077c478bd9Sstevel@tonic-gate 		if (mouse8042_debug_minimal)
7087c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "<A:%2x ", mdata);
7097c478bd9Sstevel@tonic-gate #endif
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 		rc = DDI_INTR_CLAIMED;
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 		if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) {
7147c478bd9Sstevel@tonic-gate 			*mp->b_wptr++ = mdata;
7157c478bd9Sstevel@tonic-gate 			putnext(state->ms_rqp, mp);
7167c478bd9Sstevel@tonic-gate 		}
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
7197c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
7207c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_intr() ok\n");
7217c478bd9Sstevel@tonic-gate #endif
7227c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	return (rc);
7257c478bd9Sstevel@tonic-gate }
726