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/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
22/*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
23/*	  All Rights Reserved  	*/
24
25/*
26 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
27 * Use is subject to license terms.
28 */
29
30
31/*
32 * PS/2 type Mouse Module - Streams
33 */
34
35#include <sys/param.h>
36#include <sys/types.h>
37#include <sys/kmem.h>
38#include <sys/signal.h>
39#include <sys/errno.h>
40#include <sys/file.h>
41#include <sys/termio.h>
42#include <sys/stream.h>
43#include <sys/stropts.h>
44#include <sys/strtty.h>
45#include <sys/strsun.h>
46#include <sys/debug.h>
47#include <sys/ddi.h>
48#include <sys/stat.h>
49#include <sys/cmn_err.h>
50#include <sys/sunddi.h>
51
52#include <sys/promif.h>
53#include <sys/cred.h>
54
55#include <sys/i8042.h>
56#include <sys/note.h>
57#include <sys/mouse.h>
58
59#define	DRIVER_NAME(dip)	ddi_driver_name(dip)
60
61#define	MOUSE8042_INTERNAL_OPEN(minor)	(((minor) & 0x1) == 1)
62#define	MOUSE8042_MINOR_TO_INSTANCE(minor)	((minor) / 2)
63#define	MOUSE8042_INTERNAL_MINOR(minor)		((minor) + 1)
64
65#define	MOUSE8042_RESET_TIMEOUT_USECS	500000	/* 500 ms */
66
67extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
68extern void consconfig_link(major_t major, minor_t minor);
69extern int consconfig_unlink(major_t major, minor_t minor);
70
71
72/*
73 *
74 * Local Static Data
75 *
76 */
77
78/*
79 * We only support one instance.  Yes, it's theoretically possible to
80 * plug in more than one, but it's not worth the implementation cost.
81 *
82 * The introduction of USB keyboards might make it worth reassessing
83 * this decision, as they might free up the keyboard port for a second
84 * PS/2 style mouse.
85 */
86static dev_info_t *mouse8042_dip;
87
88/*
89 * RESET states
90 */
91typedef enum {
92	MSE_RESET_IDLE,	/* No reset in progress */
93	MSE_RESET_PRE,	/* Send reset, waiting for ACK */
94	MSE_RESET_ACK,	/* Got ACK, waiting for 0xAA */
95	MSE_RESET_AA,	/* Got 0xAA, waiting for 0x00 */
96	MSE_RESET_FAILED
97} mouse8042_reset_state_e;
98
99struct mouse_state {
100	queue_t	*ms_rqp;
101	queue_t	*ms_wqp;
102	ddi_iblock_cookie_t	ms_iblock_cookie;
103	ddi_acc_handle_t	ms_handle;
104	uint8_t			*ms_addr;
105	kmutex_t		ms_mutex;
106
107	minor_t			ms_minor;
108	boolean_t		ms_opened;
109	kmutex_t		reset_mutex;
110	kcondvar_t		reset_cv;
111	mouse8042_reset_state_e	reset_state;
112	timeout_id_t		reset_tid;
113	int			ready;
114	mblk_t			*reply_mp;
115	mblk_t			*reset_ack_mp;
116	bufcall_id_t		bc_id;
117};
118
119static uint_t mouse8042_intr(caddr_t arg);
120static int mouse8042_open(queue_t *q, dev_t *devp, int flag, int sflag,
121		cred_t *cred_p);
122static int mouse8042_close(queue_t *q, int flag, cred_t *cred_p);
123static int mouse8042_wsrv(queue_t *qp);
124static int mouse8042_wput(queue_t *q, mblk_t *mp);
125
126static int mouse8042_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
127		void *arg, void **result);
128static int mouse8042_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
129static int mouse8042_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
130
131
132/*
133 * Streams module info.
134 */
135#define	MODULE_NAME	"mouse8042"
136
137static struct module_info	mouse8042_minfo = {
138	23,		/* Module ID number */
139	MODULE_NAME,
140	0, INFPSZ,	/* minimum & maximum packet sizes */
141	256, 128	/* hi and low water marks */
142};
143
144static struct qinit mouse8042_rinit = {
145	NULL,		/* put */
146	NULL,		/* service */
147	mouse8042_open,
148	mouse8042_close,
149	NULL,		/* admin */
150	&mouse8042_minfo,
151	NULL		/* statistics */
152};
153
154static struct qinit mouse8042_winit = {
155	mouse8042_wput,	/* put */
156	mouse8042_wsrv,	/* service */
157	NULL,		/* open */
158	NULL,		/* close */
159	NULL,		/* admin */
160	&mouse8042_minfo,
161	NULL		/* statistics */
162};
163
164static struct streamtab mouse8042_strinfo = {
165	&mouse8042_rinit,
166	&mouse8042_winit,
167	NULL,		/* muxrinit */
168	NULL,		/* muxwinit */
169};
170
171/*
172 * Local Function Declarations
173 */
174
175static struct cb_ops	mouse8042_cb_ops = {
176	nodev,			/* open */
177	nodev,			/* close */
178	nodev,			/* strategy */
179	nodev,			/* print */
180	nodev,			/* dump */
181	nodev,			/* read */
182	nodev,			/* write */
183	nodev,			/* ioctl */
184	nodev,			/* devmap */
185	nodev,			/* mmap */
186	nodev,			/* segmap */
187	nochpoll,		/* poll */
188	ddi_prop_op,		/* cb_prop_op */
189	&mouse8042_strinfo,	/* streamtab  */
190	D_MP | D_NEW
191};
192
193
194static struct dev_ops	mouse8042_ops = {
195	DEVO_REV,		/* devo_rev, */
196	0,			/* refcnt  */
197	mouse8042_getinfo,	/* getinfo */
198	nulldev,		/* identify */
199	nulldev,		/* probe */
200	mouse8042_attach,	/* attach */
201	mouse8042_detach,	/* detach */
202	nodev,			/* reset */
203	&mouse8042_cb_ops,	/* driver operations */
204	(struct bus_ops *)0,	/* bus operations */
205	NULL,			/* power */
206	ddi_quiesce_not_needed,		/* quiesce */
207};
208
209/*
210 * This is the loadable module wrapper.
211 */
212#include <sys/modctl.h>
213
214extern struct mod_ops mod_driverops;
215
216/*
217 * Module linkage information for the kernel.
218 */
219
220static struct modldrv modldrv = {
221	&mod_driverops, /* Type of module.  This one is a driver */
222	"PS/2 Mouse",
223	&mouse8042_ops,	/* driver ops */
224};
225
226static struct modlinkage modlinkage = {
227	MODREV_1,
228	(void *)&modldrv,
229	NULL
230};
231
232/*
233 * This is the driver initialization routine.
234 */
235int
236_init()
237{
238	int	rv;
239
240	rv = mod_install(&modlinkage);
241	return (rv);
242}
243
244
245int
246_fini(void)
247{
248	return (mod_remove(&modlinkage));
249}
250
251
252int
253_info(struct modinfo *modinfop)
254{
255	return (mod_info(&modlinkage, modinfop));
256}
257
258static int
259mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
260{
261	struct mouse_state *state;
262	mblk_t *mp;
263	int instance = ddi_get_instance(dip);
264	static ddi_device_acc_attr_t attr = {
265		DDI_DEVICE_ATTR_V0,
266		DDI_NEVERSWAP_ACC,
267		DDI_STRICTORDER_ACC,
268	};
269	int rc;
270
271
272	if (cmd == DDI_RESUME) {
273		state = (struct mouse_state *)ddi_get_driver_private(dip);
274
275		/* Ready to handle inbound data from mouse8042_intr */
276		state->ready = 1;
277
278		/*
279		 * Send a 0xaa 0x00 upstream.
280		 * This causes the vuid module to reset the mouse.
281		 */
282		if (state->ms_rqp != NULL) {
283			if (mp = allocb(1, BPRI_MED)) {
284				*mp->b_wptr++ = 0xaa;
285				putnext(state->ms_rqp, mp);
286			}
287			if (mp = allocb(1, BPRI_MED)) {
288				*mp->b_wptr++ = 0x0;
289				putnext(state->ms_rqp, mp);
290			}
291		}
292		return (DDI_SUCCESS);
293	}
294
295	if (cmd != DDI_ATTACH)
296		return (DDI_FAILURE);
297
298	if (mouse8042_dip != NULL)
299		return (DDI_FAILURE);
300
301	/* allocate and initialize state structure */
302	state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP);
303	state->ms_opened = B_FALSE;
304	state->reset_state = MSE_RESET_IDLE;
305	state->reset_tid = 0;
306	state->bc_id = 0;
307	ddi_set_driver_private(dip, state);
308
309	/*
310	 * In order to support virtual keyboard/mouse, we should distinguish
311	 * between internal virtual open and external physical open.
312	 *
313	 * When the physical devices are opened by application, they will
314	 * be unlinked from the virtual device and their data stream will
315	 * not be sent to the virtual device. When the opened physical
316	 * devices are closed, they will be relinked to the virtual devices.
317	 *
318	 * All these automatic switch between virtual and physical are
319	 * transparent.
320	 *
321	 * So we change minor node numbering scheme to be:
322	 * 	external node minor num == instance * 2
323	 *	internal node minor num == instance * 2 + 1
324	 */
325	rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2,
326	    DDI_NT_MOUSE, NULL);
327	if (rc != DDI_SUCCESS) {
328		goto fail_1;
329	}
330
331	if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
332	    instance * 2 + 1) != DDI_SUCCESS) {
333		goto fail_2;
334	}
335
336	rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr,
337	    (offset_t)0, (offset_t)0, &attr, &state->ms_handle);
338	if (rc != DDI_SUCCESS) {
339		goto fail_2;
340	}
341
342	rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie);
343	if (rc != DDI_SUCCESS) {
344		goto fail_3;
345	}
346
347	mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER,
348	    state->ms_iblock_cookie);
349	mutex_init(&state->reset_mutex, NULL, MUTEX_DRIVER,
350	    state->ms_iblock_cookie);
351	cv_init(&state->reset_cv, NULL, CV_DRIVER, NULL);
352
353	rc = ddi_add_intr(dip, 0,
354	    (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL,
355	    mouse8042_intr, (caddr_t)state);
356	if (rc != DDI_SUCCESS) {
357		goto fail_3;
358	}
359
360	mouse8042_dip = dip;
361
362	/* Ready to handle inbound data from mouse8042_intr */
363	state->ready = 1;
364
365	/* Now that we're attached, announce our presence to the world. */
366	ddi_report_dev(dip);
367	return (DDI_SUCCESS);
368
369fail_3:
370	ddi_regs_map_free(&state->ms_handle);
371
372fail_2:
373	ddi_remove_minor_node(dip, NULL);
374
375fail_1:
376	kmem_free(state, sizeof (struct mouse_state));
377	return (rc);
378}
379
380/*ARGSUSED*/
381static int
382mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
383{
384	struct mouse_state *state;
385
386	state = ddi_get_driver_private(dip);
387
388	switch (cmd) {
389	case DDI_SUSPEND:
390		/* Ignore all data from mouse8042_intr until we fully resume */
391		state->ready = 0;
392		return (DDI_SUCCESS);
393
394	case DDI_DETACH:
395		ddi_remove_intr(dip, 0, state->ms_iblock_cookie);
396		mouse8042_dip = NULL;
397		cv_destroy(&state->reset_cv);
398		mutex_destroy(&state->reset_mutex);
399		mutex_destroy(&state->ms_mutex);
400		ddi_prop_remove_all(dip);
401		ddi_regs_map_free(&state->ms_handle);
402		ddi_remove_minor_node(dip, NULL);
403		kmem_free(state, sizeof (struct mouse_state));
404		return (DDI_SUCCESS);
405
406	default:
407		return (DDI_FAILURE);
408	}
409}
410
411
412/* ARGSUSED */
413static int
414mouse8042_getinfo(
415    dev_info_t *dip,
416    ddi_info_cmd_t infocmd,
417    void *arg,
418    void **result)
419{
420	dev_t dev = (dev_t)arg;
421	minor_t	minor = getminor(dev);
422	int	instance = MOUSE8042_MINOR_TO_INSTANCE(minor);
423
424	switch (infocmd) {
425	case DDI_INFO_DEVT2DEVINFO:
426		if (mouse8042_dip == NULL)
427			return (DDI_FAILURE);
428
429		*result = (void *)mouse8042_dip;
430		break;
431	case DDI_INFO_DEVT2INSTANCE:
432		*result = (void *)(uintptr_t)instance;
433		break;
434	default:
435		return (DDI_FAILURE);
436	}
437	return (DDI_SUCCESS);
438}
439
440/*ARGSUSED*/
441static int
442mouse8042_open(
443	queue_t	*q,
444	dev_t	*devp,
445	int	flag,
446	int	sflag,
447	cred_t	*cred_p)
448{
449	struct mouse_state *state;
450	minor_t	minor = getminor(*devp);
451	int rval;
452
453	if (mouse8042_dip == NULL)
454		return (ENXIO);
455
456	state = ddi_get_driver_private(mouse8042_dip);
457
458	mutex_enter(&state->ms_mutex);
459
460	if (state->ms_opened) {
461		/*
462		 * Exit if the same minor node is already open
463		 */
464		if (state->ms_minor == minor) {
465			mutex_exit(&state->ms_mutex);
466			return (0);
467		}
468
469		/*
470		 * Check whether it is switch between physical and virtual
471		 *
472		 * Opening from virtual while the device is being physically
473		 * opened by an application should not happen. So we ASSERT
474		 * this in DEBUG version, and return error in the non-DEBUG
475		 * case.
476		 */
477		ASSERT(!MOUSE8042_INTERNAL_OPEN(minor));
478
479		if (MOUSE8042_INTERNAL_OPEN(minor)) {
480			mutex_exit(&state->ms_mutex);
481			return (EINVAL);
482		}
483
484		/*
485		 * Opening the physical one while it is being underneath
486		 * the virtual one.
487		 *
488		 * consconfig_unlink is called to unlink this device from
489		 * the virtual one, thus the old stream serving for this
490		 * device under the virtual one is closed, and then the
491		 * lower driver's close routine (here is mouse8042_close)
492		 * is also called to accomplish the whole stream close.
493		 * Here we have to drop the lock because mouse8042_close
494		 * also needs the lock.
495		 *
496		 * For mouse, the old stream is:
497		 *	consms->["pushmod"->]"mouse_vp driver"
498		 *
499		 * After the consconfig_unlink returns, the old stream is closed
500		 * and we grab the lock again to reopen this device as normal.
501		 */
502		mutex_exit(&state->ms_mutex);
503
504		/*
505		 * If unlink fails, fail the physical open.
506		 */
507		if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip),
508		    MOUSE8042_INTERNAL_MINOR(minor))) != 0) {
509			return (rval);
510		}
511
512		mutex_enter(&state->ms_mutex);
513	}
514
515
516	q->q_ptr = (caddr_t)state;
517	WR(q)->q_ptr = (caddr_t)state;
518	state->ms_rqp = q;
519	state->ms_wqp = WR(q);
520
521	qprocson(q);
522
523	state->ms_minor = minor;
524	state->ms_opened = B_TRUE;
525
526	mutex_exit(&state->ms_mutex);
527
528	return (0);
529}
530
531
532/*ARGSUSED*/
533static int
534mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
535{
536	struct mouse_state *state;
537	minor_t	minor;
538
539	state = (struct mouse_state *)q->q_ptr;
540
541	/*
542	 * Disable queue processing now, so that another reset cannot get in
543	 * after we wait for the current reset (if any) to complete.
544	 */
545	qprocsoff(q);
546
547	mutex_enter(&state->reset_mutex);
548	while (state->reset_state != MSE_RESET_IDLE) {
549		/*
550		 * Waiting for the previous reset to finish is
551		 * non-interruptible.  Some upper-level clients
552		 * cannot deal with EINTR and will not close the
553		 * STREAM properly, resulting in failure to reopen it
554		 * within the same process.
555		 */
556		cv_wait(&state->reset_cv, &state->reset_mutex);
557	}
558
559	if (state->reset_tid != 0) {
560		(void) quntimeout(q, state->reset_tid);
561		state->reset_tid = 0;
562	}
563
564	if (state->reply_mp != NULL) {
565		freemsg(state->reply_mp);
566		state->reply_mp = NULL;
567	}
568
569	if (state->reset_ack_mp != NULL) {
570		freemsg(state->reset_ack_mp);
571		state->reset_ack_mp = NULL;
572	}
573
574	mutex_exit(&state->reset_mutex);
575
576	mutex_enter(&state->ms_mutex);
577
578	if (state->bc_id != 0) {
579		(void) qunbufcall(q, state->bc_id);
580		state->bc_id = 0;
581	}
582
583	q->q_ptr = NULL;
584	WR(q)->q_ptr = NULL;
585	state->ms_rqp = NULL;
586	state->ms_wqp = NULL;
587
588	state->ms_opened = B_FALSE;
589
590	minor = state->ms_minor;
591
592	mutex_exit(&state->ms_mutex);
593
594	if (!MOUSE8042_INTERNAL_OPEN(minor)) {
595		/*
596		 * Closing physical PS/2 mouse
597		 *
598		 * Link it back to virtual mouse, and
599		 * mouse8042_open will be called as a result
600		 * of the consconfig_link call.  Do NOT try
601		 * this if the mouse is about to be detached!
602		 *
603		 * If linking back fails, this specific mouse
604		 * will not be available underneath the virtual
605		 * mouse, and can only be accessed via physical
606		 * open.
607		 */
608		consconfig_link(ddi_driver_major(mouse8042_dip),
609		    MOUSE8042_INTERNAL_MINOR(minor));
610	}
611
612	return (0);
613}
614
615static void
616mouse8042_iocnack(
617    queue_t *qp,
618    mblk_t *mp,
619    struct iocblk *iocp,
620    int error,
621    int rval)
622{
623	mp->b_datap->db_type = M_IOCNAK;
624	iocp->ioc_rval = rval;
625	iocp->ioc_error = error;
626	qreply(qp, mp);
627}
628
629static void
630mouse8042_reset_timeout(void *argp)
631{
632	struct mouse_state *state = (struct mouse_state *)argp;
633	mblk_t *mp;
634
635	mutex_enter(&state->reset_mutex);
636
637	/*
638	 * If the interrupt handler hasn't completed the reset handling
639	 * (reset_state would be IDLE or FAILED in that case), then
640	 * drop the 8042 lock, and send a faked retry reply upstream,
641	 * then enable the queue for further message processing.
642	 */
643	if (state->reset_state != MSE_RESET_IDLE &&
644	    state->reset_state != MSE_RESET_FAILED) {
645
646		state->reset_tid = 0;
647		state->reset_state = MSE_RESET_IDLE;
648		cv_signal(&state->reset_cv);
649
650		(void) ddi_get8(state->ms_handle, state->ms_addr +
651		    I8042_UNLOCK);
652
653		mp = state->reply_mp;
654		*mp->b_wptr++ = MSERESEND;
655		state->reply_mp = NULL;
656
657		if (state->ms_rqp != NULL)
658			putnext(state->ms_rqp, mp);
659		else
660			freemsg(mp);
661
662		ASSERT(state->ms_wqp != NULL);
663
664		enableok(state->ms_wqp);
665		qenable(state->ms_wqp);
666	}
667
668	mutex_exit(&state->reset_mutex);
669}
670
671/*
672 * Returns 1 if the caller should put the message (bp) back on the queue
673 */
674static int
675mouse8042_initiate_reset(queue_t *q, mblk_t *mp, struct mouse_state *state)
676{
677	mutex_enter(&state->reset_mutex);
678	/*
679	 * If we're in the middle of a reset, put the message back on the queue
680	 * for processing later.
681	 */
682	if (state->reset_state != MSE_RESET_IDLE) {
683		/*
684		 * We noenable the queue again here in case it was backenabled
685		 * by an upper-level module.
686		 */
687		noenable(q);
688
689		mutex_exit(&state->reset_mutex);
690		return (1);
691	}
692
693	/*
694	 * Drop the reset state lock before allocating the response message and
695	 * grabbing the 8042 exclusive-access lock (since those operations
696	 * may take an extended period of time to complete).
697	 */
698	mutex_exit(&state->reset_mutex);
699
700	if (state->reply_mp == NULL)
701		state->reply_mp = allocb(2, BPRI_MED);
702	if (state->reset_ack_mp == NULL)
703		state->reset_ack_mp = allocb(1, BPRI_MED);
704
705	if (state->reply_mp == NULL || state->reset_ack_mp == NULL) {
706		/*
707		 * Allocation failed -- set up a bufcall to enable the queue
708		 * whenever there is enough memory to allocate the response
709		 * message.
710		 */
711		state->bc_id = qbufcall(q, (state->reply_mp == NULL) ? 2 : 1,
712		    BPRI_MED, (void (*)(void *))qenable, q);
713
714		if (state->bc_id == 0) {
715			/*
716			 * If the qbufcall failed, we cannot proceed, so use the
717			 * message we were sent to respond with an error.
718			 */
719			*mp->b_rptr = MSEERROR;
720			mp->b_wptr = mp->b_rptr + 1;
721			qreply(q, mp);
722			return (0);
723		}
724
725		return (1);
726	} else {
727		/* Bufcall completed successfully (or wasn't needed) */
728		state->bc_id = 0;
729	}
730
731	/*
732	 * Gain exclusive access to the 8042 for the duration of the reset.
733	 * The unlock will occur when the reset has either completed or timed
734	 * out.
735	 */
736	(void) ddi_get8(state->ms_handle,
737	    state->ms_addr + I8042_LOCK);
738
739	mutex_enter(&state->reset_mutex);
740
741	state->reset_state = MSE_RESET_PRE;
742	noenable(q);
743
744	state->reset_tid = qtimeout(q,
745	    mouse8042_reset_timeout,
746	    state,
747	    drv_usectohz(
748	    MOUSE8042_RESET_TIMEOUT_USECS));
749
750	ddi_put8(state->ms_handle,
751	    state->ms_addr +
752	    I8042_INT_OUTPUT_DATA, MSERESET);
753
754	mp->b_rptr++;
755
756	mutex_exit(&state->reset_mutex);
757	return (1);
758}
759
760/*
761 * Returns 1 if the caller should stop processing messages
762 */
763static int
764mouse8042_process_data_msg(queue_t *q, mblk_t *mp, struct mouse_state *state)
765{
766	mblk_t *bp;
767	mblk_t *next;
768
769	bp = mp;
770	do {
771		while (bp->b_rptr < bp->b_wptr) {
772			/*
773			 * Detect an attempt to reset the mouse.  Lock out any
774			 * further mouse writes until the reset has completed.
775			 */
776			if (*bp->b_rptr == MSERESET) {
777
778				/*
779				 * If we couldn't allocate memory and we
780				 * we couldn't register a bufcall,
781				 * mouse8042_initiate_reset returns 0 and
782				 * has already used the message to send an
783				 * error reply back upstream, so there is no
784				 * need to deallocate or put this message back
785				 * on the queue.
786				 */
787				if (mouse8042_initiate_reset(q, bp, state) == 0)
788					return (1);
789
790				/*
791				 * If there's no data remaining in this block,
792				 * free this block and put the following blocks
793				 * of this message back on the queue. If putting
794				 * the rest of the message back on the queue
795				 * fails, free the the message.
796				 */
797				if (MBLKL(bp) == 0) {
798					next = bp->b_cont;
799					freeb(bp);
800					bp = next;
801				}
802				if (bp != NULL) {
803					if (!putbq(q, bp))
804						freemsg(bp);
805				}
806
807				return (1);
808
809			}
810			ddi_put8(state->ms_handle,
811			    state->ms_addr + I8042_INT_OUTPUT_DATA,
812			    *bp->b_rptr++);
813		}
814		next = bp->b_cont;
815		freeb(bp);
816	} while ((bp = next) != NULL);
817
818	return (0);
819}
820
821static int
822mouse8042_process_msg(queue_t *q, mblk_t *mp, struct mouse_state *state)
823{
824	struct iocblk *iocbp;
825	int rv = 0;
826
827	iocbp = (struct iocblk *)mp->b_rptr;
828
829	switch (mp->b_datap->db_type) {
830	case M_FLUSH:
831		if (*mp->b_rptr & FLUSHW) {
832			flushq(q, FLUSHDATA);
833			*mp->b_rptr &= ~FLUSHW;
834		}
835		if (*mp->b_rptr & FLUSHR) {
836			qreply(q, mp);
837		} else
838			freemsg(mp);
839		break;
840	case M_IOCTL:
841		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
842		break;
843	case M_IOCDATA:
844		mouse8042_iocnack(q, mp, iocbp, EINVAL, 0);
845		break;
846	case M_DATA:
847		rv = mouse8042_process_data_msg(q, mp, state);
848		break;
849	default:
850		freemsg(mp);
851		break;
852	}
853
854	return (rv);
855}
856
857/*
858 * This is the main mouse input routine.  Commands and parameters
859 * from upstream are sent to the mouse device immediately, unless
860 * the mouse is in the process of being reset, in which case
861 * commands are queued and executed later in the service procedure.
862 */
863static int
864mouse8042_wput(queue_t *q, mblk_t *mp)
865{
866	struct mouse_state *state;
867	state = (struct mouse_state *)q->q_ptr;
868
869	/*
870	 * Process all messages immediately, unless a reset is in
871	 * progress.  If a reset is in progress, deflect processing to
872	 * the service procedure.
873	 */
874	if (state->reset_state != MSE_RESET_IDLE)
875		return (putq(q, mp));
876
877	/*
878	 * If there are still messages outstanding in the queue that
879	 * the service procedure hasn't processed yet, put this
880	 * message in the queue also, to ensure proper message
881	 * ordering.
882	 */
883	if (q->q_first)
884		return (putq(q, mp));
885
886	(void) mouse8042_process_msg(q, mp, state);
887
888	return (0);
889}
890
891static int
892mouse8042_wsrv(queue_t *qp)
893{
894	mblk_t *mp;
895	struct mouse_state *state;
896	state = (struct mouse_state *)qp->q_ptr;
897
898	while ((mp = getq(qp)) != NULL) {
899		if (mouse8042_process_msg(qp, mp, state) != 0)
900			break;
901	}
902
903	return (0);
904}
905
906/*
907 * Returns the next reset state, given the current state and the byte
908 * received from the mouse.  Error and Resend codes are handled by the
909 * caller.
910 */
911static mouse8042_reset_state_e
912mouse8042_reset_fsm(mouse8042_reset_state_e reset_state, uint8_t mdata)
913{
914	switch (reset_state) {
915	case MSE_RESET_PRE:	/* RESET sent, now we expect an ACK */
916		if (mdata == MSE_ACK)	/* Got the ACK */
917			return (MSE_RESET_ACK);
918		break;
919
920	case MSE_RESET_ACK:	/* ACK received; now we expect 0xAA */
921		if (mdata == MSE_AA)	/* Got the 0xAA */
922			return (MSE_RESET_AA);
923		break;
924
925	case MSE_RESET_AA: 	/* 0xAA received; now we expect 0x00 */
926		if (mdata == MSE_00)
927			return (MSE_RESET_IDLE);
928		break;
929	}
930
931	return (reset_state);
932}
933
934static uint_t
935mouse8042_intr(caddr_t arg)
936{
937	unsigned char    mdata;
938	mblk_t *mp;
939	struct mouse_state *state = (struct mouse_state *)arg;
940	int rc;
941
942	mutex_enter(&state->ms_mutex);
943
944	rc = DDI_INTR_UNCLAIMED;
945
946	for (;;) {
947
948		if (ddi_get8(state->ms_handle,
949		    state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) {
950			break;
951		}
952
953		mdata = ddi_get8(state->ms_handle,
954		    state->ms_addr + I8042_INT_INPUT_DATA);
955
956		rc = DDI_INTR_CLAIMED;
957
958		/*
959		 * If we're not ready for this data, discard it.
960		 */
961		if (!state->ready)
962			continue;
963
964		mutex_enter(&state->reset_mutex);
965		if (state->reset_state != MSE_RESET_IDLE) {
966
967			if (mdata == MSEERROR || mdata == MSERESET) {
968				state->reset_state = MSE_RESET_FAILED;
969			} else {
970				state->reset_state =
971				    mouse8042_reset_fsm(state->reset_state,
972				    mdata);
973			}
974
975			if (state->reset_state == MSE_RESET_ACK) {
976
977			/*
978			 * We received an ACK from the mouse, so
979			 * send it upstream immediately so that
980			 * consumers depending on the immediate
981			 * ACK don't time out.
982			 */
983				if (state->reset_ack_mp != NULL) {
984
985					mp = state->reset_ack_mp;
986
987					state->reset_ack_mp = NULL;
988
989					if (state->ms_rqp != NULL) {
990						*mp->b_wptr++ = MSE_ACK;
991						putnext(state->ms_rqp, mp);
992					} else
993						freemsg(mp);
994				}
995
996				if (state->ms_wqp != NULL) {
997					enableok(state->ms_wqp);
998					qenable(state->ms_wqp);
999				}
1000
1001			} else if (state->reset_state == MSE_RESET_IDLE ||
1002			    state->reset_state == MSE_RESET_FAILED) {
1003
1004			/*
1005			 * If we transitioned back to the idle reset state (or
1006			 * the reset failed), disable the timeout, release the
1007			 * 8042 exclusive-access lock, then send the response
1008			 * the the upper-level modules. Finally, enable the
1009			 * queue and schedule queue service procedures so that
1010			 * upper-level modules can process the response.
1011			 * Otherwise, if we're still in the middle of the
1012			 * reset sequence, do not send the data up (since the
1013			 * response is sent at the end of the sequence, or
1014			 * on timeout/error).
1015			 */
1016
1017				mutex_exit(&state->reset_mutex);
1018				(void) quntimeout(state->ms_wqp,
1019				    state->reset_tid);
1020				mutex_enter(&state->reset_mutex);
1021
1022				(void) ddi_get8(state->ms_handle,
1023				    state->ms_addr + I8042_UNLOCK);
1024
1025				state->reset_tid = 0;
1026				if (state->reply_mp != NULL) {
1027					mp = state->reply_mp;
1028					if (state->reset_state ==
1029					    MSE_RESET_FAILED) {
1030						*mp->b_wptr++ = mdata;
1031					} else {
1032						*mp->b_wptr++ = MSE_AA;
1033						*mp->b_wptr++ = MSE_00;
1034					}
1035					state->reply_mp = NULL;
1036				} else {
1037					mp = NULL;
1038				}
1039
1040				state->reset_state = MSE_RESET_IDLE;
1041				cv_signal(&state->reset_cv);
1042
1043				if (mp != NULL) {
1044					if (state->ms_rqp != NULL)
1045						putnext(state->ms_rqp, mp);
1046					else
1047						freemsg(mp);
1048				}
1049
1050				if (state->ms_wqp != NULL) {
1051					enableok(state->ms_wqp);
1052					qenable(state->ms_wqp);
1053				}
1054			}
1055
1056			mutex_exit(&state->reset_mutex);
1057			mutex_exit(&state->ms_mutex);
1058			return (rc);
1059		}
1060		mutex_exit(&state->reset_mutex);
1061
1062		if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) {
1063			*mp->b_wptr++ = mdata;
1064			putnext(state->ms_rqp, mp);
1065		}
1066	}
1067	mutex_exit(&state->ms_mutex);
1068
1069	return (rc);
1070}
1071