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