xref: /illumos-gate/usr/src/uts/common/io/zyd/zyd_usb.c (revision e8da18d8)
1*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
2*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Use is subject to license terms.
4*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
5*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
6*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
7*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Lukas Turek <turek@ksvi.mff.cuni.cz>
8*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Jiri Svoboda <jirik.svoboda@seznam.cz>
9*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2007 by  Martin Krulis <martin.krulis@matfyz.cz>
10*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
11*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
12*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
13*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and distribute this software for any
14*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
15*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
16*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
17*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
25*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
26*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
27*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
28*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * ZD1211 wLAN driver
29*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * USB communication
30*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
31*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Manage USB communication with the ZD-based device.
32*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
33*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
34*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/byteorder.h>
35*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/stream.h>
36*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/strsun.h>
37*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include <sys/mac_provider.h>
38*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
39*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include "zyd.h"
40*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #include "zyd_reg.h"
41*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
42*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_usb_disconnect(dev_info_t *dip);
43*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int zyd_usb_reconnect(dev_info_t *dip);
44*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res zyd_usb_data_in_start_request(struct zyd_usb *uc);
45*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
46*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_usb_info_t usb_ids[] = {
47*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x53, 0x5301, ZYD_ZD1211B},
48*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x105, 0x145f, ZYD_ZD1211},
49*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x411, 0xda, ZYD_ZD1211B},
50*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x471, 0x1236, ZYD_ZD1211B},
51*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x471, 0x1237, ZYD_ZD1211B},
52*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x50d, 0x705c, ZYD_ZD1211B},
53*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3401, ZYD_ZD1211},
54*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3402, ZYD_ZD1211},
55*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3407, ZYD_ZD1211},
56*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3409, ZYD_ZD1211},
57*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3410, ZYD_ZD1211B},
58*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3412, ZYD_ZD1211B},
59*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x3413, ZYD_ZD1211B},
60*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x340a, ZYD_ZD1211B},
61*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x586, 0x340f, ZYD_ZD1211B},
62*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x79b, 0x4a, ZYD_ZD1211},
63*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x79b, 0x62, ZYD_ZD1211B},
64*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x7b8, 0x6001, ZYD_ZD1211},
65*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x83a, 0x4505, ZYD_ZD1211B},
66*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xace, 0x1211, ZYD_ZD1211},
67*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xace, 0x1215, ZYD_ZD1211B},
68*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xb05, 0x170c, ZYD_ZD1211},
69*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xb05, 0x171b, ZYD_ZD1211B},
70*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xb3b, 0x1630, ZYD_ZD1211},
71*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xb3b, 0x5630, ZYD_ZD1211},
72*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xbaf, 0x121, ZYD_ZD1211B},
73*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xcde, 0x1a, ZYD_ZD1211B},
74*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xdf6, 0x9071, ZYD_ZD1211},
75*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0xdf6, 0x9075, ZYD_ZD1211},
76*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x126f, 0xa006, ZYD_ZD1211},
77*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x129b, 0x1666, ZYD_ZD1211},
78*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x129b, 0x1667, ZYD_ZD1211B},
79*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x13b1, 0x1e, ZYD_ZD1211},
80*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x13b1, 0x24, ZYD_ZD1211B},
81*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x1435, 0x711, ZYD_ZD1211},
82*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x14ea, 0xab13, ZYD_ZD1211},
83*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x157e, 0x300b, ZYD_ZD1211},
84*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x157e, 0x300d, ZYD_ZD1211B},
85*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x157e, 0x3204, ZYD_ZD1211},
86*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x1582, 0x6003, ZYD_ZD1211B},
87*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x1740, 0x2000, ZYD_ZD1211},
88*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x2019, 0x5303, ZYD_ZD1211B},
89*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	{0x6891, 0xa727, ZYD_ZD1211}
90*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
91*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
92*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
93*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Get mac rev for usb vendor/product id.
94*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
95*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_mac_rev_t
zyd_usb_mac_rev(uint16_t vendor,uint16_t product)96*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_mac_rev(uint16_t vendor, uint16_t product)
97*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
98*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int i;
99*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
100*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "matching device usb%x,%x\n", vendor, product));
101*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (i = 0; i < sizeof (usb_ids) / sizeof (zyd_usb_info_t); i++) {
102*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (vendor == usb_ids[i].vendor_id &&
103*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    product == usb_ids[i].product_id)
104*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (usb_ids[i].mac_rev);
105*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
106*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
107*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "assuming ZD1211B\n"));
108*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_ZD1211B);
109*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
110*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
111*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
112*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Vendor-specific write to the default control pipe.
113*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
114*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_ctrl_send(struct zyd_usb * uc,uint8_t request,uint16_t value,uint8_t * data,uint16_t len)115*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_ctrl_send(struct zyd_usb *uc, uint8_t request, uint16_t value,
116*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint8_t *data, uint16_t len)
117*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
118*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
119*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int retry = 0;
120*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *msg;
121*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ctrl_setup_t setup;
122*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
123*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Always clean structures before use */
124*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bzero(&setup, sizeof (setup));
125*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.bmRequestType =
126*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
127*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.bRequest = request;
128*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wValue = value;
129*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wIndex = 0;
130*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wLength = len;
131*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.attrs = USB_ATTRS_NONE;
132*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
133*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if ((msg = allocb(len, BPRI_HI)) == NULL)
134*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
135*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
136*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(data, msg->b_wptr, len);
137*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	msg->b_wptr += len;
138*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
139*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	while ((err = usb_pipe_ctrl_xfer_wait(uc->cdata->dev_default_ph,
140*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    &setup, &msg, NULL, NULL, 0)) != USB_SUCCESS) {
141*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (retry++ > 3)
142*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			break;
143*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
144*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
145*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	freemsg(msg);
146*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
147*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
148*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB,
149*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "control pipe send failure (%d)\n", err));
150*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
151*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
152*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
153*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
154*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
155*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
156*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
157*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Vendor-specific read from the default control pipe.
158*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
159*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_ctrl_recv(struct zyd_usb * uc,uint8_t request,uint16_t value,uint8_t * data,uint16_t len)160*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_ctrl_recv(struct zyd_usb *uc, uint8_t request, uint16_t value,
161*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint8_t *data, uint16_t len)
162*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
163*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int err;
164*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *msg, *tmp_msg;
165*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ctrl_setup_t setup;
166*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	size_t msg_len;
167*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
168*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(data != NULL);
169*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
170*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bzero(&setup, sizeof (setup));
171*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.bmRequestType =
172*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
173*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.bRequest = request;
174*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wValue = value;
175*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wIndex = 0;
176*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.wLength = len;
177*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	setup.attrs = USB_ATTRS_NONE;
178*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
179*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Pointer msg must be either set to NULL or point to a valid mblk! */
180*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	msg = NULL;
181*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	err = usb_pipe_ctrl_xfer_wait(uc->cdata->dev_default_ph,
182*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    &setup, &msg, NULL, NULL, 0);
183*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
184*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (err != USB_SUCCESS) {
185*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("control pipe receive failure (%d)\n", err);
186*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
187*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
188*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
189*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	msg_len = msgsize(msg);
190*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
191*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (msg_len != len) {
192*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("control pipe failure: "
193*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "received %d bytes, %d expected\n", (int)msg_len, len);
194*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
195*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
196*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
197*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (msg->b_cont != NULL) {
198*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Fragmented message, concatenate */
199*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		tmp_msg = msgpullup(msg, -1);
200*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(msg);
201*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		msg = tmp_msg;
202*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
203*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
204*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
205*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Now we can be sure the message is in a single block
206*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * so we can copy it.
207*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
208*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(msg->b_rptr, data, len);
209*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	freemsg(msg);
210*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
211*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
212*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
213*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
214*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
215*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Load firmware into the chip.
216*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
217*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_loadfirmware(struct zyd_usb * uc,uint8_t * fw,size_t size)218*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_loadfirmware(struct zyd_usb *uc, uint8_t *fw, size_t size)
219*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
220*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint16_t addr;
221*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint8_t stat;
222*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
223*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_FW, "firmware size: %lu\n", size));
224*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
225*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	addr = ZYD_FIRMWARE_START_ADDR;
226*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	while (size > 0) {
227*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		const uint16_t mlen = (uint16_t)min(size, 4096);
228*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
229*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (zyd_usb_ctrl_send(uc, ZYD_DOWNLOADREQ, addr, fw, mlen)
230*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    != USB_SUCCESS)
231*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (ZYD_FAILURE);
232*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
233*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		addr += mlen / 2;
234*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		fw += mlen;
235*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		size -= mlen;
236*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
237*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
238*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* check whether the upload succeeded */
239*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_ctrl_recv(uc, ZYD_DOWNLOADSTS, 0, &stat, sizeof (stat))
240*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    != ZYD_SUCCESS)
241*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
242*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
243*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return ((stat & 0x80) ? ZYD_FAILURE : ZYD_SUCCESS);
244*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
245*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
246*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
247*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Return a specific alt_if from the device descriptor tree.
248*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
249*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static usb_alt_if_data_t *
usb_lookup_alt_if(usb_client_dev_data_t * cdd,uint_t config,uint_t interface,uint_t alt)250*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China usb_lookup_alt_if(usb_client_dev_data_t *cdd, uint_t config,
251*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t interface, uint_t alt)
252*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
253*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_cfg_data_t *dcfg;
254*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_if_data_t *cfgif;
255*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_alt_if_data_t *ifalt;
256*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
257*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
258*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Assume everything is in the tree for now,
259*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * (USB_PARSE_LVL_ALL)
260*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * so we can directly index the array.
261*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
262*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
263*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Descend to configuration, configs are 1-based */
264*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (config < 1 || config > cdd->dev_n_cfg)
265*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (NULL);
266*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	dcfg = &cdd->dev_cfg[config - 1];
267*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
268*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Descend to interface */
269*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (interface > dcfg->cfg_n_if - 1)
270*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (NULL);
271*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cfgif = &dcfg->cfg_if[interface];
272*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
273*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Descend to alt */
274*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (alt > cfgif->if_n_alt - 1)
275*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (NULL);
276*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ifalt = &cfgif->if_alt[alt];
277*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
278*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ifalt);
279*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
280*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
281*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
282*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Print all endpoints of an alt_if.
283*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
284*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
usb_list_all_endpoints(usb_alt_if_data_t * ifalt)285*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China usb_list_all_endpoints(usb_alt_if_data_t *ifalt)
286*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
287*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ep_data_t *ep_data;
288*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ep_descr_t *ep_descr;
289*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int i;
290*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
291*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (i = 0; i < ifalt->altif_n_ep; i++) {
292*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_data = &ifalt->altif_ep[i];
293*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_descr = &ep_data->ep_descr;
294*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "EP: %u\n", ep_descr->bEndpointAddress);
295*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
296*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
297*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
298*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
299*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * For the given alt_if, find an endpoint with the given
300*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * address and direction.
301*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
302*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      ep_direction    USB_EP_DIR_IN or USB_EP_DIR_OUT
303*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
304*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static usb_ep_data_t *
usb_find_endpoint(usb_alt_if_data_t * alt_if,uint_t ep_address,uint_t ep_direction)305*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China usb_find_endpoint(usb_alt_if_data_t *alt_if,
306*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t ep_address, uint_t ep_direction)
307*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
308*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ep_data_t *ep_data;
309*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_ep_descr_t *ep_descr;
310*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint_t ep_addr, ep_dir;
311*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int i;
312*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
313*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (i = 0; i < alt_if->altif_n_ep; i++) {
314*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_data = &alt_if->altif_ep[i];
315*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_descr = &ep_data->ep_descr;
316*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_addr = ep_descr->bEndpointAddress & USB_EP_NUM_MASK;
317*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ep_dir = ep_descr->bEndpointAddress & USB_EP_DIR_MASK;
318*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
319*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (ep_addr == ep_address && ep_dir == ep_direction) {
320*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (ep_data);
321*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
322*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
323*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
324*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_WARN("no endpoint with addr %u, dir %u\n", ep_address,
325*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ep_direction);
326*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (NULL);
327*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
328*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
329*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China enum zyd_usb_use_attr
330*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
331*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_USB_USE_ATTR = 1,
332*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_USB_NO_ATTR = 0
333*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China };
334*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
335*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
336*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Open a pipe to a given endpoint address/direction in the given
337*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * alt_if. Furthemore, if use_attr == ZYD_USB_USE_ATTR,
338*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * check whether the endpoint's transfer type is attr.
339*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
340*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_open_pipe(struct zyd_usb * uc,usb_alt_if_data_t * alt_if,uint_t ep_address,uint_t ep_direction,uint_t attr,enum zyd_usb_use_attr use_attr,usb_pipe_handle_t * pipe,usb_ep_data_t * endpoint)341*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_open_pipe(struct zyd_usb *uc,
342*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     usb_alt_if_data_t *alt_if,
343*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t ep_address,
344*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t ep_direction,
345*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint_t attr,
346*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     enum zyd_usb_use_attr use_attr,
347*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     usb_pipe_handle_t *pipe, usb_ep_data_t *endpoint)
348*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
349*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_pipe_policy_t pipe_policy;
350*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
351*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	*endpoint = *usb_find_endpoint(alt_if, ep_address, ep_direction);
352*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
353*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if ((use_attr == ZYD_USB_USE_ATTR) &&
354*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    (endpoint->ep_descr.bmAttributes & USB_EP_ATTR_MASK) != attr) {
355*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
356*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("endpoint %u/%s is not of type %s\n", ep_address,
357*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    (ep_direction == USB_EP_DIR_IN) ? "IN" : "OUT",
358*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    (attr == USB_EP_ATTR_BULK) ? "bulk" : "intr");
359*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
360*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
361*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
362*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bzero(&pipe_policy, sizeof (usb_pipe_policy_t));
363*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	pipe_policy.pp_max_async_reqs = ZYD_USB_REQ_COUNT;
364*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
365*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (usb_pipe_open(uc->dip, &endpoint->ep_descr,
366*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    &pipe_policy, USB_FLAGS_SLEEP, pipe) != USB_SUCCESS) {
367*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to open pipe %u\n", ep_address);
368*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
369*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
370*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
371*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
372*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
373*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
374*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
375*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Open communication pipes.
376*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
377*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * The following pipes are used by the ZD1211:
378*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
379*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      1/OUT BULK
380*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      2/IN  BULK
381*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      3/IN  INTR
382*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      4/OUT BULK or INTR
383*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
384*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_open_pipes(struct zyd_usb * uc)385*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_open_pipes(struct zyd_usb *uc)
386*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
387*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_alt_if_data_t *alt_if;
388*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
389*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "opening pipes\n"));
390*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
391*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	alt_if = usb_lookup_alt_if(uc->cdata, ZYD_USB_CONFIG_NUMBER,
392*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_USB_IFACE_INDEX, ZYD_USB_ALT_IF_INDEX);
393*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
394*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (alt_if == NULL) {
395*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("alt_if not found\n");
396*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
397*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
398*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
399*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG
400*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_dbg_flags & ZYD_DBG_USB)
401*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_list_all_endpoints(alt_if);
402*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China #endif
403*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
404*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_open_pipe(uc, alt_if, 1, USB_EP_DIR_OUT, USB_EP_ATTR_BULK,
405*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_USB_USE_ATTR, &uc->pipe_data_out, &uc->ep_data_out) !=
406*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_SUCCESS) {
407*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to open data OUT pipe\n");
408*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
409*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
410*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
411*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_open_pipe(uc, alt_if, 2, USB_EP_DIR_IN, USB_EP_ATTR_BULK,
412*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_USB_USE_ATTR, &uc->pipe_data_in, &uc->ep_data_in) !=
413*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_SUCCESS) {
414*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to open data IN pipe\n");
415*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
416*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
417*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
418*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_open_pipe(uc, alt_if, 3, USB_EP_DIR_IN, USB_EP_ATTR_INTR,
419*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_USB_USE_ATTR, &uc->pipe_cmd_in, &uc->ep_cmd_in) !=
420*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_SUCCESS) {
421*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to open command IN pipe\n");
422*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
423*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
424*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
425*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
426*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * Pipe 4/OUT is either a bulk or interrupt pipe.
427*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
428*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_open_pipe(uc, alt_if, 4, USB_EP_DIR_OUT, 0,
429*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_USB_NO_ATTR, &uc->pipe_cmd_out, &uc->ep_cmd_out) !=
430*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    ZYD_SUCCESS) {
431*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to open command OUT pipe\n");
432*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
433*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
434*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
435*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
436*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
437*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China fail:
438*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_usb_close_pipes(uc);
439*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_FAILURE);
440*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
441*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
442*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
443*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Close communication pipes.
444*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
445*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_usb_close_pipes(struct zyd_usb * uc)446*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_close_pipes(struct zyd_usb *uc)
447*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
448*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "closing pipes\n"));
449*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
450*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->pipe_data_out != NULL) {
451*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_close(uc->dip, uc->pipe_data_out, USB_FLAGS_SLEEP,
452*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    NULL, NULL);
453*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		uc->pipe_data_out = NULL;
454*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
455*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
456*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->pipe_data_in != NULL) {
457*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_close(uc->dip, uc->pipe_data_in, USB_FLAGS_SLEEP,
458*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    NULL, NULL);
459*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		uc->pipe_data_in = NULL;
460*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
461*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
462*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->pipe_cmd_in != NULL) {
463*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_close(uc->dip, uc->pipe_cmd_in, USB_FLAGS_SLEEP,
464*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    NULL, NULL);
465*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		uc->pipe_cmd_in = NULL;
466*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
467*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
468*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->pipe_cmd_out != NULL) {
469*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_close(uc->dip, uc->pipe_cmd_out, USB_FLAGS_SLEEP,
470*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    NULL, NULL);
471*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		uc->pipe_cmd_out = NULL;
472*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
473*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
474*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
475*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
476*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Send a sequence of bytes to a bulk pipe.
477*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
478*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc      pointer to usb module state
479*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      data    pointer to a buffer of bytes
480*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      len     size of the buffer (bytes)
481*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
482*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
483*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_data_out_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)484*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_data_out_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
485*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
486*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc = (struct zyd_softc *)req->bulk_client_private;
487*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->ic;
488*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	boolean_t resched;
489*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
490*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (req->bulk_completion_reason != USB_CR_OK)
491*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "data OUT exception\n"));
492*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
493*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
494*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->tx_queued > 0)
495*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->tx_queued--;
496*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	else
497*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_TX, "tx queue underrun\n"));
498*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
499*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->resched && (sc->tx_queued < ZYD_TX_LIST_COUNT)) {
500*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		resched = sc->resched;
501*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->resched = B_FALSE;
502*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
503*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
504*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
505*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (resched)
506*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		mac_tx_update(ic->ic_mach);
507*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
508*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
509*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
510*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
511*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
512*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when the transfer from zyd_usb_bulk_pipe_send() terminates
513*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * or an exception occurs on the pipe.
514*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
515*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
516*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_bulk_pipe_cb(usb_pipe_handle_t pipe,struct usb_bulk_req * req)517*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_bulk_pipe_cb(usb_pipe_handle_t pipe, struct usb_bulk_req *req)
518*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
519*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_cb_lock *lock;
520*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	lock = (struct zyd_cb_lock *)req->bulk_client_private;
521*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
522*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Just signal that something happened */
523*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_signal(lock);
524*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
525*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
526*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_bulk_pipe_send(struct zyd_usb * uc,usb_pipe_handle_t pipe,const void * data,size_t len)527*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_bulk_pipe_send(struct zyd_usb *uc,
528*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     usb_pipe_handle_t pipe, const void *data, size_t len)
529*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
530*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_bulk_req_t *send_req;
531*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *mblk;
532*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
533*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_cb_lock lock;
534*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
535*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req = usb_alloc_bulk_req(uc->dip, len, USB_FLAGS_SLEEP);
536*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (send_req == NULL) {
537*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate bulk request\n");
538*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
539*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
540*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_len = (uint_t)len;
541*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_client_private = (usb_opaque_t)&lock;
542*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
543*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_timeout = 5;
544*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_cb = zyd_bulk_pipe_cb;
545*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_exc_cb = zyd_bulk_pipe_cb;
546*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
547*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk = send_req->bulk_data;
548*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(data, mblk->b_wptr, len);
549*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk->b_wptr += len;
550*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
551*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_init(&lock);
552*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
553*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = usb_pipe_bulk_xfer(pipe, send_req, USB_FLAGS_NOSLEEP);
554*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
555*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB,
556*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "failed writing to bulk OUT pipe (%d)\n", res));
557*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_bulk_req(send_req);
558*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_cb_lock_destroy(&lock);
559*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
560*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
561*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
562*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_cb_lock_wait(&lock, 1000000) != ZYD_SUCCESS) {
563*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("timeout - pipe reset\n");
564*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_reset(uc->dip, pipe, USB_FLAGS_SLEEP, NULL, 0);
565*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_cb_lock_wait(&lock, -1);
566*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = ZYD_FAILURE;
567*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
568*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = (send_req->bulk_completion_reason == USB_CR_OK) ?
569*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ZYD_SUCCESS : ZYD_FAILURE;
570*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
571*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
572*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_bulk_req(send_req);
573*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_destroy(&lock);
574*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (res);
575*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
576*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
577*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
578*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when the transfer from zyd_usb_intr_pipe_send() terminates
579*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * or an exception occurs on the pipe.
580*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
581*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
582*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_intr_pipe_cb(usb_pipe_handle_t pipe,struct usb_intr_req * req)583*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_intr_pipe_cb(usb_pipe_handle_t pipe, struct usb_intr_req *req)
584*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
585*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_cb_lock *lock;
586*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	lock = (struct zyd_cb_lock *)req->intr_client_private;
587*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
588*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Just signal that something happened */
589*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_signal(lock);
590*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
591*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
592*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
593*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Send a sequence of bytes to an interrupt pipe.
594*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
595*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc      pointer to usb module state
596*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      data    pointer to a buffer of bytes
597*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      len     size of the buffer (bytes)
598*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
599*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_intr_pipe_send(struct zyd_usb * uc,usb_pipe_handle_t pipe,const void * data,size_t len)600*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_intr_pipe_send(struct zyd_usb *uc,
601*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     usb_pipe_handle_t pipe, const void *data, size_t len)
602*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
603*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_intr_req_t *send_req;
604*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *mblk;
605*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
606*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_cb_lock lock;
607*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
608*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req = usb_alloc_intr_req(uc->dip, len, USB_FLAGS_SLEEP);
609*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (send_req == NULL) {
610*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate interupt request\n");
611*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
612*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
613*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_len = (uint_t)len;
614*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_client_private = (usb_opaque_t)&lock;
615*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_attributes = USB_ATTRS_AUTOCLEARING;
616*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_timeout = 5;
617*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_cb = zyd_intr_pipe_cb;
618*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->intr_exc_cb = zyd_intr_pipe_cb;
619*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
620*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk = send_req->intr_data;
621*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(data, mblk->b_wptr, len);
622*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk->b_wptr += len;
623*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
624*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_init(&lock);
625*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
626*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = usb_pipe_intr_xfer(pipe, send_req, 0);
627*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
628*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB,
629*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "failed writing to intr/out pipe (%d)\n", res));
630*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_intr_req(send_req);
631*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_cb_lock_destroy(&lock);
632*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
633*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
634*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
635*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_cb_lock_wait(&lock, 1000000) != ZYD_SUCCESS) {
636*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("timeout - pipe reset\n");
637*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_pipe_reset(uc->dip, pipe, USB_FLAGS_SLEEP, NULL, 0);
638*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		(void) zyd_cb_lock_wait(&lock, -1);
639*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = ZYD_FAILURE;
640*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
641*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = (send_req->intr_completion_reason == USB_CR_OK) ?
642*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ZYD_SUCCESS : ZYD_FAILURE;
643*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
644*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
645*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_intr_req(send_req);
646*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_cb_lock_destroy(&lock);
647*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (res);
648*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
649*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
650*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
651*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Send a sequence of bytes to the cmd_out pipe. (in a single USB transfer)
652*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
653*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc      pointer to usb module state
654*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      data    pointer to a buffer of bytes
655*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      len     size of the buffer (bytes)
656*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
657*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_cmd_pipe_send(struct zyd_usb * uc,const void * data,size_t len)658*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_cmd_pipe_send(struct zyd_usb *uc, const void *data, size_t len)
659*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
660*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_res res;
661*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint8_t type;
662*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
663*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Determine the type of cmd_out */
664*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	type = uc->ep_cmd_out.ep_descr.bmAttributes & USB_EP_ATTR_MASK;
665*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (type == USB_EP_ATTR_BULK)
666*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = zyd_usb_bulk_pipe_send(uc, uc->pipe_cmd_out, data, len);
667*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	else
668*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		res = zyd_usb_intr_pipe_send(uc, uc->pipe_cmd_out, data, len);
669*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
670*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (res);
671*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
672*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
673*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
674*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
675*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Format and send a command to the cmd_out pipe.
676*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
677*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc      pointer to usb module state
678*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      code    ZD command code (16-bit)
679*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      data    raw buffer containing command data
680*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      len     size of the data buffer (bytes)
681*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
682*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_cmd_send(struct zyd_usb * uc,uint16_t code,const void * data,size_t len)683*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_cmd_send(struct zyd_usb *uc,
684*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     uint16_t code, const void *data, size_t len)
685*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
686*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_res res;
687*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_cmd cmd;
688*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
689*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cmd.cmd_code = LE_16(code);
690*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(data, cmd.data, len);
691*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
692*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = zyd_usb_cmd_pipe_send(uc, &cmd, sizeof (uint16_t) + len);
693*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != ZYD_SUCCESS) {
694*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "failed writing command (%d)\n", res));
695*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
696*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
697*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
698*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
699*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
700*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
701*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
702*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Issue an ioread request.
703*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
704*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Issues a ZD ioread command (with a vector of addresses passed in raw
705*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * form as in_data) and blocks until the response is received
706*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * and filled into the response buffer.
707*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
708*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc              pointer to usb module state
709*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      in_data         pointer to request data
710*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      in_len          request data size (bytes)
711*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      out_data        pointer to response buffer
712*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      out_len         response buffer size (bytes)
713*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
714*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_ioread_req(struct zyd_usb * uc,const void * in_data,size_t in_len,void * out_data,size_t out_len)715*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_ioread_req(struct zyd_usb *uc,
716*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China     const void *in_data, size_t in_len, void *out_data, size_t out_len)
717*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
718*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_res res;
719*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int cnt;
720*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
721*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Initialise io_read structure */
722*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->io_read.done = B_FALSE;
723*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->io_read.buffer = out_data;
724*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->io_read.buf_len = (int)out_len;
725*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
726*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->io_read.pending = B_TRUE;
727*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
728*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = zyd_usb_cmd_send(uc, ZYD_CMD_IORD, in_data, in_len);
729*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != ZYD_SUCCESS) {
730*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "IO read request: pipe failure(%d)\n"));
731*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
732*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
733*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
734*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	cnt = 0;
735*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	while (uc->io_read.done != B_TRUE && cnt < 500) {
736*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		delay(drv_usectohz(10 * 1000));
737*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		++cnt;
738*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
739*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
740*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->io_read.done != B_TRUE) {
741*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("I/O read request: timeout\n");
742*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
743*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
744*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
745*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (uc->io_read.exc != B_FALSE) {
746*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "I/O read request: exception\n"));
747*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
748*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
749*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
750*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
751*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
752*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
753*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
754*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
755*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when data arrives from the cmd_in pipe.
756*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
757*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
758*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_cmd_in_cb(usb_pipe_handle_t pipe,usb_intr_req_t * req)759*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cmd_in_cb(usb_pipe_handle_t pipe, usb_intr_req_t *req)
760*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
761*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
762*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_ioread *rdp;
763*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *mblk, *tmp_blk;
764*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	unsigned char *data;
765*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	size_t len;
766*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uint16_t code;
767*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
768*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = (struct zyd_usb *)req->intr_client_private;
769*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(uc != NULL);
770*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rdp = &uc->io_read;
771*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk = req->intr_data;
772*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
773*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (mblk->b_cont != NULL) {
774*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Fragmented message, concatenate */
775*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		tmp_blk = msgpullup(mblk, -1);
776*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		data = tmp_blk->b_rptr;
777*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		len = MBLKL(tmp_blk);
778*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
779*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Non-fragmented message, use directly */
780*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		tmp_blk = NULL;
781*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		data = mblk->b_rptr;
782*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		len = MBLKL(mblk);
783*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
784*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
785*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	code = LE_16(*(uint16_t *)(uintptr_t)data);
786*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (code != ZYD_RESPONSE_IOREAD) {
787*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Other response types not handled yet */
788*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_intr_req(req);
789*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
790*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
791*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
792*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (rdp->pending != B_TRUE) {
793*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("no ioread pending\n");
794*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_intr_req(req);
795*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
796*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
797*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rdp->pending = B_FALSE;
798*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
799*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Now move on to the data part */
800*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	data += sizeof (uint16_t);
801*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	len -= sizeof (uint16_t);
802*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (rdp->buf_len > len) {
803*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("too few bytes received\n");
804*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
805*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
806*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(data, rdp->buffer, rdp->buf_len);
807*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
808*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (tmp_blk != NULL)
809*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(tmp_blk);
810*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
811*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rdp->exc = B_FALSE;
812*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rdp->done = B_TRUE;
813*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_intr_req(req);
814*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
815*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
816*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
817*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when an exception occurs on the cmd_in pipe.
818*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
819*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
820*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_cmd_in_exc_cb(usb_pipe_handle_t pipe,usb_intr_req_t * req)821*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_cmd_in_exc_cb(usb_pipe_handle_t pipe, usb_intr_req_t *req)
822*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
823*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
824*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_ioread *rdp;
825*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
826*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "command IN exception\n"));
827*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
828*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = (struct zyd_usb *)req->intr_client_private;
829*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(uc != NULL);
830*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	rdp = &uc->io_read;
831*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
832*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (rdp->pending == B_TRUE) {
833*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rdp->exc = B_TRUE;
834*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		rdp->done = B_TRUE;
835*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
836*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_intr_req(req);
837*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
838*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
839*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
840*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Start interrupt polling on the cmd_in pipe.
841*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
842*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_cmd_in_start_polling(struct zyd_usb * uc)843*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_cmd_in_start_polling(struct zyd_usb *uc)
844*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
845*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_intr_req_t *intr_req;
846*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
847*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
848*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req = usb_alloc_intr_req(uc->dip, 0, USB_FLAGS_SLEEP);
849*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (intr_req == NULL) {
850*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate interrupt request\n");
851*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
852*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
853*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
854*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req->intr_attributes = USB_ATTRS_SHORT_XFER_OK;
855*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req->intr_len = uc->ep_cmd_in.ep_descr.wMaxPacketSize;
856*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req->intr_cb = zyd_cmd_in_cb;
857*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req->intr_exc_cb = zyd_cmd_in_exc_cb;
858*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	intr_req->intr_client_private = (usb_opaque_t)uc;
859*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
860*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = usb_pipe_intr_xfer(uc->pipe_cmd_in, intr_req, USB_FLAGS_NOSLEEP);
861*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
862*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed starting command IN polling: pipe failure\n");
863*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_intr_req(intr_req);
864*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
865*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
866*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
867*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
868*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
869*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
870*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
871*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Stop interrupt polling on the cmd_in pipe.
872*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
873*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_usb_cmd_in_stop_polling(struct zyd_usb * uc)874*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_cmd_in_stop_polling(struct zyd_usb *uc)
875*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
876*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "stopping command IN polling\n"));
877*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
878*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_pipe_stop_intr_polling(uc->pipe_cmd_in, USB_FLAGS_SLEEP);
879*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
880*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
881*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
882*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when data arrives on the data_in pipe.
883*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
884*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
885*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_data_in_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)886*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_data_in_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
887*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
888*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc;
889*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
890*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk_t *mblk, *tmp_blk;
891*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_rx_desc *desc;
892*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	unsigned char *data;
893*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	size_t len;
894*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
895*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = (struct zyd_usb *)req->bulk_client_private;
896*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(uc != NULL);
897*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc = ZYD_USB_TO_SOFTC(uc);
898*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
899*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	mblk = req->bulk_data;
900*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
901*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* Fragmented STREAMS message? */
902*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (mblk->b_cont != NULL) {
903*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Fragmented, concatenate it into a single block */
904*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		tmp_blk = msgpullup(mblk, -1);
905*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (tmp_blk == NULL) {
906*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ZYD_WARN("failed to concatenate fragments\n");
907*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			goto error;
908*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
909*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		data = tmp_blk->b_rptr;
910*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		len = MBLKL(tmp_blk);
911*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
912*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* Not fragmented, use directly */
913*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		tmp_blk = NULL;
914*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		data = mblk->b_rptr;
915*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		len = MBLKL(mblk);
916*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
917*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
918*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (len < 2) {
919*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("received usb transfer too short\n");
920*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto error;
921*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
922*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
923*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
924*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * If this is a composite packet, the last two bytes contain
925*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * two special signature bytes.
926*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
927*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	desc = (struct zyd_rx_desc *)(data + len) - 1;
928*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* multi-frame transfer */
929*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (LE_16(desc->tag) == ZYD_TAG_MULTIFRAME) {
930*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		const uint8_t *p = data, *end = data + len;
931*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		int i;
932*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
933*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_RX, "composite packet\n"));
934*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
935*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) {
936*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			const uint16_t len16 = LE_16(desc->len[i]);
937*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			if (len16 == 0 || p + len16 > end)
938*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 				break;
939*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_receive(ZYD_USB_TO_SOFTC(uc), p, len16);
940*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			/* next frame is aligned on a 32-bit boundary */
941*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			p += (len16 + 3) & ~3;
942*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
943*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	} else {
944*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		/* single-frame transfer */
945*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_receive(ZYD_USB_TO_SOFTC(uc), data, MBLKL(mblk));
946*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
947*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
948*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China error:
949*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (tmp_blk != NULL)
950*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		freemsg(tmp_blk);
951*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
952*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
953*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
954*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!sc->running)
955*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return;
956*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
957*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_usb_data_in_start_request(uc) != ZYD_SUCCESS) {
958*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("error restarting data_in transfer\n");
959*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
960*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
961*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
962*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
963*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Called when an exception occurs on the data_in pipe.
964*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
965*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/
966*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static void
zyd_data_in_exc_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)967*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_data_in_exc_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
968*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
969*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
970*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
971*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_USB, "data IN exception\n"));
972*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
973*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = (struct zyd_usb *)req->bulk_client_private;
974*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(uc != NULL);
975*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
976*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_free_bulk_req(req);
977*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
978*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
979*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
980*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Start a receive request on the data_in pipe.
981*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
982*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static zyd_res
zyd_usb_data_in_start_request(struct zyd_usb * uc)983*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_data_in_start_request(struct zyd_usb *uc)
984*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
985*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_bulk_req_t *req;
986*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
987*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
988*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req = usb_alloc_bulk_req(uc->dip, ZYD_RX_BUF_SIZE, USB_FLAGS_SLEEP);
989*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (req == NULL) {
990*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate bulk IN request\n");
991*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
992*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
993*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
994*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_len = (uint_t)ZYD_RX_BUF_SIZE;
995*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_timeout = 0;
996*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_client_private = (usb_opaque_t)uc;
997*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_attributes =
998*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
999*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_cb = zyd_data_in_cb;
1000*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	req->bulk_exc_cb = zyd_data_in_exc_cb;
1001*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1002*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = usb_pipe_bulk_xfer(uc->pipe_data_in, req, USB_FLAGS_NOSLEEP);
1003*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
1004*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("error starting receive request on data_in pipe\n");
1005*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_bulk_req(req);
1006*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
1007*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1008*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1009*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
1010*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1011*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1012*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1013*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1014*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Start receiving packets on the data_in pipe.
1015*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1016*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_data_in_enable(struct zyd_usb * uc)1017*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_data_in_enable(struct zyd_usb *uc)
1018*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1019*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	for (int i = 0; i < ZYD_RX_LIST_COUNT; i++) {
1020*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (zyd_usb_data_in_start_request(uc) != ZYD_SUCCESS) {
1021*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ZYD_WARN("failed to start data IN requests\n");
1022*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (ZYD_FAILURE);
1023*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
1024*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1025*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
1026*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1027*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1028*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1029*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Stop receiving packets on the data_in pipe.
1030*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1031*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_usb_data_in_disable(struct zyd_usb * uc)1032*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_data_in_disable(struct zyd_usb *uc)
1033*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1034*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_pipe_reset(uc->dip, uc->pipe_data_in, USB_FLAGS_SLEEP,
1035*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    NULL, NULL);
1036*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1037*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1038*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1039*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Send a packet to data_out.
1040*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1041*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * A packet consists of a zyd_tx_header + the IEEE802.11 frame.
1042*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1043*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_send_packet(struct zyd_usb * uc,mblk_t * mp)1044*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_send_packet(struct zyd_usb *uc, mblk_t *mp)
1045*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1046*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_bulk_req_t *send_req;
1047*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int res;
1048*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1049*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req = usb_alloc_bulk_req(uc->dip, 0, USB_FLAGS_SLEEP);
1050*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (send_req == NULL) {
1051*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to allocate bulk request\n");
1052*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
1053*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1054*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1055*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_len = msgdsize(mp);
1056*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_data = mp;
1057*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_timeout = 5;
1058*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
1059*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_client_private = (usb_opaque_t)ZYD_USB_TO_SOFTC(uc);
1060*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_cb = zyd_data_out_cb;
1061*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_exc_cb = zyd_data_out_cb;
1062*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_completion_reason = 0;
1063*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	send_req->bulk_cb_flags = 0;
1064*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1065*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	res = usb_pipe_bulk_xfer(uc->pipe_data_out, send_req, 0);
1066*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (res != USB_SUCCESS) {
1067*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB,
1068*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "failed writing to bulk/out pipe (%d)\n", res));
1069*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		usb_free_bulk_req(send_req);
1070*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (USB_FAILURE);
1071*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1072*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1073*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (USB_SUCCESS);
1074*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1075*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1076*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1077*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Initialize USB device communication and USB module state.
1078*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *
1079*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      uc      pointer to usb module state
1080*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  *      dip     pointer to device info structure
1081*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1082*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_res
zyd_usb_init(struct zyd_softc * sc)1083*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_init(struct zyd_softc *sc)
1084*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1085*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc = &sc->usb;
1086*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	dev_info_t *dip = sc->dip;
1087*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	int ures;
1088*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1089*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->dip = dip;
1090*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1091*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ures = usb_client_attach(uc->dip, USBDRV_VERSION, 0);
1092*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ures != USB_SUCCESS) {
1093*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("usb_client_attach failed, error code: %d\n", ures);
1094*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (ZYD_FAILURE);
1095*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1096*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1097*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/*
1098*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * LVL_ALL is needed for later endpoint scanning,
1099*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 * and the tree must not be freed before that.
1100*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	 */
1101*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ures = usb_get_dev_data(uc->dip, &uc->cdata, USB_PARSE_LVL_ALL, 0);
1102*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ures != USB_SUCCESS) {
1103*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("usb_get_dev_data failed, error code: %d\n", ures);
1104*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ASSERT(uc->cdata == NULL);
1105*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
1106*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1107*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1108*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ures = usb_reset_device(uc->dip, USB_RESET_LVL_DEFAULT);
1109*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ures != USB_SUCCESS) {
1110*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("usb_reset_device failed, error code: %d\n", ures);
1111*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
1112*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1113*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1114*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->connected = B_TRUE;
1115*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1116*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ures = usb_register_hotplug_cbs(dip, zyd_usb_disconnect,
1117*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    zyd_usb_reconnect);
1118*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (ures != USB_SUCCESS) {
1119*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("usb_register_hotplug_cbs failed, error code: %d\n",
1120*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    ures);
1121*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		goto fail;
1122*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1123*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1124*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_SUCCESS);
1125*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China fail:
1126*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_client_detach(uc->dip, uc->cdata);
1127*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->cdata = NULL;
1128*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (ZYD_FAILURE);
1129*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1130*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1131*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1132*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Deinitialize USB device communication.
1133*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1134*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China void
zyd_usb_deinit(struct zyd_softc * sc)1135*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_deinit(struct zyd_softc *sc)
1136*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1137*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc = &sc->usb;
1138*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1139*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_unregister_hotplug_cbs(sc->dip);
1140*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1141*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_client_detach(uc->dip, uc->cdata);
1142*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->cdata = NULL;
1143*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->connected = B_FALSE;
1144*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1145*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1146*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China /*
1147*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  * Device connected
1148*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China  */
1149*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_usb_reconnect(dev_info_t * dip)1150*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_reconnect(dev_info_t *dip)
1151*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1152*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc;
1153*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
1154*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1155*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(zyd_ssp, ddi_get_instance(dip));
1156*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
1157*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = &sc->usb;
1158*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(!uc->connected);
1159*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1160*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->suspended)
1161*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_RESUME | ZYD_DBG_USB,
1162*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "reconnect before resume\n"));
1163*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1164*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* check device changes after disconnect */
1165*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (usb_check_same_device(sc->dip, NULL, USB_LOG_L2, -1,
1166*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
1167*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "different device connected\n"));
1168*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1169*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1170*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1171*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
1172*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_hw_init(sc) != ZYD_SUCCESS) {
1173*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to reinit hardware\n");
1174*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
1175*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1176*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1177*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->running) {
1178*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (zyd_hw_start(sc) != ZYD_SUCCESS) {
1179*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ZYD_WARN("failed to restart hardware\n");
1180*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_serial_exit(sc);
1181*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			goto fail;
1182*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
1183*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1184*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
1185*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1186*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->connected = B_TRUE;
1187*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1188*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1189*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China fail:
1190*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	usb_client_detach(uc->dip, uc->cdata);
1191*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->cdata = NULL;
1192*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
1193*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1194*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1195*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China static int
zyd_usb_disconnect(dev_info_t * dip)1196*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_usb_disconnect(dev_info_t *dip)
1197*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1198*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_softc *sc;
1199*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc;
1200*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1201*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(zyd_ssp, ddi_get_instance(dip));
1202*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
1203*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc = &sc->usb;
1204*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1205*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!uc->connected) {
1206*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "different device disconnected\n"));
1207*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1208*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1209*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	uc->connected = B_FALSE;
1210*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1211*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->suspended) {
1212*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB, "disconnect after suspend\n"));
1213*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1214*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1215*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->ic, IEEE80211_S_INIT, -1);
1216*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1217*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
1218*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_stop(sc);
1219*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_deinit(sc);
1220*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
1221*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1222*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1223*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1224*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1225*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China int
zyd_suspend(struct zyd_softc * sc)1226*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_suspend(struct zyd_softc *sc)
1227*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1228*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc = &sc->usb;
1229*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1230*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!uc->connected) {
1231*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB | ZYD_DBG_RESUME,
1232*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "suspend after disconnect\n"));
1233*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->suspended = B_TRUE;
1234*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1235*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1236*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_RESUME, "suspend\n"));
1237*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1238*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->suspended = B_TRUE;
1239*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->ic, IEEE80211_S_INIT, -1);
1240*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1241*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
1242*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_stop(sc);
1243*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_hw_deinit(sc);
1244*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
1245*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1246*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_RESUME, "suspend complete\n"));
1247*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1248*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1249*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1250*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China int
zyd_resume(struct zyd_softc * sc)1251*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China zyd_resume(struct zyd_softc *sc)
1252*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China {
1253*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	struct zyd_usb *uc = &sc->usb;
1254*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1255*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (!uc->connected) {
1256*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_DEBUG((ZYD_DBG_USB | ZYD_DBG_RESUME,
1257*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		    "resume after disconnect\n"));
1258*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->suspended = B_FALSE;
1259*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1260*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1261*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_RESUME, "resume\n"));
1262*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1263*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	/* check device changes after disconnect */
1264*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (usb_check_same_device(sc->dip, NULL, USB_LOG_L2, -1,
1265*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	    USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
1266*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("different device connected to same port\n");
1267*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		sc->suspended = B_FALSE;
1268*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		uc->connected = B_FALSE;
1269*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1270*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1271*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1272*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	(void) zyd_serial_enter(sc, ZYD_NO_SIG);
1273*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (zyd_hw_init(sc) != ZYD_SUCCESS) {
1274*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		ZYD_WARN("failed to reinit hardware\n");
1275*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		zyd_serial_exit(sc);
1276*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1277*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1278*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	if (sc->running) {
1279*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		if (zyd_hw_start(sc) != ZYD_SUCCESS) {
1280*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			ZYD_WARN("failed to restart hardware\n");
1281*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			zyd_serial_exit(sc);
1282*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
1283*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 		}
1284*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	}
1285*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	zyd_serial_exit(sc);
1286*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1287*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	sc->suspended = B_FALSE;
1288*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 
1289*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	ZYD_DEBUG((ZYD_DBG_RESUME, "resume complete\n"));
1290*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1291*e8da18d8Spengcheng chen - Sun Microsystems - Beijing China }
1292