xref: /titanic_51/usr/src/uts/common/io/mouse8042.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
23*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
24*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * PS/2 type Mouse Module - Streams
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/termio.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/strtty.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #include <sys/promif.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #include <sys/i8042.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/note.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	DRIVER_NAME(dip)	ddi_driver_name(dip)
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
62*7c478bd9Sstevel@tonic-gate #define	MOUSE8042_DEBUG
63*7c478bd9Sstevel@tonic-gate #endif
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	MOUSE8042_INTERNAL_OPEN(minor)	(((minor) & 0x1) == 1)
66*7c478bd9Sstevel@tonic-gate #define	MOUSE8042_MINOR_TO_INSTANCE(minor)	((minor) / 2)
67*7c478bd9Sstevel@tonic-gate #define	MOUSE8042_INTERNAL_MINOR(minor)		((minor) + 1)
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
70*7c478bd9Sstevel@tonic-gate extern void consconfig_link(major_t major, minor_t minor);
71*7c478bd9Sstevel@tonic-gate extern int consconfig_unlink(major_t major, minor_t minor);
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  *
76*7c478bd9Sstevel@tonic-gate  * Local Static Data
77*7c478bd9Sstevel@tonic-gate  *
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /*
81*7c478bd9Sstevel@tonic-gate  * We only support one instance.  Yes, it's theoretically possible to
82*7c478bd9Sstevel@tonic-gate  * plug in more than one, but it's not worth the implementation cost.
83*7c478bd9Sstevel@tonic-gate  *
84*7c478bd9Sstevel@tonic-gate  * The introduction of USB keyboards might make it worth reassessing
85*7c478bd9Sstevel@tonic-gate  * this decision, as they might free up the keyboard port for a second
86*7c478bd9Sstevel@tonic-gate  * PS/2 style mouse.
87*7c478bd9Sstevel@tonic-gate  */
88*7c478bd9Sstevel@tonic-gate static dev_info_t *mouse8042_dip;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate struct mouse_state {
91*7c478bd9Sstevel@tonic-gate 	queue_t	*ms_rqp;
92*7c478bd9Sstevel@tonic-gate 	queue_t	*ms_wqp;
93*7c478bd9Sstevel@tonic-gate 	ddi_iblock_cookie_t	ms_iblock_cookie;
94*7c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	ms_handle;
95*7c478bd9Sstevel@tonic-gate 	uint8_t			*ms_addr;
96*7c478bd9Sstevel@tonic-gate 	kmutex_t		ms_mutex;
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 	minor_t			ms_minor;
99*7c478bd9Sstevel@tonic-gate 	boolean_t		ms_opened;
100*7c478bd9Sstevel@tonic-gate };
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
103*7c478bd9Sstevel@tonic-gate int mouse8042_debug = 0;
104*7c478bd9Sstevel@tonic-gate int mouse8042_debug_minimal = 0;
105*7c478bd9Sstevel@tonic-gate #endif
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate static uint_t mouse8042_intr(caddr_t arg);
108*7c478bd9Sstevel@tonic-gate static int mouse8042_open(queue_t *q, dev_t *devp, int flag, int sflag,
109*7c478bd9Sstevel@tonic-gate 		cred_t *cred_p);
110*7c478bd9Sstevel@tonic-gate static int mouse8042_close(queue_t *q, int flag, cred_t *cred_p);
111*7c478bd9Sstevel@tonic-gate static int mouse8042_wput(queue_t *q, mblk_t *mp);
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate static int mouse8042_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
114*7c478bd9Sstevel@tonic-gate 		void *arg, void **result);
115*7c478bd9Sstevel@tonic-gate static int mouse8042_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
116*7c478bd9Sstevel@tonic-gate static int mouse8042_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate /*
120*7c478bd9Sstevel@tonic-gate  * Streams module info.
121*7c478bd9Sstevel@tonic-gate  */
122*7c478bd9Sstevel@tonic-gate #define	MODULE_NAME	"mouse8042"
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static struct module_info	mouse8042_minfo = {
125*7c478bd9Sstevel@tonic-gate 	23,		/* Module ID number */
126*7c478bd9Sstevel@tonic-gate 	MODULE_NAME,
127*7c478bd9Sstevel@tonic-gate 	0, INFPSZ,	/* minimum & maximum packet sizes */
128*7c478bd9Sstevel@tonic-gate 	256, 128	/* hi and low water marks */
129*7c478bd9Sstevel@tonic-gate };
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate static struct qinit mouse8042_rinit = {
132*7c478bd9Sstevel@tonic-gate 	NULL,		/* put */
133*7c478bd9Sstevel@tonic-gate 	NULL,		/* service */
134*7c478bd9Sstevel@tonic-gate 	mouse8042_open,
135*7c478bd9Sstevel@tonic-gate 	mouse8042_close,
136*7c478bd9Sstevel@tonic-gate 	NULL,		/* admin */
137*7c478bd9Sstevel@tonic-gate 	&mouse8042_minfo,
138*7c478bd9Sstevel@tonic-gate 	NULL		/* statistics */
139*7c478bd9Sstevel@tonic-gate };
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate static struct qinit mouse8042_winit = {
142*7c478bd9Sstevel@tonic-gate 	mouse8042_wput,	/* put */
143*7c478bd9Sstevel@tonic-gate 	NULL,		/* service */
144*7c478bd9Sstevel@tonic-gate 	NULL,		/* open */
145*7c478bd9Sstevel@tonic-gate 	NULL,		/* close */
146*7c478bd9Sstevel@tonic-gate 	NULL,		/* admin */
147*7c478bd9Sstevel@tonic-gate 	&mouse8042_minfo,
148*7c478bd9Sstevel@tonic-gate 	NULL		/* statistics */
149*7c478bd9Sstevel@tonic-gate };
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate static struct streamtab mouse8042_strinfo = {
152*7c478bd9Sstevel@tonic-gate 	&mouse8042_rinit,
153*7c478bd9Sstevel@tonic-gate 	&mouse8042_winit,
154*7c478bd9Sstevel@tonic-gate 	NULL,		/* muxrinit */
155*7c478bd9Sstevel@tonic-gate 	NULL,		/* muxwinit */
156*7c478bd9Sstevel@tonic-gate };
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate /*
159*7c478bd9Sstevel@tonic-gate  * Local Function Declarations
160*7c478bd9Sstevel@tonic-gate  */
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate static struct cb_ops	mouse8042_cb_ops = {
163*7c478bd9Sstevel@tonic-gate 	nodev,			/* open */
164*7c478bd9Sstevel@tonic-gate 	nodev,			/* close */
165*7c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
166*7c478bd9Sstevel@tonic-gate 	nodev,			/* print */
167*7c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
168*7c478bd9Sstevel@tonic-gate 	nodev,			/* read */
169*7c478bd9Sstevel@tonic-gate 	nodev,			/* write */
170*7c478bd9Sstevel@tonic-gate 	nodev,			/* ioctl */
171*7c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
172*7c478bd9Sstevel@tonic-gate 	nodev,			/* mmap */
173*7c478bd9Sstevel@tonic-gate 	nodev,			/* segmap */
174*7c478bd9Sstevel@tonic-gate 	nochpoll,		/* poll */
175*7c478bd9Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
176*7c478bd9Sstevel@tonic-gate 	&mouse8042_strinfo,	/* streamtab  */
177*7c478bd9Sstevel@tonic-gate 	D_MP | D_NEW
178*7c478bd9Sstevel@tonic-gate };
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate static struct dev_ops	mouse8042_ops = {
182*7c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev, */
183*7c478bd9Sstevel@tonic-gate 	0,			/* refcnt  */
184*7c478bd9Sstevel@tonic-gate 	mouse8042_getinfo,	/* getinfo */
185*7c478bd9Sstevel@tonic-gate 	nulldev,		/* identify */
186*7c478bd9Sstevel@tonic-gate 	nulldev,		/* probe */
187*7c478bd9Sstevel@tonic-gate 	mouse8042_attach,	/* attach */
188*7c478bd9Sstevel@tonic-gate 	mouse8042_detach,	/* detach */
189*7c478bd9Sstevel@tonic-gate 	nodev,			/* reset */
190*7c478bd9Sstevel@tonic-gate 	&mouse8042_cb_ops,	/* driver operations */
191*7c478bd9Sstevel@tonic-gate 	(struct bus_ops *)0	/* bus operations */
192*7c478bd9Sstevel@tonic-gate };
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate /*
195*7c478bd9Sstevel@tonic-gate  * This is the loadable module wrapper.
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate /*
202*7c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
203*7c478bd9Sstevel@tonic-gate  */
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
206*7c478bd9Sstevel@tonic-gate 	&mod_driverops, /* Type of module.  This one is a driver */
207*7c478bd9Sstevel@tonic-gate 	"PS/2 Mouse %I%, %E%",
208*7c478bd9Sstevel@tonic-gate 	&mouse8042_ops,	/* driver ops */
209*7c478bd9Sstevel@tonic-gate };
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
212*7c478bd9Sstevel@tonic-gate 	MODREV_1,
213*7c478bd9Sstevel@tonic-gate 	(void *)&modldrv,
214*7c478bd9Sstevel@tonic-gate 	NULL
215*7c478bd9Sstevel@tonic-gate };
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * This is the driver initialization routine.
219*7c478bd9Sstevel@tonic-gate  */
220*7c478bd9Sstevel@tonic-gate int
221*7c478bd9Sstevel@tonic-gate _init()
222*7c478bd9Sstevel@tonic-gate {
223*7c478bd9Sstevel@tonic-gate 	int	rv;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	rv = mod_install(&modlinkage);
226*7c478bd9Sstevel@tonic-gate 	return (rv);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate int
231*7c478bd9Sstevel@tonic-gate _fini(void)
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate int
238*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate static int
244*7c478bd9Sstevel@tonic-gate mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
245*7c478bd9Sstevel@tonic-gate {
246*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
247*7c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
248*7c478bd9Sstevel@tonic-gate 	static ddi_device_acc_attr_t attr = {
249*7c478bd9Sstevel@tonic-gate 		DDI_DEVICE_ATTR_V0,
250*7c478bd9Sstevel@tonic-gate 		DDI_NEVERSWAP_ACC,
251*7c478bd9Sstevel@tonic-gate 		DDI_STRICTORDER_ACC,
252*7c478bd9Sstevel@tonic-gate 	};
253*7c478bd9Sstevel@tonic-gate 	int rc;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
257*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug) {
258*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, MODULE_NAME "_attach entry\n");
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate #endif
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	if (cmd != DDI_ATTACH)
263*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	if (mouse8042_dip != NULL)
266*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	/* allocate and initialize state structure */
269*7c478bd9Sstevel@tonic-gate 	state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP);
270*7c478bd9Sstevel@tonic-gate 	state->ms_opened = B_FALSE;
271*7c478bd9Sstevel@tonic-gate 	ddi_set_driver_private(dip, state);
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	/*
274*7c478bd9Sstevel@tonic-gate 	 * In order to support virtual keyboard/mouse, we should distinguish
275*7c478bd9Sstevel@tonic-gate 	 * between internal virtual open and external physical open.
276*7c478bd9Sstevel@tonic-gate 	 *
277*7c478bd9Sstevel@tonic-gate 	 * When the physical devices are opened by application, they will
278*7c478bd9Sstevel@tonic-gate 	 * be unlinked from the virtual device and their data stream will
279*7c478bd9Sstevel@tonic-gate 	 * not be sent to the virtual device. When the opened physical
280*7c478bd9Sstevel@tonic-gate 	 * devices are closed, they will be relinked to the virtual devices.
281*7c478bd9Sstevel@tonic-gate 	 *
282*7c478bd9Sstevel@tonic-gate 	 * All these automatic switch between virtual and physical are
283*7c478bd9Sstevel@tonic-gate 	 * transparent.
284*7c478bd9Sstevel@tonic-gate 	 *
285*7c478bd9Sstevel@tonic-gate 	 * So we change minor node numbering scheme to be:
286*7c478bd9Sstevel@tonic-gate 	 * 	external node minor num == instance * 2
287*7c478bd9Sstevel@tonic-gate 	 *	internal node minor num == instance * 2 + 1
288*7c478bd9Sstevel@tonic-gate 	 */
289*7c478bd9Sstevel@tonic-gate 	rc = ddi_create_minor_node(dip, "l", S_IFCHR, instance * 2,
290*7c478bd9Sstevel@tonic-gate 	    DDI_NT_MOUSE, NULL);
291*7c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
292*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
293*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT,
294*7c478bd9Sstevel@tonic-gate 		    MODULE_NAME "_attach: ddi_create_minor_node failed\n");
295*7c478bd9Sstevel@tonic-gate #endif
296*7c478bd9Sstevel@tonic-gate 		goto fail_1;
297*7c478bd9Sstevel@tonic-gate 	}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
300*7c478bd9Sstevel@tonic-gate 		    instance * 2 + 1) != DDI_SUCCESS) {
301*7c478bd9Sstevel@tonic-gate 		goto fail_2;
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr,
305*7c478bd9Sstevel@tonic-gate 		(offset_t)0, (offset_t)0, &attr, &state->ms_handle);
306*7c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
307*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
308*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, MODULE_NAME "_attach:  can't map registers");
309*7c478bd9Sstevel@tonic-gate #endif
310*7c478bd9Sstevel@tonic-gate 		goto fail_2;
311*7c478bd9Sstevel@tonic-gate 	}
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie);
314*7c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
315*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
316*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,
317*7c478bd9Sstevel@tonic-gate 		    MODULE_NAME "_attach:  Can't get iblock cookie");
318*7c478bd9Sstevel@tonic-gate #endif
319*7c478bd9Sstevel@tonic-gate 		goto fail_3;
320*7c478bd9Sstevel@tonic-gate 	}
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER,
323*7c478bd9Sstevel@tonic-gate 	    state->ms_iblock_cookie);
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	rc = ddi_add_intr(dip, 0,
326*7c478bd9Sstevel@tonic-gate 		(ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL,
327*7c478bd9Sstevel@tonic-gate 		mouse8042_intr, (caddr_t)state);
328*7c478bd9Sstevel@tonic-gate 	if (rc != DDI_SUCCESS) {
329*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
330*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, MODULE_NAME "_attach: cannot add interrupt");
331*7c478bd9Sstevel@tonic-gate #endif
332*7c478bd9Sstevel@tonic-gate 		goto fail_3;
333*7c478bd9Sstevel@tonic-gate 	}
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	mouse8042_dip = dip;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	/* Now that we're attached, announce our presence to the world. */
338*7c478bd9Sstevel@tonic-gate 	ddi_report_dev(dip);
339*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
340*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "?%s #%d: version %s\n",
341*7c478bd9Sstevel@tonic-gate 	    DRIVER_NAME(dip), ddi_get_instance(dip), "%I% (%E%)");
342*7c478bd9Sstevel@tonic-gate #endif
343*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate fail_3:
346*7c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&state->ms_handle);
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate fail_2:
349*7c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(dip, NULL);
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate fail_1:
352*7c478bd9Sstevel@tonic-gate 	kmem_free(state, sizeof (struct mouse_state));
353*7c478bd9Sstevel@tonic-gate 	return (rc);
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
357*7c478bd9Sstevel@tonic-gate static int
358*7c478bd9Sstevel@tonic-gate mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
359*7c478bd9Sstevel@tonic-gate {
360*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	state = ddi_get_driver_private(dip);
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
367*7c478bd9Sstevel@tonic-gate 		ddi_remove_intr(dip, 0, state->ms_iblock_cookie);
368*7c478bd9Sstevel@tonic-gate 		mouse8042_dip = NULL;
369*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&state->ms_mutex);
370*7c478bd9Sstevel@tonic-gate 		ddi_prop_remove_all(dip);
371*7c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&state->ms_handle);
372*7c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(dip, NULL);
373*7c478bd9Sstevel@tonic-gate 		kmem_free(state, sizeof (struct mouse_state));
374*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	default:
377*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
378*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug) {
379*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
380*7c478bd9Sstevel@tonic-gate 			    "mouse8042_detach: cmd = %d unknown\n", cmd);
381*7c478bd9Sstevel@tonic-gate 		}
382*7c478bd9Sstevel@tonic-gate #endif
383*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
384*7c478bd9Sstevel@tonic-gate 	}
385*7c478bd9Sstevel@tonic-gate }
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
389*7c478bd9Sstevel@tonic-gate static int
390*7c478bd9Sstevel@tonic-gate mouse8042_getinfo(
391*7c478bd9Sstevel@tonic-gate     dev_info_t *dip,
392*7c478bd9Sstevel@tonic-gate     ddi_info_cmd_t infocmd,
393*7c478bd9Sstevel@tonic-gate     void *arg,
394*7c478bd9Sstevel@tonic-gate     void **result)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate 	dev_t dev = (dev_t)arg;
397*7c478bd9Sstevel@tonic-gate 	minor_t	minor = getminor(dev);
398*7c478bd9Sstevel@tonic-gate 	int	instance = MOUSE8042_MINOR_TO_INSTANCE(minor);
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
401*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
402*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_getinfo: call\n");
403*7c478bd9Sstevel@tonic-gate #endif
404*7c478bd9Sstevel@tonic-gate 	switch (infocmd) {
405*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
406*7c478bd9Sstevel@tonic-gate 		if (mouse8042_dip == NULL)
407*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 		*result = (void *)mouse8042_dip;
410*7c478bd9Sstevel@tonic-gate 		break;
411*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
412*7c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
413*7c478bd9Sstevel@tonic-gate 		break;
414*7c478bd9Sstevel@tonic-gate 	default:
415*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
418*7c478bd9Sstevel@tonic-gate }
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
421*7c478bd9Sstevel@tonic-gate static int
422*7c478bd9Sstevel@tonic-gate mouse8042_open(
423*7c478bd9Sstevel@tonic-gate 	queue_t	*q,
424*7c478bd9Sstevel@tonic-gate 	dev_t	*devp,
425*7c478bd9Sstevel@tonic-gate 	int	flag,
426*7c478bd9Sstevel@tonic-gate 	int	sflag,
427*7c478bd9Sstevel@tonic-gate 	cred_t	*cred_p)
428*7c478bd9Sstevel@tonic-gate {
429*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
430*7c478bd9Sstevel@tonic-gate 	minor_t	minor = getminor(*devp);
431*7c478bd9Sstevel@tonic-gate 	int rval;
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	if (mouse8042_dip == NULL)
434*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	state = ddi_get_driver_private(mouse8042_dip);
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
439*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
440*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_open:entered\n");
441*7c478bd9Sstevel@tonic-gate #endif
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	if (state->ms_opened) {
446*7c478bd9Sstevel@tonic-gate 		/*
447*7c478bd9Sstevel@tonic-gate 		 * Exit if the same minor node is already open
448*7c478bd9Sstevel@tonic-gate 		 */
449*7c478bd9Sstevel@tonic-gate 		if (state->ms_minor == minor) {
450*7c478bd9Sstevel@tonic-gate 			mutex_exit(&state->ms_mutex);
451*7c478bd9Sstevel@tonic-gate 			return (0);
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 		/*
455*7c478bd9Sstevel@tonic-gate 		 * Check whether it is switch between physical and virtual
456*7c478bd9Sstevel@tonic-gate 		 *
457*7c478bd9Sstevel@tonic-gate 		 * Opening from virtual while the device is being physically
458*7c478bd9Sstevel@tonic-gate 		 * opened by an application should not happen. So we ASSERT
459*7c478bd9Sstevel@tonic-gate 		 * this in DEBUG version, and return error in the non-DEBUG
460*7c478bd9Sstevel@tonic-gate 		 * case.
461*7c478bd9Sstevel@tonic-gate 		 */
462*7c478bd9Sstevel@tonic-gate 		ASSERT(!MOUSE8042_INTERNAL_OPEN(minor));
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 		if (MOUSE8042_INTERNAL_OPEN(minor)) {
465*7c478bd9Sstevel@tonic-gate 			mutex_exit(&state->ms_mutex);
466*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
467*7c478bd9Sstevel@tonic-gate 		}
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 		/*
470*7c478bd9Sstevel@tonic-gate 		 * Opening the physical one while it is being underneath
471*7c478bd9Sstevel@tonic-gate 		 * the virtual one.
472*7c478bd9Sstevel@tonic-gate 		 *
473*7c478bd9Sstevel@tonic-gate 		 * consconfig_unlink is called to unlink this device from
474*7c478bd9Sstevel@tonic-gate 		 * the virtual one, thus the old stream serving for this
475*7c478bd9Sstevel@tonic-gate 		 * device under the virtual one is closed, and then the
476*7c478bd9Sstevel@tonic-gate 		 * lower driver's close routine (here is mouse8042_close)
477*7c478bd9Sstevel@tonic-gate 		 * is also called to accomplish the whole stream close.
478*7c478bd9Sstevel@tonic-gate 		 * Here we have to drop the lock because mouse8042_close
479*7c478bd9Sstevel@tonic-gate 		 * also needs the lock.
480*7c478bd9Sstevel@tonic-gate 		 *
481*7c478bd9Sstevel@tonic-gate 		 * For mouse, the old stream is:
482*7c478bd9Sstevel@tonic-gate 		 *	consms->["pushmod"->]"mouse_vp driver"
483*7c478bd9Sstevel@tonic-gate 		 *
484*7c478bd9Sstevel@tonic-gate 		 * After the consconfig_unlink returns, the old stream is closed
485*7c478bd9Sstevel@tonic-gate 		 * and we grab the lock again to reopen this device as normal.
486*7c478bd9Sstevel@tonic-gate 		 */
487*7c478bd9Sstevel@tonic-gate 		mutex_exit(&state->ms_mutex);
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 		/*
490*7c478bd9Sstevel@tonic-gate 		 * If unlink fails, fail the physical open.
491*7c478bd9Sstevel@tonic-gate 		 */
492*7c478bd9Sstevel@tonic-gate 		if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip),
493*7c478bd9Sstevel@tonic-gate 		    MOUSE8042_INTERNAL_MINOR(minor))) != 0) {
494*7c478bd9Sstevel@tonic-gate 			return (rval);
495*7c478bd9Sstevel@tonic-gate 		}
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 		mutex_enter(&state->ms_mutex);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	q->q_ptr = (caddr_t)state;
502*7c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = (caddr_t)state;
503*7c478bd9Sstevel@tonic-gate 	state->ms_rqp = q;
504*7c478bd9Sstevel@tonic-gate 	state->ms_wqp = WR(q);
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	qprocson(q);
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	state->ms_minor = minor;
509*7c478bd9Sstevel@tonic-gate 	state->ms_opened = B_TRUE;
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	return (0);
514*7c478bd9Sstevel@tonic-gate }
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
518*7c478bd9Sstevel@tonic-gate static int
519*7c478bd9Sstevel@tonic-gate mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
520*7c478bd9Sstevel@tonic-gate {
521*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
522*7c478bd9Sstevel@tonic-gate 	minor_t	minor;
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	state = (struct mouse_state *)q->q_ptr;
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
527*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
528*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_close:entered\n");
529*7c478bd9Sstevel@tonic-gate #endif
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	qprocsoff(q);
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 	q->q_ptr = NULL;
536*7c478bd9Sstevel@tonic-gate 	WR(q)->q_ptr = NULL;
537*7c478bd9Sstevel@tonic-gate 	state->ms_rqp = NULL;
538*7c478bd9Sstevel@tonic-gate 	state->ms_wqp = NULL;
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	state->ms_opened = B_FALSE;
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	minor = state->ms_minor;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	if (!MOUSE8042_INTERNAL_OPEN(minor)) {
547*7c478bd9Sstevel@tonic-gate 		/*
548*7c478bd9Sstevel@tonic-gate 		 * Closing physical PS/2 mouse
549*7c478bd9Sstevel@tonic-gate 		 *
550*7c478bd9Sstevel@tonic-gate 		 * Link it back to virtual mouse, and
551*7c478bd9Sstevel@tonic-gate 		 * mouse8042_open will be called as a result
552*7c478bd9Sstevel@tonic-gate 		 * of the consconfig_link call.
553*7c478bd9Sstevel@tonic-gate 		 *
554*7c478bd9Sstevel@tonic-gate 		 * If linking back fails, this specific mouse
555*7c478bd9Sstevel@tonic-gate 		 * will not be available underneath the virtual
556*7c478bd9Sstevel@tonic-gate 		 * mouse, and can only be accessed via physical
557*7c478bd9Sstevel@tonic-gate 		 * open.
558*7c478bd9Sstevel@tonic-gate 		 */
559*7c478bd9Sstevel@tonic-gate 		consconfig_link(ddi_driver_major(mouse8042_dip),
560*7c478bd9Sstevel@tonic-gate 		    MOUSE8042_INTERNAL_MINOR(minor));
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	return (0);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate static void
567*7c478bd9Sstevel@tonic-gate mouse8042_iocnack(
568*7c478bd9Sstevel@tonic-gate     queue_t *qp,
569*7c478bd9Sstevel@tonic-gate     mblk_t *mp,
570*7c478bd9Sstevel@tonic-gate     struct iocblk *iocp,
571*7c478bd9Sstevel@tonic-gate     int error,
572*7c478bd9Sstevel@tonic-gate     int rval)
573*7c478bd9Sstevel@tonic-gate {
574*7c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_IOCNAK;
575*7c478bd9Sstevel@tonic-gate 	iocp->ioc_rval = rval;
576*7c478bd9Sstevel@tonic-gate 	iocp->ioc_error = error;
577*7c478bd9Sstevel@tonic-gate 	qreply(qp, mp);
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate static int
581*7c478bd9Sstevel@tonic-gate mouse8042_wput(queue_t *q, mblk_t *mp)
582*7c478bd9Sstevel@tonic-gate {
583*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocbp;
584*7c478bd9Sstevel@tonic-gate 	mblk_t *bp;
585*7c478bd9Sstevel@tonic-gate 	mblk_t *next;
586*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state;
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	state = (struct mouse_state *)q->q_ptr;
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
591*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
592*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_wput:entered\n");
593*7c478bd9Sstevel@tonic-gate #endif
594*7c478bd9Sstevel@tonic-gate 	iocbp = (struct iocblk *)mp->b_rptr;
595*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
596*7c478bd9Sstevel@tonic-gate 	case M_FLUSH:
597*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
598*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
599*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_FLUSH\n");
600*7c478bd9Sstevel@tonic-gate #endif
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW)
603*7c478bd9Sstevel@tonic-gate 			flushq(q, FLUSHDATA);
604*7c478bd9Sstevel@tonic-gate 		qreply(q, mp);
605*7c478bd9Sstevel@tonic-gate 		break;
606*7c478bd9Sstevel@tonic-gate 	case M_IOCTL:
607*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
608*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
609*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_IOCTL\n");
610*7c478bd9Sstevel@tonic-gate #endif
611*7c478bd9Sstevel@tonic-gate 		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
612*7c478bd9Sstevel@tonic-gate 		break;
613*7c478bd9Sstevel@tonic-gate 	case M_IOCDATA:
614*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
615*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
616*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_wput:M_IOCDATA\n");
617*7c478bd9Sstevel@tonic-gate #endif
618*7c478bd9Sstevel@tonic-gate 		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
619*7c478bd9Sstevel@tonic-gate 		break;
620*7c478bd9Sstevel@tonic-gate 	case M_DATA:
621*7c478bd9Sstevel@tonic-gate 		bp = mp;
622*7c478bd9Sstevel@tonic-gate 		do {
623*7c478bd9Sstevel@tonic-gate 			while (bp->b_rptr < bp->b_wptr) {
624*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
625*7c478bd9Sstevel@tonic-gate 				if (mouse8042_debug) {
626*7c478bd9Sstevel@tonic-gate 					cmn_err(CE_CONT,
627*7c478bd9Sstevel@tonic-gate 					    "mouse8042:  send %2x\n",
628*7c478bd9Sstevel@tonic-gate 					    *bp->b_rptr);
629*7c478bd9Sstevel@tonic-gate 				}
630*7c478bd9Sstevel@tonic-gate 				if (mouse8042_debug_minimal) {
631*7c478bd9Sstevel@tonic-gate 					cmn_err(CE_CONT, ">a:%2x ",
632*7c478bd9Sstevel@tonic-gate 					    *bp->b_rptr);
633*7c478bd9Sstevel@tonic-gate 				}
634*7c478bd9Sstevel@tonic-gate #endif
635*7c478bd9Sstevel@tonic-gate 				ddi_put8(state->ms_handle,
636*7c478bd9Sstevel@tonic-gate 					state->ms_addr + I8042_INT_OUTPUT_DATA,
637*7c478bd9Sstevel@tonic-gate 					*bp->b_rptr++);
638*7c478bd9Sstevel@tonic-gate 			}
639*7c478bd9Sstevel@tonic-gate 			next = bp->b_cont;
640*7c478bd9Sstevel@tonic-gate 			freeb(bp);
641*7c478bd9Sstevel@tonic-gate 		} while ((bp = next) != NULL);
642*7c478bd9Sstevel@tonic-gate 		break;
643*7c478bd9Sstevel@tonic-gate 	default:
644*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
645*7c478bd9Sstevel@tonic-gate 		break;
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
648*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
649*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_wput:leaving\n");
650*7c478bd9Sstevel@tonic-gate #endif
651*7c478bd9Sstevel@tonic-gate 	return (0);	/* ignored */
652*7c478bd9Sstevel@tonic-gate }
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate static uint_t
655*7c478bd9Sstevel@tonic-gate mouse8042_intr(caddr_t arg)
656*7c478bd9Sstevel@tonic-gate {
657*7c478bd9Sstevel@tonic-gate 	unsigned char    mdata;
658*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
659*7c478bd9Sstevel@tonic-gate 	struct mouse_state *state = (struct mouse_state *)arg;
660*7c478bd9Sstevel@tonic-gate 	int rc;
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate 	mutex_enter(&state->ms_mutex);
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
665*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
666*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_intr()\n");
667*7c478bd9Sstevel@tonic-gate #endif
668*7c478bd9Sstevel@tonic-gate 	rc = DDI_INTR_UNCLAIMED;
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate 	for (;;) {
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 		if (ddi_get8(state->ms_handle,
673*7c478bd9Sstevel@tonic-gate 			    state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) {
674*7c478bd9Sstevel@tonic-gate 			break;
675*7c478bd9Sstevel@tonic-gate 		}
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 		mdata = ddi_get8(state->ms_handle,
678*7c478bd9Sstevel@tonic-gate 				state->ms_addr + I8042_INT_INPUT_DATA);
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate #if	defined(MOUSE8042_DEBUG)
681*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug)
682*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "mouse8042_intr:  got %2x\n", mdata);
683*7c478bd9Sstevel@tonic-gate 		if (mouse8042_debug_minimal)
684*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "<A:%2x ", mdata);
685*7c478bd9Sstevel@tonic-gate #endif
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 		rc = DDI_INTR_CLAIMED;
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 		if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) {
690*7c478bd9Sstevel@tonic-gate 			*mp->b_wptr++ = mdata;
691*7c478bd9Sstevel@tonic-gate 			putnext(state->ms_rqp, mp);
692*7c478bd9Sstevel@tonic-gate 		}
693*7c478bd9Sstevel@tonic-gate 	}
694*7c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG
695*7c478bd9Sstevel@tonic-gate 	if (mouse8042_debug)
696*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "mouse8042_intr() ok\n");
697*7c478bd9Sstevel@tonic-gate #endif
698*7c478bd9Sstevel@tonic-gate 	mutex_exit(&state->ms_mutex);
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	return (rc);
701*7c478bd9Sstevel@tonic-gate }
702