xref: /titanic_52/usr/src/uts/common/io/vuidmice/vuidps2.c (revision 5b81b7ca9b4fd49f704a5f492832ec658207bb98)
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
522eb7cb5Sgd78059  * Common Development and Distribution License (the "License").
622eb7cb5Sgd78059  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2257f4a14aSGarrett D'Amore  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * 			2/3/5 Button PS/2 Mouse Protocol
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * This module dynamically determines the number of buttons on the mouse.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/stream.h>
347c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
3557f4a14aSGarrett D'Amore #include "vuidmice.h"
367c478bd9Sstevel@tonic-gate #include <sys/vuid_wheel.h>
377c478bd9Sstevel@tonic-gate #include <sys/mouse.h>
3822eb7cb5Sgd78059 #include <sys/strsun.h>
397c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
407c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * BUT(1)		LEFT   BUTTON
447c478bd9Sstevel@tonic-gate  * BUT(2)		MIDDLE BUTTON (if present)
457c478bd9Sstevel@tonic-gate  * BUT(3)		RIGHT  BUTTON
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	PS2_BUTTONMASK		7		/* mask byte zero with this */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	PS2_BUTTON_L		(uchar_t)0x01	/* Left button pressed */
517c478bd9Sstevel@tonic-gate #define	PS2_BUTTON_R		(uchar_t)0x02	/* Right button pressed */
527c478bd9Sstevel@tonic-gate #define	PS2_BUTTON_M		(uchar_t)0x04	/* Middle button pressed */
537c478bd9Sstevel@tonic-gate #define	PS2_DATA_XSIGN		(uchar_t)0x10	/* X data sign bit */
547c478bd9Sstevel@tonic-gate #define	PS2_DATA_YSIGN		(uchar_t)0x20	/* Y data sign bit */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	PS2_START			0	/* Beginning of packet	*/
577c478bd9Sstevel@tonic-gate #define	PS2_BUTTON			1	/* Got button status	*/
587c478bd9Sstevel@tonic-gate #define	PS2_MAYBE_REATTACH		2	/* Got button status	*/
597c478bd9Sstevel@tonic-gate #define	PS2_DELTA_Y			3	/* Got delta X		*/
607c478bd9Sstevel@tonic-gate #define	PS2_WHEEL_DELTA_Z		4
617c478bd9Sstevel@tonic-gate #define	PS2_WHEEL5_DELTA_Z		5
6215bfc6b7SSeth Goldberg #define	PS2_WAIT_RESET_COMPLETE		6
6315bfc6b7SSeth Goldberg #define	PS2_WAIT_FOR_AA			7
6415bfc6b7SSeth Goldberg #define	PS2_WAIT_FOR_00			8
657c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SETRES0_ACK1		9
667c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SETRES0_ACK2		10	/* -+ must be consecutive */
677c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SCALE1_1_ACK		11	/*  | */
687c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SCALE1_2_ACK		12	/*  | */
697c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SCALE1_3_ACK		13	/* -+ */
7015bfc6b7SSeth Goldberg #define	PS2_WAIT_STATREQ_ACK		14	/* -+ */
7115bfc6b7SSeth Goldberg #define	PS2_WAIT_STATUS_1		15	/*  | */
7215bfc6b7SSeth Goldberg #define	PS2_WAIT_STATUS_BUTTONS		16	/*  | must stay in this order */
7315bfc6b7SSeth Goldberg #define	PS2_WAIT_STATUS_REV		17	/* -+ */
747c478bd9Sstevel@tonic-gate #define	PS2_WAIT_STATUS_3		18
757c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL1_CMD_ACK	19	/* Set the sample rate to 200 */
767c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL1_RATE_ACK	20
777c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL2_CMD_ACK	21	/* Set the sample rate to 200 */
787c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL2_RATE_ACK	22
797c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL3_CMD_ACK	23	/* Set the sample rate to 80 */
807c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_SMPL3_RATE_ACK	24
817c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_DEV_CMD		25
827c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL_DEV_ACK		26	/* Detected wheel mouse */
837c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL1_CMD_ACK	27	/* Set the sample rate to 200 */
847c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL1_RATE_ACK	28
857c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL2_CMD_ACK	29	/* Set the sample rate to 200 */
867c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL2_RATE_ACK	30
877c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL3_CMD_ACK	31	/* Set the sample rate to 100 */
887c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_SMPL3_RATE_ACK	32
897c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_DEV_CMD		33
907c478bd9Sstevel@tonic-gate #define	PS2_WAIT_WHEEL5_DEV_ACK		34	/* Detected 5 button mouse */
917c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SETRES3_CMD		35
927c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SETRES3_ACK1		36
937c478bd9Sstevel@tonic-gate #define	PS2_WAIT_SETRES3_ACK2		37
947c478bd9Sstevel@tonic-gate #define	PS2_WAIT_STREAM_ACK		38
957c478bd9Sstevel@tonic-gate #define	PS2_WAIT_ON_ACK			39
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #define	MOUSE_MODE_PLAIN	0	/* Normal PS/2 mouse - 3 byte msgs */
987c478bd9Sstevel@tonic-gate #define	MOUSE_MODE_WHEEL	1	/* Wheel mouse - 4 byte msgs */
997c478bd9Sstevel@tonic-gate #define	MOUSE_MODE_WHEEL5	2	/* Wheel + 5 btn mouse - 4 byte msgs */
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	PS2_FLAG_NO_EXTN	0x08	/* Mouse doesn't obey extended cmds */
1027c478bd9Sstevel@tonic-gate #define	PS2_FLAG_INIT_DONE	0x01	/* Mouse has been inited successfully */
1037c478bd9Sstevel@tonic-gate #define	PS2_FLAG_INIT_TIMEOUT	0x02	/* Mouse init timeout */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * The RESET command takes more time
1077c478bd9Sstevel@tonic-gate  * before the PS/2 mouse is ready
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate #define	PS2_INIT_TMOUT_RESET	500000	/* 500ms for RESET command */
1107c478bd9Sstevel@tonic-gate #define	PS2_INIT_TMOUT_PER_CMD	200000	/* 200ms for each command-response */
11152aa746fSlq150181 #define	PS2_INIT_TMOUT_PER_GROUP	500000 /* 500ms for group commands */
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define	PS2_MAX_INIT_COUNT	5
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static void vuidmice_send_wheel_event(queue_t *const, uchar_t,
1167c478bd9Sstevel@tonic-gate 		uchar_t, uchar_t, int);
1177c478bd9Sstevel@tonic-gate extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int);
1187c478bd9Sstevel@tonic-gate extern void uniqtime32(struct timeval32 *);
1197c478bd9Sstevel@tonic-gate static void VUID_INIT_TIMEOUT(void *q);
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate  * We apply timeout to nearly each command-response
1237c478bd9Sstevel@tonic-gate  * during initialization:
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  * Set timeout for SET RESOLUTION
1267c478bd9Sstevel@tonic-gate  * Set timeout for SET SCALE
1277c478bd9Sstevel@tonic-gate  * Set timeout for SET SAMPLE RATE
1287c478bd9Sstevel@tonic-gate  * Set timeout for STATUS REQUEST
1297c478bd9Sstevel@tonic-gate  * Set timeout for GET DEV
1307c478bd9Sstevel@tonic-gate  * Set timeout for SET STREAM MODE and ENABLE.
1317c478bd9Sstevel@tonic-gate  *
1327c478bd9Sstevel@tonic-gate  * But for simplicity, sometimes we just apply the timeout
13352aa746fSlq150181  * to a function with group commands (e.g. wheel-mouse detection).
1347c478bd9Sstevel@tonic-gate  *
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate static void
1377c478bd9Sstevel@tonic-gate vuid_set_timeout(queue_t *const qp, clock_t time)
1387c478bd9Sstevel@tonic-gate {
13915bfc6b7SSeth Goldberg 	if (STATEP->init_tid != 0)
14015bfc6b7SSeth Goldberg 		(void) quntimeout(qp, STATEP->init_tid);
1417c478bd9Sstevel@tonic-gate 	STATEP->init_tid = qtimeout(qp, VUID_INIT_TIMEOUT,
1427c478bd9Sstevel@tonic-gate 	    qp, drv_usectohz(time));
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate static void
1467c478bd9Sstevel@tonic-gate vuid_cancel_timeout(queue_t *const qp)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	(void) quntimeout(qp, STATEP->init_tid);
1497c478bd9Sstevel@tonic-gate 	STATEP->init_tid = 0;
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate  * vuidmice_send_wheel_event
1547c478bd9Sstevel@tonic-gate  *	Convert wheel data to firm_events
1557c478bd9Sstevel@tonic-gate  */
1567c478bd9Sstevel@tonic-gate static void
1577c478bd9Sstevel@tonic-gate vuidmice_send_wheel_event(queue_t *const qp, uchar_t event_id,
1587c478bd9Sstevel@tonic-gate     uchar_t event_pair_type, uchar_t event_pair, int event_value)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	mblk_t		*bp;
1617c478bd9Sstevel@tonic-gate 	Firm_event	*fep;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	if ((bp = allocb((int)sizeof (Firm_event), BPRI_HI)) == NULL) {
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 		return;
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 
16822eb7cb5Sgd78059 	fep = (void *)bp->b_wptr;
1697c478bd9Sstevel@tonic-gate 	fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) |
1707c478bd9Sstevel@tonic-gate 	    vuid_id_offset(event_id);
1717c478bd9Sstevel@tonic-gate 	fep->pair_type = event_pair_type;
1727c478bd9Sstevel@tonic-gate 	fep->pair = event_pair;
1737c478bd9Sstevel@tonic-gate 	fep->value = event_value;
1747c478bd9Sstevel@tonic-gate 	uniqtime32(&fep->time);
1757c478bd9Sstevel@tonic-gate 	bp->b_wptr += sizeof (Firm_event);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	if (canput(qp->q_next)) {
1787c478bd9Sstevel@tonic-gate 		putnext(qp, bp);
1797c478bd9Sstevel@tonic-gate 	} else {
1807c478bd9Sstevel@tonic-gate 		(void) putbq(qp, bp); /* read side is blocked */
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate static void
1867c478bd9Sstevel@tonic-gate sendButtonEvent(queue_t *const qp)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	static int bmap[3] = {1, 3, 2};
1897c478bd9Sstevel@tonic-gate 	uint_t b;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* for each button, see if it has changed */
1927c478bd9Sstevel@tonic-gate 	for (b = 0; b < STATEP->nbuttons; b++) {
1937c478bd9Sstevel@tonic-gate 		uchar_t	mask = 0x1 << b;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 		if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask))
1967c478bd9Sstevel@tonic-gate 			VUID_PUTNEXT(qp, (uchar_t)BUT(bmap[b]), FE_PAIR_NONE, 0,
1977c478bd9Sstevel@tonic-gate 			    (STATEP->buttons & mask ? 1 : 0));
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate void
2027c478bd9Sstevel@tonic-gate put1(queue_t *const qp, int c)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	mblk_t *bp;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if (bp = allocb(1, BPRI_MED)) {
2077c478bd9Sstevel@tonic-gate 		*bp->b_wptr++ = (char)c;
2087c478bd9Sstevel@tonic-gate 		putnext(qp, bp);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
21215bfc6b7SSeth Goldberg static void
21315bfc6b7SSeth Goldberg vuidmice_start_wdc_or_setres(queue_t *qp)
21415bfc6b7SSeth Goldberg {
21515bfc6b7SSeth Goldberg 	/* Set timeout for set res or sample rate */
21615bfc6b7SSeth Goldberg 	vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP);
21715bfc6b7SSeth Goldberg 
21815bfc6b7SSeth Goldberg 	/*
21915bfc6b7SSeth Goldberg 	 * Start the wheel-mouse detection code.  First, we look
22015bfc6b7SSeth Goldberg 	 * for standard wheel mice.  If we set the sample rate
22115bfc6b7SSeth Goldberg 	 * to 200, 100, and then 80 and finally request the
22215bfc6b7SSeth Goldberg 	 * device ID, a wheel mouse will return an ID of 0x03.
22315bfc6b7SSeth Goldberg 	 * After that, we'll try for the wheel+5 variety.  The
22415bfc6b7SSeth Goldberg 	 * incantation in this case is 200, 200, and 80.  We'll
22515bfc6b7SSeth Goldberg 	 * get 0x04 back in that case.
22615bfc6b7SSeth Goldberg 	 */
22715bfc6b7SSeth Goldberg 	if (STATEP->inited & PS2_FLAG_NO_EXTN) {
22815bfc6b7SSeth Goldberg 		STATEP->state = PS2_WAIT_SETRES3_ACK1;
22915bfc6b7SSeth Goldberg 		put1(WR(qp), MSESETRES);
23015bfc6b7SSeth Goldberg 	} else {
23115bfc6b7SSeth Goldberg 		STATEP->state = PS2_WAIT_WHEEL_SMPL1_CMD_ACK;
23215bfc6b7SSeth Goldberg 		put1(WR(qp), MSECHGMOD);
23315bfc6b7SSeth Goldberg 	}
23415bfc6b7SSeth Goldberg }
23515bfc6b7SSeth Goldberg 
2367c478bd9Sstevel@tonic-gate int
2377c478bd9Sstevel@tonic-gate VUID_OPEN(queue_t *const qp)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	STATEP->format = VUID_FIRM_EVENT;
2407c478bd9Sstevel@tonic-gate 	STATEP->vuid_mouse_mode = MOUSE_MODE_PLAIN;
2417c478bd9Sstevel@tonic-gate 	STATEP->inited = 0;
2427c478bd9Sstevel@tonic-gate 	STATEP->nbuttons = 3;
2437c478bd9Sstevel@tonic-gate 
24415bfc6b7SSeth Goldberg 	STATEP->state = PS2_WAIT_RESET_COMPLETE;
2457c478bd9Sstevel@tonic-gate 
24652aa746fSlq150181 	put1(WR(qp), MSERESET);
24752aa746fSlq150181 
2487c478bd9Sstevel@tonic-gate 	while ((STATEP->state != PS2_START) &&
2497c478bd9Sstevel@tonic-gate 	    !(STATEP->inited & PS2_FLAG_INIT_TIMEOUT)) {
2507c478bd9Sstevel@tonic-gate 		if (qwait_sig(qp) == 0)
2517c478bd9Sstevel@tonic-gate 			break;
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	/*
2557c478bd9Sstevel@tonic-gate 	 * Later the PS/2 mouse maybe re-attach, so here
2567c478bd9Sstevel@tonic-gate 	 * clear the init_count.
2577c478bd9Sstevel@tonic-gate 	 */
2587c478bd9Sstevel@tonic-gate 	STATEP->init_count = 0;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	return (0);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate void
2647c478bd9Sstevel@tonic-gate VUID_CLOSE(queue_t *const qp)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 	if (STATEP->init_tid != 0)
2677c478bd9Sstevel@tonic-gate 		vuid_cancel_timeout(qp);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static void
2717c478bd9Sstevel@tonic-gate VUID_INIT_TIMEOUT(void *q)
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate 	queue_t	*qp = q;
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	STATEP->init_tid = 0;
2767c478bd9Sstevel@tonic-gate 
277fd9cb95cSsethg 	/*
278fd9cb95cSsethg 	 * Some mice do not even send an error in response to
279fd9cb95cSsethg 	 * the wheel mouse sample commands, so if we're in any of
280fd9cb95cSsethg 	 * the PS2_WAIT_WHEEL_SMPL* states, and there has been
281fd9cb95cSsethg 	 * a timeout, assume the mouse cannot handle the extended
282fd9cb95cSsethg 	 * (wheel mouse) commands.
283fd9cb95cSsethg 	 */
284fd9cb95cSsethg 	if ((STATEP->state == PS2_WAIT_WHEEL_SMPL1_CMD_ACK) ||
285fd9cb95cSsethg 	    (STATEP->state == PS2_WAIT_WHEEL_SMPL1_RATE_ACK) ||
2867c478bd9Sstevel@tonic-gate 	    (STATEP->state == PS2_WAIT_WHEEL_SMPL2_RATE_ACK) ||
2877c478bd9Sstevel@tonic-gate 	    (STATEP->state == PS2_WAIT_WHEEL_SMPL3_RATE_ACK)) {
2887c478bd9Sstevel@tonic-gate 		/*
2897c478bd9Sstevel@tonic-gate 		 * We overload 'inited' to mark the PS/2 mouse
2907c478bd9Sstevel@tonic-gate 		 * as one which doesn't respond to extended commands.
2917c478bd9Sstevel@tonic-gate 		 */
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		STATEP->inited |= PS2_FLAG_NO_EXTN;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
29615bfc6b7SSeth Goldberg 
29715bfc6b7SSeth Goldberg 	/*
29815bfc6b7SSeth Goldberg 	 * If the Logitech button detection sequence timed out at some point
29915bfc6b7SSeth Goldberg 	 * in the sequence, ignore it and skip to the next step in
30015bfc6b7SSeth Goldberg 	 * initialization.  Do NOT count this as a timeout, so do NOT
30115bfc6b7SSeth Goldberg 	 * increment init_count.
30215bfc6b7SSeth Goldberg 	 */
30315bfc6b7SSeth Goldberg 	if (STATEP->state >= PS2_WAIT_STATREQ_ACK &&
30415bfc6b7SSeth Goldberg 	    STATEP->state <= PS2_WAIT_STATUS_REV) {
30515bfc6b7SSeth Goldberg 
30615bfc6b7SSeth Goldberg 		/* See the comment under the PS2_WAIT_STATUS_BUTTONS case */
30715bfc6b7SSeth Goldberg #if	defined(VUID3PS2)
30815bfc6b7SSeth Goldberg 		STATEP->nbuttons = 3;
30915bfc6b7SSeth Goldberg #else
31015bfc6b7SSeth Goldberg 		STATEP->nbuttons = 2;
31115bfc6b7SSeth Goldberg #endif
31215bfc6b7SSeth Goldberg 		vuidmice_start_wdc_or_setres(qp);
3137c478bd9Sstevel@tonic-gate 		return;
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 
31615bfc6b7SSeth Goldberg 	/*
31715bfc6b7SSeth Goldberg 	 * If the initialization process has timed out too many times, even if
31815bfc6b7SSeth Goldberg 	 * a subset of the process was successful, stop trying and put the
31915bfc6b7SSeth Goldberg 	 * mouse in the only state from which it can recover -- waiting for an
32015bfc6b7SSeth Goldberg 	 * 0xAA 0x00 response (i.e. like one we get on resume from mouse8042
32115bfc6b7SSeth Goldberg 	 * or from a replug).
32215bfc6b7SSeth Goldberg 	 */
32315bfc6b7SSeth Goldberg 	if (++STATEP->init_count >= PS2_MAX_INIT_COUNT) {
32415bfc6b7SSeth Goldberg 		STATEP->inited |= PS2_FLAG_INIT_TIMEOUT;
32515bfc6b7SSeth Goldberg 		STATEP->state = PS2_WAIT_FOR_AA;
32615bfc6b7SSeth Goldberg 	} else {
3277c478bd9Sstevel@tonic-gate 
32815bfc6b7SSeth Goldberg 		STATEP->state = PS2_WAIT_RESET_COMPLETE;
3297c478bd9Sstevel@tonic-gate 
33015bfc6b7SSeth Goldberg 		/* Try to reset the mouse again */
3317c478bd9Sstevel@tonic-gate 		put1(WR(qp), MSERESET);
3327c478bd9Sstevel@tonic-gate 	}
33315bfc6b7SSeth Goldberg }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate void
3367c478bd9Sstevel@tonic-gate VUID_QUEUE(queue_t *const qp, mblk_t *mp)
3377c478bd9Sstevel@tonic-gate {
33815bfc6b7SSeth Goldberg 	int code, length;
3397c478bd9Sstevel@tonic-gate 	clock_t now;
3407c478bd9Sstevel@tonic-gate 	clock_t elapsed;
3417c478bd9Sstevel@tonic-gate 	clock_t mouse_timeout;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	mouse_timeout = drv_usectohz(250000);
3447c478bd9Sstevel@tonic-gate 	now = ddi_get_lbolt();
3457c478bd9Sstevel@tonic-gate 	elapsed = now - STATEP->last_event_lbolt;
3467c478bd9Sstevel@tonic-gate 	STATEP->last_event_lbolt = now;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	while (mp->b_rptr < mp->b_wptr) {
34915bfc6b7SSeth Goldberg 		length = MBLKL(mp);
3507c478bd9Sstevel@tonic-gate 		code = *mp->b_rptr++;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		switch (STATEP->state) {
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		/*
3557c478bd9Sstevel@tonic-gate 		 * Start state. We stay here if the start code is not
3567c478bd9Sstevel@tonic-gate 		 * received thus forcing us back into sync. When we get a
3577c478bd9Sstevel@tonic-gate 		 * start code the button mask comes with it forcing us to
3587c478bd9Sstevel@tonic-gate 		 * to the next state.
3597c478bd9Sstevel@tonic-gate 		 */
3607c478bd9Sstevel@tonic-gate restart:
3617c478bd9Sstevel@tonic-gate 		case PS2_START:
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 			/*
3647c478bd9Sstevel@tonic-gate 			 * 3-byte packet format
3657c478bd9Sstevel@tonic-gate 			 *
3667c478bd9Sstevel@tonic-gate 			 * Bit   7   6    5	4	3   2	1	0
3677c478bd9Sstevel@tonic-gate 			 * Byte ---- ---- ----- ----- -- ------ ------ ------
3687c478bd9Sstevel@tonic-gate 			 * 1    Y_Ov X_Ov Y_Sgn X_Sgn  1 MdlBtn RgtBtn LftBtn
3697c478bd9Sstevel@tonic-gate 			 * 2    |<--------------X Movement----------------->|
3707c478bd9Sstevel@tonic-gate 			 * 3    |<--------------Y Movement----------------->|
3717c478bd9Sstevel@tonic-gate 			 *
3727c478bd9Sstevel@tonic-gate 			 * 4-byte wheel packet format
3737c478bd9Sstevel@tonic-gate 			 *
3747c478bd9Sstevel@tonic-gate 			 * Bit   7    6   5	4	3   2	1	0
3757c478bd9Sstevel@tonic-gate 			 * Byte ---- ---- ----- ----- -- ------ ------ ------
3767c478bd9Sstevel@tonic-gate 			 * 1    Y_Ov X_Ov Y_Sgn X_Sgn  1 MdlBtn RgtBtn LftBtn
3777c478bd9Sstevel@tonic-gate 			 * 2    |<--------------X Movement----------------->|
3787c478bd9Sstevel@tonic-gate 			 * 3    |<--------------Y Movement----------------->|
3797c478bd9Sstevel@tonic-gate 			 * 4    |<--------------Z Movement----------------->|
3807c478bd9Sstevel@tonic-gate 			 *
3817c478bd9Sstevel@tonic-gate 			 * 4-byte wheel+5 packet format
3827c478bd9Sstevel@tonic-gate 			 *
3837c478bd9Sstevel@tonic-gate 			 * Bit   7    6   5	4	3   2	1	0
3847c478bd9Sstevel@tonic-gate 			 * Byte ---- ---- ----- ----- -- ------ ------ ------
3857c478bd9Sstevel@tonic-gate 			 * 1    Y_Ov X_Ov Y_Sgn X_Sgn  1 MdlBtn RgtBtn LftBtn
3867c478bd9Sstevel@tonic-gate 			 * 2    |<--------------X Movement----------------->|
3877c478bd9Sstevel@tonic-gate 			 * 3    |<--------------Y Movement----------------->|
3887c478bd9Sstevel@tonic-gate 			 * 4	0    0   5_Btn 4_Btn Z3   Z2	Z1	Z0
3897c478bd9Sstevel@tonic-gate 			 */
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 			if (!(STATEP->inited & PS2_FLAG_INIT_DONE)) {
3927c478bd9Sstevel@tonic-gate 				STATEP->sync_byte = code & 0x8;
3937c478bd9Sstevel@tonic-gate 				STATEP->inited |= PS2_FLAG_INIT_DONE;
3947c478bd9Sstevel@tonic-gate 			}
3957c478bd9Sstevel@tonic-gate 		/*
3967c478bd9Sstevel@tonic-gate 		 * the PS/2 mouse data format doesn't have any sort of sync
3977c478bd9Sstevel@tonic-gate 		 * data to make sure we are in sync with the packet stream,
3987c478bd9Sstevel@tonic-gate 		 * but the Technical Reference manual states that bits 2 & 3
3997c478bd9Sstevel@tonic-gate 		 * of the first byte are reserved.  Logitech uses bit 2 for
4007c478bd9Sstevel@tonic-gate 		 * the middle button.  We HOPE that noone uses bit 3 though,
4017c478bd9Sstevel@tonic-gate 		 * and decide we're out of sync if bit 3 is not set here.
4027c478bd9Sstevel@tonic-gate 		 */
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 			if ((code ^ STATEP->sync_byte) & 0x08) {
4057c478bd9Sstevel@tonic-gate 				/* bit 3 not set */
4067c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_START;
4077c478bd9Sstevel@tonic-gate 				break;			/* toss the code */
4087c478bd9Sstevel@tonic-gate 			}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 			/* get the button values */
4117c478bd9Sstevel@tonic-gate 			STATEP->buttons = code & PS2_BUTTONMASK;
4127c478bd9Sstevel@tonic-gate 			if (STATEP->buttons != STATEP->oldbuttons) {
4137c478bd9Sstevel@tonic-gate 				sendButtonEvent(qp);
4147c478bd9Sstevel@tonic-gate 				STATEP->oldbuttons = STATEP->buttons;
4157c478bd9Sstevel@tonic-gate 			}
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 			/* bit 5 indicates Y value is negative (the sign bit) */
4187c478bd9Sstevel@tonic-gate 			if (code & PS2_DATA_YSIGN)
4197c478bd9Sstevel@tonic-gate 				STATEP->deltay = -1 & ~0xff;
4207c478bd9Sstevel@tonic-gate 			else
4217c478bd9Sstevel@tonic-gate 				STATEP->deltay = 0;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 			/* bit 4 is X sign bit */
4247c478bd9Sstevel@tonic-gate 			if (code & PS2_DATA_XSIGN)
4257c478bd9Sstevel@tonic-gate 				STATEP->deltax = -1 & ~0xff;
4267c478bd9Sstevel@tonic-gate 			else
4277c478bd9Sstevel@tonic-gate 				STATEP->deltax = 0;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 			if (code == MSE_AA)
4307c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_MAYBE_REATTACH;
4317c478bd9Sstevel@tonic-gate 			else
4327c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_BUTTON;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			break;
4357c478bd9Sstevel@tonic-gate 
43615bfc6b7SSeth Goldberg 		case PS2_WAIT_FOR_AA:
43715bfc6b7SSeth Goldberg 			/*
43815bfc6b7SSeth Goldberg 			 * On Dell latitude D800, the initial MSE_ACK is
43915bfc6b7SSeth Goldberg 			 * received after the initialization sequence
44015bfc6b7SSeth Goldberg 			 * times out, so restart it here.
44115bfc6b7SSeth Goldberg 			 */
44215bfc6b7SSeth Goldberg 			if (code == MSE_ACK) {
44315bfc6b7SSeth Goldberg 				STATEP->inited &= ~PS2_FLAG_INIT_TIMEOUT;
44415bfc6b7SSeth Goldberg 				STATEP->init_count = 0;
44515bfc6b7SSeth Goldberg 				STATEP->state = PS2_WAIT_RESET_COMPLETE;
44615bfc6b7SSeth Goldberg 				put1(WR(qp), MSERESET);
44715bfc6b7SSeth Goldberg 				break;
44815bfc6b7SSeth Goldberg 			}
44915bfc6b7SSeth Goldberg 
45015bfc6b7SSeth Goldberg 			if (code != MSE_AA)
45115bfc6b7SSeth Goldberg 				break;
45215bfc6b7SSeth Goldberg 
45315bfc6b7SSeth Goldberg 			STATEP->state = PS2_WAIT_FOR_00;
45415bfc6b7SSeth Goldberg 			break;
45515bfc6b7SSeth Goldberg 
45615bfc6b7SSeth Goldberg 		case PS2_WAIT_FOR_00:
45715bfc6b7SSeth Goldberg 			if (code != MSE_00)
45815bfc6b7SSeth Goldberg 				break;
45915bfc6b7SSeth Goldberg 
46015bfc6b7SSeth Goldberg 			STATEP->inited &= ~PS2_FLAG_INIT_TIMEOUT;
46115bfc6b7SSeth Goldberg 			STATEP->init_count = 0;
46215bfc6b7SSeth Goldberg 			STATEP->state = PS2_WAIT_RESET_COMPLETE;
46315bfc6b7SSeth Goldberg 			put1(WR(qp), MSERESET);
46415bfc6b7SSeth Goldberg 			break;
46515bfc6b7SSeth Goldberg 
4667c478bd9Sstevel@tonic-gate 		case PS2_MAYBE_REATTACH:
4677c478bd9Sstevel@tonic-gate 			if (code == MSE_00) {
46815bfc6b7SSeth Goldberg 				STATEP->state = PS2_WAIT_RESET_COMPLETE;
46952aa746fSlq150181 				put1(WR(qp), MSERESET);
4707c478bd9Sstevel@tonic-gate 				break;
4717c478bd9Sstevel@tonic-gate 			}
4727c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 		case PS2_BUTTON:
4757c478bd9Sstevel@tonic-gate 			/*
4767c478bd9Sstevel@tonic-gate 			 * Now for the 7 bits of delta x.  "Or" in
4777c478bd9Sstevel@tonic-gate 			 * the sign bit and continue.  This is ac-
4787c478bd9Sstevel@tonic-gate 			 * tually a signed 9 bit number, but I just
4797c478bd9Sstevel@tonic-gate 			 * truncate it to a signed char in order to
4807c478bd9Sstevel@tonic-gate 			 * avoid changing and retesting all of the
4817c478bd9Sstevel@tonic-gate 			 * mouse-related modules for this patch.
4827c478bd9Sstevel@tonic-gate 			 */
4837c478bd9Sstevel@tonic-gate 			if (elapsed > mouse_timeout)
4847c478bd9Sstevel@tonic-gate 				goto restart;
4857c478bd9Sstevel@tonic-gate 			STATEP->deltax |= code & 0xff;
4867c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_DELTA_Y;
4877c478bd9Sstevel@tonic-gate 			break;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 		case PS2_DELTA_Y:
4907c478bd9Sstevel@tonic-gate 			/*
4917c478bd9Sstevel@tonic-gate 			 * This byte is delta Y.  If this is a plain mouse,
4927c478bd9Sstevel@tonic-gate 			 * we're done.  Wheel mice have two different flavors
4937c478bd9Sstevel@tonic-gate 			 * of fourth byte.
4947c478bd9Sstevel@tonic-gate 			 */
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 			if (elapsed > mouse_timeout) {
4977c478bd9Sstevel@tonic-gate 				goto restart;
4987c478bd9Sstevel@tonic-gate 			}
4997c478bd9Sstevel@tonic-gate 			STATEP->deltay |= code & 0xff;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 			if (STATEP->vuid_mouse_mode == MOUSE_MODE_WHEEL) {
5027c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_WHEEL_DELTA_Z;
5037c478bd9Sstevel@tonic-gate 				break;
5047c478bd9Sstevel@tonic-gate 			} else if (STATEP->vuid_mouse_mode ==
5057c478bd9Sstevel@tonic-gate 			    MOUSE_MODE_WHEEL5) {
5067c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_WHEEL5_DELTA_Z;
5077c478bd9Sstevel@tonic-gate 				break;
5087c478bd9Sstevel@tonic-gate 			}
5097c478bd9Sstevel@tonic-gate 			goto packet_complete;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 		case PS2_WHEEL5_DELTA_Z:
5127c478bd9Sstevel@tonic-gate 			if (code & 0x10) {
5137c478bd9Sstevel@tonic-gate 				/* fourth physical button */
5147c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)BUT(4),
5157c478bd9Sstevel@tonic-gate 				    FE_PAIR_NONE, 0, 1);
5167c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)BUT(4),
5177c478bd9Sstevel@tonic-gate 				    FE_PAIR_NONE, 0, 0);
5187c478bd9Sstevel@tonic-gate 			} else if (code & 0x20) {
5197c478bd9Sstevel@tonic-gate 				/* fifth physical button */
5207c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)BUT(5),
5217c478bd9Sstevel@tonic-gate 				    FE_PAIR_NONE, 0, 1);
5227c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)BUT(5),
5237c478bd9Sstevel@tonic-gate 				    FE_PAIR_NONE, 0, 0);
5247c478bd9Sstevel@tonic-gate 			}
5257c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 		case PS2_WHEEL_DELTA_Z:
5287c478bd9Sstevel@tonic-gate 			/*
5297c478bd9Sstevel@tonic-gate 			 * Check whether reporting vertical wheel
5307c478bd9Sstevel@tonic-gate 			 * movements is enabled
5317c478bd9Sstevel@tonic-gate 			 */
5327c478bd9Sstevel@tonic-gate 			code &= 0xf;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 			if (STATEP->wheel_state_bf & (1 <<
5357c478bd9Sstevel@tonic-gate 			    VUIDMICE_VERTICAL_WHEEL_ID)) {
5367c478bd9Sstevel@tonic-gate 				/*
5377c478bd9Sstevel@tonic-gate 				 * PS/2 mouse reports -ve values
5387c478bd9Sstevel@tonic-gate 				 * when the wheel is scrolled up. So
5397c478bd9Sstevel@tonic-gate 				 * we need to convert it into +ve as
5407c478bd9Sstevel@tonic-gate 				 * X interprets a +ve value as wheel up event.
5417c478bd9Sstevel@tonic-gate 				 * Same is true for the horizontal wheel also.
5427c478bd9Sstevel@tonic-gate 				 * The mouse reports 0xf when scrolled up
5437c478bd9Sstevel@tonic-gate 				 * and 0x1 when scrolled down. This observation
5447c478bd9Sstevel@tonic-gate 				 * is based on Logitech, HCL,
5457c478bd9Sstevel@tonic-gate 				 * Microsoft and Black Cat mouse only
5467c478bd9Sstevel@tonic-gate 				 */
5477c478bd9Sstevel@tonic-gate 				if (code == 0xf) {
5487c478bd9Sstevel@tonic-gate 					/* negative Z - wheel up */
5497c478bd9Sstevel@tonic-gate 					code |= 0xfffffff0;
5507c478bd9Sstevel@tonic-gate 					vuidmice_send_wheel_event(qp, 0,
5517c478bd9Sstevel@tonic-gate 					    FE_PAIR_NONE, 0, -code);
5527c478bd9Sstevel@tonic-gate 				} else if (code == 0x01) {
5537c478bd9Sstevel@tonic-gate 					/* positive Z - wheel down */
5547c478bd9Sstevel@tonic-gate 					vuidmice_send_wheel_event(qp, 0,
5557c478bd9Sstevel@tonic-gate 					    FE_PAIR_NONE, 0, -code);
5567c478bd9Sstevel@tonic-gate 				}
5577c478bd9Sstevel@tonic-gate 			}
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 			/*
5607c478bd9Sstevel@tonic-gate 			 * Check whether reporting horizontal wheel
5617c478bd9Sstevel@tonic-gate 			 * movements is enabled
5627c478bd9Sstevel@tonic-gate 			 */
5637c478bd9Sstevel@tonic-gate 			if (STATEP->wheel_state_bf &
5647c478bd9Sstevel@tonic-gate 			    (1 << VUIDMICE_HORIZONTAL_WHEEL_ID)) {
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 				/*
5677c478bd9Sstevel@tonic-gate 				 * The mouse return -7 and +7 when it
5687c478bd9Sstevel@tonic-gate 				 * is scrolled horizontally
5697c478bd9Sstevel@tonic-gate 				 */
5707c478bd9Sstevel@tonic-gate 				if (code == 0x09) {
5717c478bd9Sstevel@tonic-gate 					/* negative Z - wheel left */
5727c478bd9Sstevel@tonic-gate 					vuidmice_send_wheel_event(qp, 1,
5737c478bd9Sstevel@tonic-gate 					    FE_PAIR_NONE, 0, 1);
5747c478bd9Sstevel@tonic-gate 				} else if (code == 0x07) {
5757c478bd9Sstevel@tonic-gate 					/* positive Z - wheel right */
5767c478bd9Sstevel@tonic-gate 					vuidmice_send_wheel_event(qp, 1,
5777c478bd9Sstevel@tonic-gate 					    FE_PAIR_NONE, 0, -1);
5787c478bd9Sstevel@tonic-gate 				}
5797c478bd9Sstevel@tonic-gate 			}
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate packet_complete:
5827c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_START;
5837c478bd9Sstevel@tonic-gate 			/*
5847c478bd9Sstevel@tonic-gate 			 * If we can peek at the next mouse character, and
5857c478bd9Sstevel@tonic-gate 			 * its not the start of the next packet, don't use
5867c478bd9Sstevel@tonic-gate 			 * this packet.
5877c478bd9Sstevel@tonic-gate 			 */
58822eb7cb5Sgd78059 			if (mp->b_wptr > mp->b_rptr &&
5897c478bd9Sstevel@tonic-gate 			    ((mp->b_rptr[0] ^ STATEP->sync_byte) & 0x08)) {
5907c478bd9Sstevel@tonic-gate 				/*
5917c478bd9Sstevel@tonic-gate 				 * bit 3 not set
5927c478bd9Sstevel@tonic-gate 				 */
5937c478bd9Sstevel@tonic-gate 				break;
5947c478bd9Sstevel@tonic-gate 			}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 			/*
5977c478bd9Sstevel@tonic-gate 			 * send the info to the next level --
5987c478bd9Sstevel@tonic-gate 			 * need to send multiple events if we have both
5997c478bd9Sstevel@tonic-gate 			 * a delta *AND* button event(s)
6007c478bd9Sstevel@tonic-gate 			 */
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			/* motion has occurred ... */
6037c478bd9Sstevel@tonic-gate 			if (STATEP->deltax)
6047c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)LOC_X_DELTA,
6057c478bd9Sstevel@tonic-gate 				    FE_PAIR_ABSOLUTE, (uchar_t)LOC_X_ABSOLUTE,
6067c478bd9Sstevel@tonic-gate 				    STATEP->deltax);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 			if (STATEP->deltay)
6097c478bd9Sstevel@tonic-gate 				VUID_PUTNEXT(qp, (uchar_t)LOC_Y_DELTA,
6107c478bd9Sstevel@tonic-gate 				    FE_PAIR_ABSOLUTE, (uchar_t)LOC_Y_ABSOLUTE,
6117c478bd9Sstevel@tonic-gate 				    STATEP->deltay);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 			STATEP->deltax = STATEP->deltay = 0;
6147c478bd9Sstevel@tonic-gate 			break;
6157c478bd9Sstevel@tonic-gate 
61615bfc6b7SSeth Goldberg 		case PS2_WAIT_RESET_COMPLETE:
61752aa746fSlq150181 
61852aa746fSlq150181 			/*
61915bfc6b7SSeth Goldberg 			 * If length is 1, code holds the data from the message.
62015bfc6b7SSeth Goldberg 			 * for lengths > 1, we look at *(mp->b_rptr + offset)
62115bfc6b7SSeth Goldberg 			 * for the rest of the data.
62252aa746fSlq150181 			 */
62315bfc6b7SSeth Goldberg 			if (length == 1) {
62415bfc6b7SSeth Goldberg 				/*
625*5b81b7caSSeth Goldberg 				 * A response with length 1 from the mouse
626*5b81b7caSSeth Goldberg 				 * driver can be either an ACK (the first part
627*5b81b7caSSeth Goldberg 				 * of the reset reply) or either MSEERROR or
628*5b81b7caSSeth Goldberg 				 * MSERESEND.  Issue another reset if either
629*5b81b7caSSeth Goldberg 				 * of the latter are received.  For mice that
630*5b81b7caSSeth Goldberg 				 * are not connected, MSERESEND is received
631*5b81b7caSSeth Goldberg 				 * quickly.
63215bfc6b7SSeth Goldberg 				 */
633*5b81b7caSSeth Goldberg 
634*5b81b7caSSeth Goldberg 				if (code == MSE_ACK)
635*5b81b7caSSeth Goldberg 					break;
636*5b81b7caSSeth Goldberg 
63715bfc6b7SSeth Goldberg 				if (++STATEP->init_count >=
63815bfc6b7SSeth Goldberg 				    PS2_MAX_INIT_COUNT) {
63915bfc6b7SSeth Goldberg 					STATEP->inited |= PS2_FLAG_INIT_TIMEOUT;
64015bfc6b7SSeth Goldberg 					STATEP->state = PS2_WAIT_FOR_AA;
64115bfc6b7SSeth Goldberg 				} else {
64215bfc6b7SSeth Goldberg 					put1(WR(qp), MSERESET);
64315bfc6b7SSeth Goldberg 				}
644*5b81b7caSSeth Goldberg 
64515bfc6b7SSeth Goldberg 				break;
64615bfc6b7SSeth Goldberg 
647*5b81b7caSSeth Goldberg 			} else if (length != 2) {
648e19e2143Srui zang - Sun Microsystems - Beijing China 				break;
64952aa746fSlq150181 			}
65052aa746fSlq150181 
651*5b81b7caSSeth Goldberg 			/*
652*5b81b7caSSeth Goldberg 			 * The only possible 2-byte reply from mouse8042 is
653*5b81b7caSSeth Goldberg 			 * 0xAA 0x00.  If the mouse doesn't send that, mouse8042
654*5b81b7caSSeth Goldberg 			 * will send a 1-byte error message, handled above by
655*5b81b7caSSeth Goldberg 			 * resetting the mouse.
656*5b81b7caSSeth Goldberg 			 */
657*5b81b7caSSeth Goldberg 
658*5b81b7caSSeth Goldberg 			/* Skip past the 0x00 (since `code' contains 0xAA) */
659*5b81b7caSSeth Goldberg 			mp->b_rptr += 1;
6607c478bd9Sstevel@tonic-gate 
66115bfc6b7SSeth Goldberg 			/* Reset completed successfully */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_SETRES0_ACK1;
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 			/* Set timeout for set res */
66652aa746fSlq150181 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP);
6677c478bd9Sstevel@tonic-gate 
66815bfc6b7SSeth Goldberg 			/* Begin Logitech autodetect sequence */
66952aa746fSlq150181 			put1(WR(qp), MSESETRES);
6707c478bd9Sstevel@tonic-gate 			break;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SETRES0_ACK1:
6737c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
6747c478bd9Sstevel@tonic-gate 				break;
6757c478bd9Sstevel@tonic-gate 			}
6767c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_SETRES0_ACK2;
67752aa746fSlq150181 			put1(WR(qp), 0);
6787c478bd9Sstevel@tonic-gate 			break;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SETRES0_ACK2:
6817c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SCALE1_1_ACK:
6827c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SCALE1_2_ACK:
6837c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
6847c478bd9Sstevel@tonic-gate 				break;
6857c478bd9Sstevel@tonic-gate 			}
6867c478bd9Sstevel@tonic-gate 			STATEP->state++;
68752aa746fSlq150181 			put1(WR(qp), MSESCALE1);
6887c478bd9Sstevel@tonic-gate 			break;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SCALE1_3_ACK:
6917c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
6927c478bd9Sstevel@tonic-gate 				break;
6937c478bd9Sstevel@tonic-gate 			}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 			/* Set res and scale have been ok */
6967c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_STATREQ_ACK;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 			/* Set timeout for status request */
70152aa746fSlq150181 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP);
70252aa746fSlq150181 
70352aa746fSlq150181 			put1(WR(qp), MSESTATREQ);
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 			break;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STATREQ_ACK:
7087c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7097c478bd9Sstevel@tonic-gate 				break;
7107c478bd9Sstevel@tonic-gate 			}
7117c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_STATUS_1;
7127c478bd9Sstevel@tonic-gate 			break;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STATUS_1:
7157c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_STATUS_BUTTONS;
7167c478bd9Sstevel@tonic-gate 			break;
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STATUS_BUTTONS:
7197c478bd9Sstevel@tonic-gate 			if (code != 0) {
7207c478bd9Sstevel@tonic-gate 				STATEP->nbuttons = (uchar_t)code;
7217c478bd9Sstevel@tonic-gate 				STATEP->state = (uchar_t)PS2_WAIT_STATUS_REV;
7227c478bd9Sstevel@tonic-gate 			} else {
7237c478bd9Sstevel@tonic-gate #if	defined(VUID3PS2)
7247c478bd9Sstevel@tonic-gate 				/*
7257c478bd9Sstevel@tonic-gate 				 * It seems that there are some 3-button mice
7267c478bd9Sstevel@tonic-gate 				 * that don't play the Logitech autodetect
7277c478bd9Sstevel@tonic-gate 				 * game.  One is a Mouse Systems mouse OEM'ed
7287c478bd9Sstevel@tonic-gate 				 * by Intergraph.
7297c478bd9Sstevel@tonic-gate 				 *
7307c478bd9Sstevel@tonic-gate 				 * Until we find out how to autodetect these
7317c478bd9Sstevel@tonic-gate 				 * mice, we'll assume that if we're being
7327c478bd9Sstevel@tonic-gate 				 * compiled as vuid3ps2 and the mouse doesn't
7337c478bd9Sstevel@tonic-gate 				 * play the autodetect game, it's a 3-button
7347c478bd9Sstevel@tonic-gate 				 * mouse.  This effectively disables
7357c478bd9Sstevel@tonic-gate 				 * autodetect for mice using vuid3ps2, but
7367c478bd9Sstevel@tonic-gate 				 * since vuid3ps2 is used only on x86 where
7377c478bd9Sstevel@tonic-gate 				 * we currently assume manual configuration,
7387c478bd9Sstevel@tonic-gate 				 * this shouldn't be a problem.  At some point
7397c478bd9Sstevel@tonic-gate 				 * in the future when we *do* start using
7407c478bd9Sstevel@tonic-gate 				 * autodetect on x86, we should probably define
7417c478bd9Sstevel@tonic-gate 				 * VUIDPS2 instead of VUID3PS2.  Even then,
7427c478bd9Sstevel@tonic-gate 				 * we could leave this code so that *some*
7437c478bd9Sstevel@tonic-gate 				 * mice could use autodetect and others not.
7447c478bd9Sstevel@tonic-gate 				 */
7457c478bd9Sstevel@tonic-gate 				STATEP->nbuttons = 3;
7467c478bd9Sstevel@tonic-gate #else
7477c478bd9Sstevel@tonic-gate 				STATEP->nbuttons = 2;
7487c478bd9Sstevel@tonic-gate #endif
7497c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_WAIT_STATUS_3;
7507c478bd9Sstevel@tonic-gate 			}
7517c478bd9Sstevel@tonic-gate 			break;
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STATUS_REV:
7547c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STATUS_3:
7577c478bd9Sstevel@tonic-gate 
75815bfc6b7SSeth Goldberg 			/* Status request completed successfully */
7597c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
7607c478bd9Sstevel@tonic-gate 
76115bfc6b7SSeth Goldberg 			vuidmice_start_wdc_or_setres(qp);
7627c478bd9Sstevel@tonic-gate 			break;
76315bfc6b7SSeth Goldberg 
7647c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL1_CMD_ACK:
7657c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7667c478bd9Sstevel@tonic-gate 				break;
7677c478bd9Sstevel@tonic-gate 			}
7687c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_SMPL1_RATE_ACK;
76952aa746fSlq150181 			put1(WR(qp), 200);
7707c478bd9Sstevel@tonic-gate 			break;
7717c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL1_RATE_ACK:
7727c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7737c478bd9Sstevel@tonic-gate 				break;
7747c478bd9Sstevel@tonic-gate 			}
7757c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_SMPL2_CMD_ACK;
77652aa746fSlq150181 			put1(WR(qp), MSECHGMOD);
7777c478bd9Sstevel@tonic-gate 			break;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL2_CMD_ACK:
7807c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7817c478bd9Sstevel@tonic-gate 				break;
7827c478bd9Sstevel@tonic-gate 			}
7837c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_SMPL2_RATE_ACK;
78452aa746fSlq150181 			put1(WR(qp), 100);
7857c478bd9Sstevel@tonic-gate 			break;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL2_RATE_ACK:
7887c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7897c478bd9Sstevel@tonic-gate 				break;
7907c478bd9Sstevel@tonic-gate 			}
7917c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_SMPL3_CMD_ACK;
79252aa746fSlq150181 			put1(WR(qp), MSECHGMOD);
7937c478bd9Sstevel@tonic-gate 			break;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL3_CMD_ACK:
7967c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
7977c478bd9Sstevel@tonic-gate 				break;
7987c478bd9Sstevel@tonic-gate 			}
7997c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_SMPL3_RATE_ACK;
80052aa746fSlq150181 			put1(WR(qp), 80);
8017c478bd9Sstevel@tonic-gate 			break;
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_SMPL3_RATE_ACK:
8047c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8057c478bd9Sstevel@tonic-gate 				break;
8067c478bd9Sstevel@tonic-gate 			}
8077c478bd9Sstevel@tonic-gate 
80815bfc6b7SSeth Goldberg 			/* Set sample rate completed successfully */
8097c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_DEV_CMD;
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 			/* Set timeout for get dev */
8147c478bd9Sstevel@tonic-gate 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD);
8157c478bd9Sstevel@tonic-gate 
81652aa746fSlq150181 			put1(WR(qp), MSEGETDEV);
8177c478bd9Sstevel@tonic-gate 			break;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_DEV_CMD:
8207c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8217c478bd9Sstevel@tonic-gate 				break;
8227c478bd9Sstevel@tonic-gate 			}
8237c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL_DEV_ACK;
8247c478bd9Sstevel@tonic-gate 			break;
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL_DEV_ACK:
8277c478bd9Sstevel@tonic-gate 
82815bfc6b7SSeth Goldberg 			/* Get dev completed successfully */
8297c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 			if (code != 0x03) {
8327c478bd9Sstevel@tonic-gate 				STATEP->state = PS2_WAIT_SETRES3_ACK1;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 				/* Set timeout for set res */
8357c478bd9Sstevel@tonic-gate 				vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD);
8367c478bd9Sstevel@tonic-gate 
83752aa746fSlq150181 				put1(WR(qp), MSESETRES);
83852aa746fSlq150181 
8397c478bd9Sstevel@tonic-gate 				break;
8407c478bd9Sstevel@tonic-gate 			}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 			STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 			/*
8457c478bd9Sstevel@tonic-gate 			 * Found wheel. By default enable the wheel.
8467c478bd9Sstevel@tonic-gate 			 */
8477c478bd9Sstevel@tonic-gate 			STATEP->wheel_state_bf |= VUID_WHEEL_STATE_ENABLED;
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL1_CMD_ACK;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 			/* Set timeout for set sample rate */
85252aa746fSlq150181 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP);
85352aa746fSlq150181 
85452aa746fSlq150181 			/* We're on a roll - try for wheel+5 */
85552aa746fSlq150181 			put1(WR(qp), MSECHGMOD);
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 			break;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL1_CMD_ACK:
8607c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8617c478bd9Sstevel@tonic-gate 				break;
8627c478bd9Sstevel@tonic-gate 			}
8637c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL1_RATE_ACK;
86452aa746fSlq150181 			put1(WR(qp), 200);
8657c478bd9Sstevel@tonic-gate 			break;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL1_RATE_ACK:
8687c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8697c478bd9Sstevel@tonic-gate 				break;
8707c478bd9Sstevel@tonic-gate 			}
8717c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL2_CMD_ACK;
87252aa746fSlq150181 			put1(WR(qp), MSECHGMOD);
8737c478bd9Sstevel@tonic-gate 			break;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL2_CMD_ACK:
8767c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8777c478bd9Sstevel@tonic-gate 				break;
8787c478bd9Sstevel@tonic-gate 			}
8797c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL2_RATE_ACK;
88052aa746fSlq150181 			put1(WR(qp), 200);
8817c478bd9Sstevel@tonic-gate 			break;
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL2_RATE_ACK:
8847c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8857c478bd9Sstevel@tonic-gate 				break;
8867c478bd9Sstevel@tonic-gate 			}
8877c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL3_CMD_ACK;
88852aa746fSlq150181 			put1(WR(qp), MSECHGMOD);
8897c478bd9Sstevel@tonic-gate 			break;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL3_CMD_ACK:
8927c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
8937c478bd9Sstevel@tonic-gate 				break;
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_SMPL3_RATE_ACK;
89652aa746fSlq150181 			put1(WR(qp), 80);
8977c478bd9Sstevel@tonic-gate 			break;
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_SMPL3_RATE_ACK:
9007c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9017c478bd9Sstevel@tonic-gate 				break;
9027c478bd9Sstevel@tonic-gate 			}
9037c478bd9Sstevel@tonic-gate 
90415bfc6b7SSeth Goldberg 			/* Set sample rate completed successfully */
9057c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_DEV_CMD;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 			/* Set timeout for wheel5 get dev */
9107c478bd9Sstevel@tonic-gate 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD);
9117c478bd9Sstevel@tonic-gate 
91252aa746fSlq150181 			put1(WR(qp), MSEGETDEV);
91352aa746fSlq150181 
9147c478bd9Sstevel@tonic-gate 			break;
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_DEV_CMD:
9177c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9187c478bd9Sstevel@tonic-gate 				break;
9197c478bd9Sstevel@tonic-gate 			}
9207c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_WHEEL5_DEV_ACK;
9217c478bd9Sstevel@tonic-gate 			break;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 		case PS2_WAIT_WHEEL5_DEV_ACK:
9247c478bd9Sstevel@tonic-gate 			if (code == 0x04) {
9257c478bd9Sstevel@tonic-gate 				STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL5;
9267c478bd9Sstevel@tonic-gate 				STATEP->nbuttons	= 5;
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 				/*
9297c478bd9Sstevel@tonic-gate 				 * Found wheel. By default enable the wheel.
9307c478bd9Sstevel@tonic-gate 				 */
9317c478bd9Sstevel@tonic-gate 				STATEP->wheel_state_bf |=
9327c478bd9Sstevel@tonic-gate 				    VUID_WHEEL_STATE_ENABLED <<
9337c478bd9Sstevel@tonic-gate 				    MOUSE_MODE_WHEEL;
9347c478bd9Sstevel@tonic-gate 			}
9357c478bd9Sstevel@tonic-gate 
93615bfc6b7SSeth Goldberg 			/* Wheel5 get dev completed successfully */
9377c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SETRES3_CMD:
9427c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_SETRES3_ACK1;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 			/* Set timeout for set res */
9457c478bd9Sstevel@tonic-gate 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD);
9467c478bd9Sstevel@tonic-gate 
94752aa746fSlq150181 			put1(WR(qp), MSESETRES);
94852aa746fSlq150181 
9497c478bd9Sstevel@tonic-gate 			break;
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SETRES3_ACK1:
9527c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9537c478bd9Sstevel@tonic-gate 				break;
9547c478bd9Sstevel@tonic-gate 			}
9557c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_SETRES3_ACK2;
95652aa746fSlq150181 			put1(WR(qp), 3);
9577c478bd9Sstevel@tonic-gate 			break;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 		case PS2_WAIT_SETRES3_ACK2:
9607c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9617c478bd9Sstevel@tonic-gate 				break;
9627c478bd9Sstevel@tonic-gate 			}
9637c478bd9Sstevel@tonic-gate 
96415bfc6b7SSeth Goldberg 			/* Set res completed successfully */
9657c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_STREAM_ACK;
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 			/* Set timeout for enable */
9707c478bd9Sstevel@tonic-gate 			vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD);
9717c478bd9Sstevel@tonic-gate 
97252aa746fSlq150181 			put1(WR(qp), MSESTREAM);
97352aa746fSlq150181 
9747c478bd9Sstevel@tonic-gate 			break;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 		case PS2_WAIT_STREAM_ACK:
9777c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9787c478bd9Sstevel@tonic-gate 				break;
9797c478bd9Sstevel@tonic-gate 			}
9807c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_WAIT_ON_ACK;
98152aa746fSlq150181 			put1(WR(qp), MSEON);
9827c478bd9Sstevel@tonic-gate 			break;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 		case PS2_WAIT_ON_ACK:
9857c478bd9Sstevel@tonic-gate 			if (code != MSE_ACK) {
9867c478bd9Sstevel@tonic-gate 				break;
9877c478bd9Sstevel@tonic-gate 			}
9887c478bd9Sstevel@tonic-gate 
98915bfc6b7SSeth Goldberg 			/* Enable completed successfully */
99015bfc6b7SSeth Goldberg 
99115bfc6b7SSeth Goldberg 			/*
99215bfc6b7SSeth Goldberg 			 * The entire initialization sequence
99315bfc6b7SSeth Goldberg 			 * is complete.  Now, we can clear the
99415bfc6b7SSeth Goldberg 			 * init_count retry counter.
99515bfc6b7SSeth Goldberg 			 */
99615bfc6b7SSeth Goldberg 			STATEP->init_count = 0;
9977c478bd9Sstevel@tonic-gate 			vuid_cancel_timeout(qp);
9987c478bd9Sstevel@tonic-gate 
99915bfc6b7SSeth Goldberg 
10007c478bd9Sstevel@tonic-gate 			STATEP->state = PS2_START;
10017c478bd9Sstevel@tonic-gate 			break;
10027c478bd9Sstevel@tonic-gate 		}
10037c478bd9Sstevel@tonic-gate 	}
10047c478bd9Sstevel@tonic-gate 	freemsg(mp);
10057c478bd9Sstevel@tonic-gate }
1006