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 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 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 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 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 * 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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