19f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 39f758cafSpengcheng chen - Sun Microsystems - Beijing China * Use is subject to license terms. 49f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 59f758cafSpengcheng chen - Sun Microsystems - Beijing China 69f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 79f758cafSpengcheng chen - Sun Microsystems - Beijing China * Copyright (c) 2003, 2004 89f758cafSpengcheng chen - Sun Microsystems - Beijing China * Daan Vreeken <Danovitsch@Vitsch.net>. All rights reserved. 99f758cafSpengcheng chen - Sun Microsystems - Beijing China * 109f758cafSpengcheng chen - Sun Microsystems - Beijing China * Redistribution and use in source and binary forms, with or without 119f758cafSpengcheng chen - Sun Microsystems - Beijing China * modification, are permitted provided that the following conditions 129f758cafSpengcheng chen - Sun Microsystems - Beijing China * are met: 139f758cafSpengcheng chen - Sun Microsystems - Beijing China * 1. Redistributions of source code must retain the above copyright 149f758cafSpengcheng chen - Sun Microsystems - Beijing China * notice, this list of conditions and the following disclaimer. 159f758cafSpengcheng chen - Sun Microsystems - Beijing China * 2. Redistributions in binary form must reproduce the above copyright 169f758cafSpengcheng chen - Sun Microsystems - Beijing China * notice, this list of conditions and the following disclaimer in the 179f758cafSpengcheng chen - Sun Microsystems - Beijing China * documentation and/or other materials provided with the distribution. 189f758cafSpengcheng chen - Sun Microsystems - Beijing China * 3. All advertising materials mentioning features or use of this software 199f758cafSpengcheng chen - Sun Microsystems - Beijing China * must display the following acknowledgement: 209f758cafSpengcheng chen - Sun Microsystems - Beijing China * This product includes software developed by Daan Vreeken. 219f758cafSpengcheng chen - Sun Microsystems - Beijing China * 4. Neither the name of the author nor the names of any co-contributors 229f758cafSpengcheng chen - Sun Microsystems - Beijing China * may be used to endorse or promote products derived from this software 239f758cafSpengcheng chen - Sun Microsystems - Beijing China * without specific prior written permission. 249f758cafSpengcheng chen - Sun Microsystems - Beijing China * 259f758cafSpengcheng chen - Sun Microsystems - Beijing China * THIS SOFTWARE IS PROVIDED BY Daan Vreeken AND CONTRIBUTORS ``AS IS'' AND 269f758cafSpengcheng chen - Sun Microsystems - Beijing China * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 279f758cafSpengcheng chen - Sun Microsystems - Beijing China * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 289f758cafSpengcheng chen - Sun Microsystems - Beijing China * ARE DISCLAIMED. IN NO EVENT SHALL Daan Vreeken OR THE VOICES IN HIS HEAD 299f758cafSpengcheng chen - Sun Microsystems - Beijing China * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 309f758cafSpengcheng chen - Sun Microsystems - Beijing China * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 319f758cafSpengcheng chen - Sun Microsystems - Beijing China * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 329f758cafSpengcheng chen - Sun Microsystems - Beijing China * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 339f758cafSpengcheng chen - Sun Microsystems - Beijing China * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 349f758cafSpengcheng chen - Sun Microsystems - Beijing China * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 359f758cafSpengcheng chen - Sun Microsystems - Beijing China * THE POSSIBILITY OF SUCH DAMAGE. 369f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 379f758cafSpengcheng chen - Sun Microsystems - Beijing China 389f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 399f758cafSpengcheng chen - Sun Microsystems - Beijing China * Atmel AT76c503 / AT76c503a / AT76c505 / AT76c505a USB WLAN driver 409f758cafSpengcheng chen - Sun Microsystems - Beijing China * 419f758cafSpengcheng chen - Sun Microsystems - Beijing China * Originally written by Daan Vreeken <Danovitsch @ Vitsch . net> 429f758cafSpengcheng chen - Sun Microsystems - Beijing China * http://vitsch.net/bsd/atuwi 439f758cafSpengcheng chen - Sun Microsystems - Beijing China * 449f758cafSpengcheng chen - Sun Microsystems - Beijing China * Contributed to by : 459f758cafSpengcheng chen - Sun Microsystems - Beijing China * Chris Whitehouse, Alistair Phillips, Peter Pilka, Martijn van Buul, 469f758cafSpengcheng chen - Sun Microsystems - Beijing China * Suihong Liang, Arjan van Leeuwen, Stuart Walsh 479f758cafSpengcheng chen - Sun Microsystems - Beijing China * 489f758cafSpengcheng chen - Sun Microsystems - Beijing China * Ported to OpenBSD by Theo de Raadt and David Gwynne. 499f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 509f758cafSpengcheng chen - Sun Microsystems - Beijing China 519f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/strsubr.h> 529f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/strsun.h> 539f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/mac_provider.h> 549f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/mac_wifi.h> 559f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/net80211.h> 569f758cafSpengcheng chen - Sun Microsystems - Beijing China #define USBDRV_MAJOR_VER 2 579f758cafSpengcheng chen - Sun Microsystems - Beijing China #define USBDRV_MINOR_VER 0 589f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/usb/usba.h> 599f758cafSpengcheng chen - Sun Microsystems - Beijing China #include <sys/usb/usba/usba_types.h> 609f758cafSpengcheng chen - Sun Microsystems - Beijing China 619f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_rfmd.hex" 629f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_rfmd2958.hex" 639f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_rfmd2958-smc.hex" 649f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_intersil.hex" 659f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_at76c505_rfmd.hex" 669f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_at76c503_rfmd_acc.hex" 679f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "fw/atmel_at76c503_i3863.hex" 689f758cafSpengcheng chen - Sun Microsystems - Beijing China #include "atu.h" 699f758cafSpengcheng chen - Sun Microsystems - Beijing China 709f758cafSpengcheng chen - Sun Microsystems - Beijing China static void *atu_soft_state_p; 719f758cafSpengcheng chen - Sun Microsystems - Beijing China static mac_callbacks_t atu_m_callbacks; 729f758cafSpengcheng chen - Sun Microsystems - Beijing China static const struct ieee80211_rateset atu_rateset = {4, {2, 4, 11, 22}}; 739f758cafSpengcheng chen - Sun Microsystems - Beijing China 749f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 759f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_usb_request(struct atu_softc *sc, uint8_t type, 769f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t request, uint16_t value, uint16_t index, uint16_t length, 779f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t *data) 789f758cafSpengcheng chen - Sun Microsystems - Beijing China { 799f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_ctrl_setup_t req; 809f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_cb_flags_t cf; 819f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_cr_t cr; 829f758cafSpengcheng chen - Sun Microsystems - Beijing China mblk_t *mp = NULL; 839f758cafSpengcheng chen - Sun Microsystems - Beijing China int uret = USB_SUCCESS; 849f758cafSpengcheng chen - Sun Microsystems - Beijing China 859f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&req, sizeof (req)); 869f758cafSpengcheng chen - Sun Microsystems - Beijing China req.bmRequestType = type; 879f758cafSpengcheng chen - Sun Microsystems - Beijing China req.bRequest = request; 889f758cafSpengcheng chen - Sun Microsystems - Beijing China req.wValue = value; 899f758cafSpengcheng chen - Sun Microsystems - Beijing China req.wIndex = index; 909f758cafSpengcheng chen - Sun Microsystems - Beijing China req.wLength = length; 919f758cafSpengcheng chen - Sun Microsystems - Beijing China req.attrs = USB_ATTRS_NONE; 929f758cafSpengcheng chen - Sun Microsystems - Beijing China 939f758cafSpengcheng chen - Sun Microsystems - Beijing China if (type & USB_DEV_REQ_DEV_TO_HOST) { 949f758cafSpengcheng chen - Sun Microsystems - Beijing China req.attrs = USB_ATTRS_AUTOCLEARING; 959f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, 969f758cafSpengcheng chen - Sun Microsystems - Beijing China &req, &mp, &cr, &cf, 0); 979f758cafSpengcheng chen - Sun Microsystems - Beijing China if (mp == NULL) 989f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 999f758cafSpengcheng chen - Sun Microsystems - Beijing China 1009f758cafSpengcheng chen - Sun Microsystems - Beijing China if (uret == USB_SUCCESS) 1019f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(mp->b_rptr, data, length); 1029f758cafSpengcheng chen - Sun Microsystems - Beijing China } else { 1039f758cafSpengcheng chen - Sun Microsystems - Beijing China if ((mp = allocb(length, BPRI_HI)) == NULL) 1049f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ENOMEM); 1059f758cafSpengcheng chen - Sun Microsystems - Beijing China 1069f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(data, mp->b_wptr, length); 1079f758cafSpengcheng chen - Sun Microsystems - Beijing China mp->b_wptr += length; 1089f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, 1099f758cafSpengcheng chen - Sun Microsystems - Beijing China &req, &mp, &cr, &cf, 0); 1109f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1119f758cafSpengcheng chen - Sun Microsystems - Beijing China 1129f758cafSpengcheng chen - Sun Microsystems - Beijing China if (mp) 1139f758cafSpengcheng chen - Sun Microsystems - Beijing China freemsg(mp); 1149f758cafSpengcheng chen - Sun Microsystems - Beijing China 1159f758cafSpengcheng chen - Sun Microsystems - Beijing China return (uret == USB_SUCCESS ? 0 : EIO); 1169f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1179f758cafSpengcheng chen - Sun Microsystems - Beijing China 1189f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 1199f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_mib(struct atu_softc *sc, uint8_t type, uint8_t size, 1209f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t index, uint8_t *buf) 1219f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1229f758cafSpengcheng chen - Sun Microsystems - Beijing China return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x033, 1239f758cafSpengcheng chen - Sun Microsystems - Beijing China type << 8, index, size, buf); 1249f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1259f758cafSpengcheng chen - Sun Microsystems - Beijing China 1269f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 1279f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_cmd_status(struct atu_softc *sc, uint8_t cmd, uint8_t *status) 1289f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1299f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 1309f758cafSpengcheng chen - Sun Microsystems - Beijing China * all other drivers (including Windoze) request 40 bytes of status 1319f758cafSpengcheng chen - Sun Microsystems - Beijing China * and get a short-xfer of just 6 bytes. we can save 34 bytes of 1329f758cafSpengcheng chen - Sun Microsystems - Beijing China * buffer if we just request those 6 bytes in the first place :) 1339f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 1349f758cafSpengcheng chen - Sun Microsystems - Beijing China return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x22, cmd, 1359f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, 6, status); 1369f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1379f758cafSpengcheng chen - Sun Microsystems - Beijing China 1389f758cafSpengcheng chen - Sun Microsystems - Beijing China static uint8_t 1399f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_dfu_state(struct atu_softc *sc) 1409f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1419f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t state; 1429f758cafSpengcheng chen - Sun Microsystems - Beijing China 1439f758cafSpengcheng chen - Sun Microsystems - Beijing China if (atu_usb_request(sc, DFU_GETSTATE, 0, 0, 1, &state)) 1449f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DFUState_DFUError); 1459f758cafSpengcheng chen - Sun Microsystems - Beijing China return (state); 1469f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1479f758cafSpengcheng chen - Sun Microsystems - Beijing China 1489f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 1499f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_opmode(struct atu_softc *sc, uint8_t *mode) 1509f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1519f758cafSpengcheng chen - Sun Microsystems - Beijing China return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0001, 1529f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, 1, mode); 1539f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1549f758cafSpengcheng chen - Sun Microsystems - Beijing China 1559f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 1569f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_config(struct atu_softc *sc) 1579f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1589f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 1599f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_rfmd_conf rfmd_conf; 1609f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_intersil_conf intersil_conf; 1619f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 1629f758cafSpengcheng chen - Sun Microsystems - Beijing China 1639f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (sc->sc_radio) { 1649f758cafSpengcheng chen - Sun Microsystems - Beijing China case RadioRFMD: 1659f758cafSpengcheng chen - Sun Microsystems - Beijing China case RadioRFMD2958: 1669f758cafSpengcheng chen - Sun Microsystems - Beijing China case RadioRFMD2958_SMC: 1679f758cafSpengcheng chen - Sun Microsystems - Beijing China case AT76C503_RFMD_ACC: 1689f758cafSpengcheng chen - Sun Microsystems - Beijing China case AT76C505_RFMD: 1699f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0a02, 1709f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, sizeof (rfmd_conf), (uint8_t *)&rfmd_conf); 1719f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 1729f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: get RFMD config failed\n", 1739f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 1749f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 1759f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1769f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(rfmd_conf.MACAddr, ic->ic_macaddr, IEEE80211_ADDR_LEN); 1779f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 1789f758cafSpengcheng chen - Sun Microsystems - Beijing China 1799f758cafSpengcheng chen - Sun Microsystems - Beijing China case RadioIntersil: 1809f758cafSpengcheng chen - Sun Microsystems - Beijing China case AT76C503_i3863: 1819f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0902, 1829f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, sizeof (intersil_conf), (uint8_t *)&intersil_conf); 1839f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 1849f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: get Intersil config failed\n", 1859f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 1869f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 1879f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1889f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(intersil_conf.MACAddr, ic->ic_macaddr, 1899f758cafSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_ADDR_LEN); 1909f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 1919f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1929f758cafSpengcheng chen - Sun Microsystems - Beijing China 1939f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 1949f758cafSpengcheng chen - Sun Microsystems - Beijing China } 1959f758cafSpengcheng chen - Sun Microsystems - Beijing China 1969f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 1979f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_wait_completion(struct atu_softc *sc, uint8_t cmd, uint8_t *status) 1989f758cafSpengcheng chen - Sun Microsystems - Beijing China { 1999f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t statusreq[6]; 2009f758cafSpengcheng chen - Sun Microsystems - Beijing China int idle_count = 0, err; 2019f758cafSpengcheng chen - Sun Microsystems - Beijing China 2029f758cafSpengcheng chen - Sun Microsystems - Beijing China while ((err = atu_get_cmd_status(sc, cmd, statusreq)) == 0) { 2039f758cafSpengcheng chen - Sun Microsystems - Beijing China 2049f758cafSpengcheng chen - Sun Microsystems - Beijing China if ((statusreq[5] != STATUS_IN_PROGRESS) && 2059f758cafSpengcheng chen - Sun Microsystems - Beijing China (statusreq[5] != STATUS_IDLE)) { 2069f758cafSpengcheng chen - Sun Microsystems - Beijing China if (status != NULL) 2079f758cafSpengcheng chen - Sun Microsystems - Beijing China *status = statusreq[5]; 2089f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 2099f758cafSpengcheng chen - Sun Microsystems - Beijing China } else if (idle_count++ > 60) { 2109f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: command (0x%02x) timeout\n", 2119f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, cmd); 2129f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ETIME); 2139f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2149f758cafSpengcheng chen - Sun Microsystems - Beijing China 2159f758cafSpengcheng chen - Sun Microsystems - Beijing China drv_usecwait(10 * 1000); 2169f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2179f758cafSpengcheng chen - Sun Microsystems - Beijing China 2189f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 2199f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2209f758cafSpengcheng chen - Sun Microsystems - Beijing China 2219f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 2229f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_send_command(struct atu_softc *sc, uint8_t *command, int size) 2239f758cafSpengcheng chen - Sun Microsystems - Beijing China { 2249f758cafSpengcheng chen - Sun Microsystems - Beijing China return atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000, 2259f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, size, command); 2269f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2279f758cafSpengcheng chen - Sun Microsystems - Beijing China 2289f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 2299f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_send_mib(struct atu_softc *sc, uint8_t type, uint8_t size, 2309f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t index, void *data) 2319f758cafSpengcheng chen - Sun Microsystems - Beijing China { 2329f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_cmd_set_mib request; 2339f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 2349f758cafSpengcheng chen - Sun Microsystems - Beijing China 2359f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&request, sizeof (request)); 2369f758cafSpengcheng chen - Sun Microsystems - Beijing China request.AtCmd = CMD_SET_MIB; 2379f758cafSpengcheng chen - Sun Microsystems - Beijing China request.AtSize = size + 4; 2389f758cafSpengcheng chen - Sun Microsystems - Beijing China request.MIBType = type; 2399f758cafSpengcheng chen - Sun Microsystems - Beijing China request.MIBSize = size; 2409f758cafSpengcheng chen - Sun Microsystems - Beijing China request.MIBIndex = index; 2419f758cafSpengcheng chen - Sun Microsystems - Beijing China request.MIBReserved = 0; 2429f758cafSpengcheng chen - Sun Microsystems - Beijing China 2439f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 2449f758cafSpengcheng chen - Sun Microsystems - Beijing China * For 1 and 2 byte requests we assume a direct value, 2459f758cafSpengcheng chen - Sun Microsystems - Beijing China * everything bigger than 2 bytes we assume a pointer to the data 2469f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 2479f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (size) { 2489f758cafSpengcheng chen - Sun Microsystems - Beijing China case 0: 2499f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 2509f758cafSpengcheng chen - Sun Microsystems - Beijing China case 1: 2519f758cafSpengcheng chen - Sun Microsystems - Beijing China request.data[0] = (long)data & 0x000000ff; 2529f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 2539f758cafSpengcheng chen - Sun Microsystems - Beijing China case 2: 2549f758cafSpengcheng chen - Sun Microsystems - Beijing China request.data[0] = (long)data & 0x000000ff; 2559f758cafSpengcheng chen - Sun Microsystems - Beijing China request.data[1] = (long)data >> 8; 2569f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 2579f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 2589f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(data, request.data, size); 2599f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 2609f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2619f758cafSpengcheng chen - Sun Microsystems - Beijing China 2629f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000, 2639f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0000, size+8, (uint8_t *)&request); 2649f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 2659f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 2669f758cafSpengcheng chen - Sun Microsystems - Beijing China 2679f758cafSpengcheng chen - Sun Microsystems - Beijing China return (atu_wait_completion(sc, CMD_SET_MIB, NULL)); 2689f758cafSpengcheng chen - Sun Microsystems - Beijing China } 2699f758cafSpengcheng chen - Sun Microsystems - Beijing China 2709f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 2719f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_switch_radio(struct atu_softc *sc, boolean_t on) 2729f758cafSpengcheng chen - Sun Microsystems - Beijing China { 2739f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_cmd radio; 2749f758cafSpengcheng chen - Sun Microsystems - Beijing China boolean_t ostate; 2759f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 2769f758cafSpengcheng chen - Sun Microsystems - Beijing China 2779f758cafSpengcheng chen - Sun Microsystems - Beijing China /* Intersil doesn't seem to support radio switch */ 2789f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_radio == RadioIntersil) 2799f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 2809f758cafSpengcheng chen - Sun Microsystems - Beijing China 2819f758cafSpengcheng chen - Sun Microsystems - Beijing China ostate = ATU_RADIO_ON(sc) ? B_TRUE : B_FALSE; 2829f758cafSpengcheng chen - Sun Microsystems - Beijing China if (on != ostate) { 2839f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&radio, sizeof (radio)); 2849f758cafSpengcheng chen - Sun Microsystems - Beijing China radio.Cmd = on ? CMD_RADIO_ON : CMD_RADIO_OFF; 2859f758cafSpengcheng chen - Sun Microsystems - Beijing China 2869f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_command(sc, (uint8_t *)&radio, 2879f758cafSpengcheng chen - Sun Microsystems - Beijing China sizeof (radio)); 2889f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 2899f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 2909f758cafSpengcheng chen - Sun Microsystems - Beijing China 2919f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_wait_completion(sc, radio.Cmd, NULL); 2929f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 2939f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 2949f758cafSpengcheng chen - Sun Microsystems - Beijing China 2959f758cafSpengcheng chen - Sun Microsystems - Beijing China if (on) 2969f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= ATU_FLAG_RADIO_ON; 2979f758cafSpengcheng chen - Sun Microsystems - Beijing China else 2989f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~ATU_FLAG_RADIO_ON; 2999f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3009f758cafSpengcheng chen - Sun Microsystems - Beijing China 3019f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 3029f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3039f758cafSpengcheng chen - Sun Microsystems - Beijing China 3049f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 3059f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_config(struct atu_softc *sc) 3069f758cafSpengcheng chen - Sun Microsystems - Beijing China { 3079f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 3089f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211_key *k; 3099f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_cmd_card_config cmd; 3109f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t rates[4] = {0x82, 0x84, 0x8B, 0x96}; 3119f758cafSpengcheng chen - Sun Microsystems - Beijing China int err, i; 3129f758cafSpengcheng chen - Sun Microsystems - Beijing China 3139f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_mib(sc, MIB_MAC_ADDR_STA, ic->ic_macaddr); 3149f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 3159f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: setting MAC address failed\n", 3169f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 3179f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 3189f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3199f758cafSpengcheng chen - Sun Microsystems - Beijing China 3209f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&cmd, sizeof (cmd)); 3219f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.Cmd = CMD_STARTUP; 3229f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.Reserved = 0; 3239f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.Size = sizeof (cmd) - 4; 3249f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.Channel = ATU_DEF_CHAN; 3259f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.ShortRetryLimit = 7; 3269f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.RTS_Threshold = 2347; 3279f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.FragThreshold = 2346; 3289f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.PromiscuousMode = 1; 3299f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.AutoRateFallback = 1; 3309f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(rates, cmd.BasicRateSet, 4); 3319f758cafSpengcheng chen - Sun Microsystems - Beijing China 3329f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_PRIVACY) { 3339f758cafSpengcheng chen - Sun Microsystems - Beijing China k = ic->ic_nw_keys + ic->ic_def_txkey; 3349f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (k->wk_keylen) { 3359f758cafSpengcheng chen - Sun Microsystems - Beijing China case 5: 3369f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.EncryptionType = ATU_ENC_WEP40; 3379f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 3389f758cafSpengcheng chen - Sun Microsystems - Beijing China case 13: 3399f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.EncryptionType = ATU_ENC_WEP104; 3409f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 3419f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 3429f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: key invalid (%d bytes)\n", 3439f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, k->wk_keylen); 3449f758cafSpengcheng chen - Sun Microsystems - Beijing China goto nowep; 3459f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3469f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.PrivacyInvoked = 1; 3479f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.ExcludeUnencrypted = 1; 3489f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.WEP_DefaultKeyID = ic->ic_def_txkey; 3499f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < IEEE80211_WEP_NKID; i++) { 3509f758cafSpengcheng chen - Sun Microsystems - Beijing China k = ic->ic_nw_keys + i; 3519f758cafSpengcheng chen - Sun Microsystems - Beijing China if (k->wk_keylen == 0) 3529f758cafSpengcheng chen - Sun Microsystems - Beijing China continue; 3539f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(k->wk_key, cmd.WEP_DefaultKey + i, k->wk_keylen); 3549f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3559f758cafSpengcheng chen - Sun Microsystems - Beijing China } else { 3569f758cafSpengcheng chen - Sun Microsystems - Beijing China nowep: 3579f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.EncryptionType = ATU_ENC_NONE; 3589f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3599f758cafSpengcheng chen - Sun Microsystems - Beijing China 3609f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(ic->ic_des_essid, cmd.SSID, ic->ic_des_esslen); 3619f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.SSID_Len = ic->ic_des_esslen; 3629f758cafSpengcheng chen - Sun Microsystems - Beijing China cmd.BeaconPeriod = 100; 3639f758cafSpengcheng chen - Sun Microsystems - Beijing China 3649f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_command(sc, (uint8_t *)&cmd, sizeof (cmd)); 3659f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 3669f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 3679f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_wait_completion(sc, CMD_STARTUP, NULL); 3689f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 3699f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 3709f758cafSpengcheng chen - Sun Microsystems - Beijing China 3719f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_switch_radio(sc, B_TRUE); 3729f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 3739f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 3749f758cafSpengcheng chen - Sun Microsystems - Beijing China 3759f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_mib(sc, MIB_MAC_MGMT_POWER_MODE, 3769f758cafSpengcheng chen - Sun Microsystems - Beijing China (void *)ATU_POWER_ACTIVE); 3779f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 3789f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 3799f758cafSpengcheng chen - Sun Microsystems - Beijing China 3809f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 3819f758cafSpengcheng chen - Sun Microsystems - Beijing China } 3829f758cafSpengcheng chen - Sun Microsystems - Beijing China 3839f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 3849f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_start_scan(struct atu_softc *sc) 3859f758cafSpengcheng chen - Sun Microsystems - Beijing China { 3869f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 3879f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_cmd_do_scan scan; 3889f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 3899f758cafSpengcheng chen - Sun Microsystems - Beijing China 3909f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!ATU_RUNNING(sc)) 3919f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 3929f758cafSpengcheng chen - Sun Microsystems - Beijing China 3939f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&scan, sizeof (scan)); 3949f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.Cmd = CMD_START_SCAN; 3959f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.Reserved = 0; 3969f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.Size = sizeof (scan) - 4; 3979f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) memset(scan.BSSID, 0xff, sizeof (scan.BSSID)); 3989f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(ic->ic_des_essid, scan.SSID, ic->ic_des_esslen); 3999f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.SSID_Len = ic->ic_des_esslen; 4009f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.ScanType = ATU_SCAN_ACTIVE; 4019f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.Channel = ieee80211_chan2ieee(ic, ic->ic_curchan); 4029f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.ProbeDelay = 0; 4039f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.MinChannelTime = 20; 4049f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.MaxChannelTime = 40; 4059f758cafSpengcheng chen - Sun Microsystems - Beijing China scan.InternationalScan = 0; 4069f758cafSpengcheng chen - Sun Microsystems - Beijing China 4079f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_command(sc, (uint8_t *)&scan, sizeof (scan)); 4089f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 4099f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: SCAN command failed\n", 4109f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 4119f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 4129f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4139f758cafSpengcheng chen - Sun Microsystems - Beijing China 4149f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_wait_completion(sc, CMD_START_SCAN, NULL); 4159f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 4169f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: SCAN completion failed\n", 4179f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 4189f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 4199f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4209f758cafSpengcheng chen - Sun Microsystems - Beijing China 4219f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 4229f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4239f758cafSpengcheng chen - Sun Microsystems - Beijing China 4249f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 4259f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_join(struct atu_softc *sc, struct ieee80211_node *node) 4269f758cafSpengcheng chen - Sun Microsystems - Beijing China { 4279f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_cmd_join join; 4289f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t status; 4299f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 4309f758cafSpengcheng chen - Sun Microsystems - Beijing China 4319f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(&join, sizeof (join)); 4329f758cafSpengcheng chen - Sun Microsystems - Beijing China join.Cmd = CMD_JOIN; 4339f758cafSpengcheng chen - Sun Microsystems - Beijing China join.Reserved = 0x00; 4349f758cafSpengcheng chen - Sun Microsystems - Beijing China join.Size = sizeof (join) - 4; 4359f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(node->in_bssid, join.bssid, IEEE80211_ADDR_LEN); 4369f758cafSpengcheng chen - Sun Microsystems - Beijing China bcopy(node->in_essid, join.essid, node->in_esslen); 4379f758cafSpengcheng chen - Sun Microsystems - Beijing China join.essid_size = node->in_esslen; 4389f758cafSpengcheng chen - Sun Microsystems - Beijing China 4399f758cafSpengcheng chen - Sun Microsystems - Beijing China if (node->in_capinfo & IEEE80211_CAPINFO_IBSS) 4409f758cafSpengcheng chen - Sun Microsystems - Beijing China join.bss_type = ATU_MODE_IBSS; 4419f758cafSpengcheng chen - Sun Microsystems - Beijing China else 4429f758cafSpengcheng chen - Sun Microsystems - Beijing China join.bss_type = ATU_MODE_STA; 4439f758cafSpengcheng chen - Sun Microsystems - Beijing China 4449f758cafSpengcheng chen - Sun Microsystems - Beijing China join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->in_chan); 4459f758cafSpengcheng chen - Sun Microsystems - Beijing China join.timeout = ATU_JOIN_TIMEOUT; 4469f758cafSpengcheng chen - Sun Microsystems - Beijing China join.reserved = 0x00; 4479f758cafSpengcheng chen - Sun Microsystems - Beijing China 4489f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_send_command(sc, (uint8_t *)&join, sizeof (join)); 4499f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 4509f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: JOIN command failed\n", 4519f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 4529f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 4539f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4549f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_wait_completion(sc, CMD_JOIN, &status); 4559f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 4569f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 4579f758cafSpengcheng chen - Sun Microsystems - Beijing China 4589f758cafSpengcheng chen - Sun Microsystems - Beijing China if (status != STATUS_COMPLETE) { 4599f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: incorrect JOIN state (0x%02x)\n", 4609f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, status); 4619f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 4629f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4639f758cafSpengcheng chen - Sun Microsystems - Beijing China 4649f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 4659f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4669f758cafSpengcheng chen - Sun Microsystems - Beijing China 4679f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 4689f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 4699f758cafSpengcheng chen - Sun Microsystems - Beijing China { 4709f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)ic; 4719f758cafSpengcheng chen - Sun Microsystems - Beijing China enum ieee80211_state ostate = ic->ic_state; 4729f758cafSpengcheng chen - Sun Microsystems - Beijing China int err = 0; 4739f758cafSpengcheng chen - Sun Microsystems - Beijing China 4749f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 4759f758cafSpengcheng chen - Sun Microsystems - Beijing China 4769f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 4779f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 4789f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 4799f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 4809f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 4819f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4829f758cafSpengcheng chen - Sun Microsystems - Beijing China ostate = ic->ic_state; 4839f758cafSpengcheng chen - Sun Microsystems - Beijing China 4849f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (nstate) { 4859f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_SCAN: 4869f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (ostate) { 4879f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_SCAN: 4889f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_AUTH: 4899f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_ASSOC: 4909f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_RUN: 4919f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 4929f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_newstate(ic, nstate, arg); 4939f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 4949f758cafSpengcheng chen - Sun Microsystems - Beijing China if ((err = atu_start_scan(sc)) != 0) { 4959f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 4969f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_cancel_scan(ic); 4979f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 4989f758cafSpengcheng chen - Sun Microsystems - Beijing China } 4999f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = timeout( 5009f758cafSpengcheng chen - Sun Microsystems - Beijing China (void (*) (void*))ieee80211_next_scan, 5019f758cafSpengcheng chen - Sun Microsystems - Beijing China (void *)&sc->sc_ic, 0); 5029f758cafSpengcheng chen - Sun Microsystems - Beijing China 5039f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 5049f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 5059f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 5069f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 5079f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5089f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 5099f758cafSpengcheng chen - Sun Microsystems - Beijing China 5109f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_AUTH: 5119f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (ostate) { 5129f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_INIT: 5139f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_SCAN: 5149f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_join(sc, ic->ic_bss); 5159f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 5169f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 5179f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 5189f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5199f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 5209f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 5219f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 5229f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5239f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 5249f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 5259f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5269f758cafSpengcheng chen - Sun Microsystems - Beijing China 5279f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 5289f758cafSpengcheng chen - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg); 5299f758cafSpengcheng chen - Sun Microsystems - Beijing China 5309f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 5319f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5329f758cafSpengcheng chen - Sun Microsystems - Beijing China 5339f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 5349f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_open_pipes(struct atu_softc *sc) 5359f758cafSpengcheng chen - Sun Microsystems - Beijing China { 5369f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_ep_data_t *ep; 5379f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_policy_t policy = {0}; 5389f758cafSpengcheng chen - Sun Microsystems - Beijing China int uret; 5399f758cafSpengcheng chen - Sun Microsystems - Beijing China 5409f758cafSpengcheng chen - Sun Microsystems - Beijing China ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0, 5419f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 5429f758cafSpengcheng chen - Sun Microsystems - Beijing China policy.pp_max_async_reqs = ATU_TX_LIST_CNT; 5439f758cafSpengcheng chen - Sun Microsystems - Beijing China 5449f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy, 5459f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_FLAGS_SLEEP, &sc->sc_tx_pipe); 5469f758cafSpengcheng chen - Sun Microsystems - Beijing China if (uret != USB_SUCCESS) 5479f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 5489f758cafSpengcheng chen - Sun Microsystems - Beijing China 5499f758cafSpengcheng chen - Sun Microsystems - Beijing China ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0, 5509f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_EP_ATTR_BULK, USB_EP_DIR_IN); 5519f758cafSpengcheng chen - Sun Microsystems - Beijing China policy.pp_max_async_reqs = ATU_RX_LIST_CNT + 32; 5529f758cafSpengcheng chen - Sun Microsystems - Beijing China 5539f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy, 5549f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_FLAGS_SLEEP, &sc->sc_rx_pipe); 5559f758cafSpengcheng chen - Sun Microsystems - Beijing China if (uret != USB_SUCCESS) 5569f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 5579f758cafSpengcheng chen - Sun Microsystems - Beijing China 5589f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 5599f758cafSpengcheng chen - Sun Microsystems - Beijing China fail: 5609f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_rx_pipe != NULL) { 5619f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe, 5629f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_FLAGS_SLEEP, NULL, 0); 5639f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_rx_pipe = NULL; 5649f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5659f758cafSpengcheng chen - Sun Microsystems - Beijing China 5669f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_tx_pipe != NULL) { 5679f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe, 5689f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_FLAGS_SLEEP, NULL, 0); 5699f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_pipe = NULL; 5709f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5719f758cafSpengcheng chen - Sun Microsystems - Beijing China 5729f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 5739f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5749f758cafSpengcheng chen - Sun Microsystems - Beijing China 5759f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 5769f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_close_pipes(struct atu_softc *sc) 5779f758cafSpengcheng chen - Sun Microsystems - Beijing China { 5789f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_flags_t flags = USB_FLAGS_SLEEP; 5799f758cafSpengcheng chen - Sun Microsystems - Beijing China 5809f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_rx_pipe != NULL) { 5819f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_reset(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0); 5829f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0); 5839f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_rx_pipe = NULL; 5849f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5859f758cafSpengcheng chen - Sun Microsystems - Beijing China 5869f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_tx_pipe != NULL) { 5879f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_reset(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0); 5889f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0); 5899f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_pipe = NULL; 5909f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5919f758cafSpengcheng chen - Sun Microsystems - Beijing China } 5929f758cafSpengcheng chen - Sun Microsystems - Beijing China 5939f758cafSpengcheng chen - Sun Microsystems - Beijing China static int atu_rx_trigger(struct atu_softc *sc); 5949f758cafSpengcheng chen - Sun Microsystems - Beijing China 5959f758cafSpengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 5969f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 5979f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 5989f758cafSpengcheng chen - Sun Microsystems - Beijing China { 5999f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private; 6009f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 6019f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211_node *ni; 6029f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_rx_hdr *h; 6039f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211_frame *wh; 6049f758cafSpengcheng chen - Sun Microsystems - Beijing China mblk_t *mp = req->bulk_data; 6059f758cafSpengcheng chen - Sun Microsystems - Beijing China int len, pktlen; 6069f758cafSpengcheng chen - Sun Microsystems - Beijing China 6079f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_data = NULL; 6089f758cafSpengcheng chen - Sun Microsystems - Beijing China if (req->bulk_completion_reason != USB_CR_OK) { 6099f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_rx_err++; 6109f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 6119f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6129f758cafSpengcheng chen - Sun Microsystems - Beijing China 6139f758cafSpengcheng chen - Sun Microsystems - Beijing China len = msgdsize(mp); 6149f758cafSpengcheng chen - Sun Microsystems - Beijing China if (len < ATU_RX_HDRLEN + ATU_MIN_FRAMELEN) { 6159f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_CONT, "%s: fragment (%d bytes)\n", 6169f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, len); 6179f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_rx_err++; 6189f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 6199f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6209f758cafSpengcheng chen - Sun Microsystems - Beijing China 6219f758cafSpengcheng chen - Sun Microsystems - Beijing China h = (struct atu_rx_hdr *)mp->b_rptr; 6229f758cafSpengcheng chen - Sun Microsystems - Beijing China pktlen = h->length - 4; 6239f758cafSpengcheng chen - Sun Microsystems - Beijing China if (pktlen + ATU_RX_HDRLEN + 4 != len) { 6249f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_CONT, "%s: jumbo (%d bytes -> %d bytes)\n", 6259f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, len, pktlen); 6269f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_rx_err++; 6279f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 6289f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6299f758cafSpengcheng chen - Sun Microsystems - Beijing China 6309f758cafSpengcheng chen - Sun Microsystems - Beijing China mp->b_rptr += ATU_RX_HDRLEN; 6319f758cafSpengcheng chen - Sun Microsystems - Beijing China mp->b_wptr = mp->b_rptr + pktlen; 6329f758cafSpengcheng chen - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)mp->b_rptr; 6339f758cafSpengcheng chen - Sun Microsystems - Beijing China 6349f758cafSpengcheng chen - Sun Microsystems - Beijing China if (wh->i_fc[1] & IEEE80211_FC1_WEP) 6359f758cafSpengcheng chen - Sun Microsystems - Beijing China wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 6369f758cafSpengcheng chen - Sun Microsystems - Beijing China 6379f758cafSpengcheng chen - Sun Microsystems - Beijing China ni = ieee80211_find_rxnode(ic, wh); 6389f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) ieee80211_input(ic, mp, ni, h->rssi, h->rx_time); 6399f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_free_node(ni); 6409f758cafSpengcheng chen - Sun Microsystems - Beijing China done: 6419f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_free_bulk_req(req); 6429f758cafSpengcheng chen - Sun Microsystems - Beijing China 6439f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxlock); 6449f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->rx_queued--; 6459f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxlock); 6469f758cafSpengcheng chen - Sun Microsystems - Beijing China 6479f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ATU_RUNNING(sc)) 6489f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_rx_trigger(sc); 6499f758cafSpengcheng chen - Sun Microsystems - Beijing China return; 6509f758cafSpengcheng chen - Sun Microsystems - Beijing China fail: 6519f758cafSpengcheng chen - Sun Microsystems - Beijing China freemsg(mp); 6529f758cafSpengcheng chen - Sun Microsystems - Beijing China goto done; 6539f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6549f758cafSpengcheng chen - Sun Microsystems - Beijing China 6559f758cafSpengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 6569f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 6579f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 6589f758cafSpengcheng chen - Sun Microsystems - Beijing China { 6599f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private; 6609f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 6619f758cafSpengcheng chen - Sun Microsystems - Beijing China 6629f758cafSpengcheng chen - Sun Microsystems - Beijing China if (req->bulk_completion_reason != USB_CR_OK) 6639f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_stats.is_tx_failed++; 6649f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_free_bulk_req(req); 6659f758cafSpengcheng chen - Sun Microsystems - Beijing China 6669f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 6679f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->tx_queued--; 6689f758cafSpengcheng chen - Sun Microsystems - Beijing China 6699f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_need_sched) { 6709f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_need_sched = 0; 6719f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_tx_update(ic->ic_mach); 6729f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6739f758cafSpengcheng chen - Sun Microsystems - Beijing China 6749f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 6759f758cafSpengcheng chen - Sun Microsystems - Beijing China } 6769f758cafSpengcheng chen - Sun Microsystems - Beijing China 6779f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 6789f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_rx_trigger(struct atu_softc *sc) 6799f758cafSpengcheng chen - Sun Microsystems - Beijing China { 6809f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_bulk_req_t *req; 6819f758cafSpengcheng chen - Sun Microsystems - Beijing China int uret; 6829f758cafSpengcheng chen - Sun Microsystems - Beijing China 6839f758cafSpengcheng chen - Sun Microsystems - Beijing China req = usb_alloc_bulk_req(sc->sc_dip, ATU_RX_BUFSZ, USB_FLAGS_SLEEP); 6849f758cafSpengcheng chen - Sun Microsystems - Beijing China if (req == NULL) 6859f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ENOMEM); 6869f758cafSpengcheng chen - Sun Microsystems - Beijing China 6879f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_len = ATU_RX_BUFSZ; 6889f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_client_private = (usb_opaque_t)sc; 6899f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_timeout = 0; 6909f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 6919f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_cb = atu_rxeof; 6929f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_exc_cb = atu_rxeof; 6939f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_completion_reason = 0; 6949f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_cb_flags = 0; 6959f758cafSpengcheng chen - Sun Microsystems - Beijing China 6969f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_bulk_xfer(sc->sc_rx_pipe, req, 0); 6979f758cafSpengcheng chen - Sun Microsystems - Beijing China if (uret != USB_SUCCESS) { 6989f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_free_bulk_req(req); 6999f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 7009f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7019f758cafSpengcheng chen - Sun Microsystems - Beijing China 7029f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxlock); 7039f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->rx_queued++; 7049f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxlock); 7059f758cafSpengcheng chen - Sun Microsystems - Beijing China 7069f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 7079f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7089f758cafSpengcheng chen - Sun Microsystems - Beijing China 7099f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 7109f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_tx_trigger(struct atu_softc *sc, mblk_t *mp) 7119f758cafSpengcheng chen - Sun Microsystems - Beijing China { 7129f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_bulk_req_t *req; 7139f758cafSpengcheng chen - Sun Microsystems - Beijing China int uret; 7149f758cafSpengcheng chen - Sun Microsystems - Beijing China 7159f758cafSpengcheng chen - Sun Microsystems - Beijing China req = usb_alloc_bulk_req(sc->sc_dip, 0, USB_FLAGS_SLEEP); 7169f758cafSpengcheng chen - Sun Microsystems - Beijing China if (req == NULL) 7179f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 7189f758cafSpengcheng chen - Sun Microsystems - Beijing China 7199f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_len = msgdsize(mp); 7209f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_data = mp; 7219f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_client_private = (usb_opaque_t)sc; 7229f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_timeout = 10; 7239f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 7249f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_cb = atu_txeof; 7259f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_exc_cb = atu_txeof; 7269f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_completion_reason = 0; 7279f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_cb_flags = 0; 7289f758cafSpengcheng chen - Sun Microsystems - Beijing China 7299f758cafSpengcheng chen - Sun Microsystems - Beijing China uret = usb_pipe_bulk_xfer(sc->sc_tx_pipe, req, 0); 7309f758cafSpengcheng chen - Sun Microsystems - Beijing China if (uret != USB_SUCCESS) { 7319f758cafSpengcheng chen - Sun Microsystems - Beijing China req->bulk_data = NULL; 7329f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_free_bulk_req(req); 7339f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 7349f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7359f758cafSpengcheng chen - Sun Microsystems - Beijing China 7369f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 7379f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->tx_queued++; 7389f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 7399f758cafSpengcheng chen - Sun Microsystems - Beijing China 7409f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 7419f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7429f758cafSpengcheng chen - Sun Microsystems - Beijing China 7439f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 7449f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_init_rx_queue(struct atu_softc *sc) 7459f758cafSpengcheng chen - Sun Microsystems - Beijing China { 7469f758cafSpengcheng chen - Sun Microsystems - Beijing China int err, i; 7479f758cafSpengcheng chen - Sun Microsystems - Beijing China 7489f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxlock); 7499f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->rx_queued = 0; 7509f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxlock); 7519f758cafSpengcheng chen - Sun Microsystems - Beijing China 7529f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < ATU_RX_LIST_CNT; i++) { 7539f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_rx_trigger(sc); 7549f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 7559f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 7569f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7579f758cafSpengcheng chen - Sun Microsystems - Beijing China 7589f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 7599f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7609f758cafSpengcheng chen - Sun Microsystems - Beijing China 7619f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 7629f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_init_tx_queue(struct atu_softc *sc) 7639f758cafSpengcheng chen - Sun Microsystems - Beijing China { 7649f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 7659f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->tx_queued = 0; 7669f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 7679f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7689f758cafSpengcheng chen - Sun Microsystems - Beijing China 7699f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 7709f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 7719f758cafSpengcheng chen - Sun Microsystems - Beijing China { 7729f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)ic; 7739f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211_node *ni = NULL; 7749f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_tx_hdr *desc; 7759f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211_frame *wh; 7769f758cafSpengcheng chen - Sun Microsystems - Beijing China mblk_t *m; 7779f758cafSpengcheng chen - Sun Microsystems - Beijing China int pktlen = msgdsize(mp), err = 0; 7789f758cafSpengcheng chen - Sun Microsystems - Beijing China 7799f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 7809f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->tx_queued > ATU_TX_LIST_CNT) { 7819f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_nobuf++; 7829f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 7839f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ENOMEM; 7849f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 7859f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7869f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 7879f758cafSpengcheng chen - Sun Microsystems - Beijing China 7889f758cafSpengcheng chen - Sun Microsystems - Beijing China m = allocb(ATU_TX_BUFSZ, BPRI_MED); 7899f758cafSpengcheng chen - Sun Microsystems - Beijing China if (m == NULL) { 7909f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_nobuf++; 7919f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ENOMEM; 7929f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 7939f758cafSpengcheng chen - Sun Microsystems - Beijing China } 7949f758cafSpengcheng chen - Sun Microsystems - Beijing China /* reserve tx header space */ 7959f758cafSpengcheng chen - Sun Microsystems - Beijing China m->b_rptr += ATU_TX_HDRLEN; 7969f758cafSpengcheng chen - Sun Microsystems - Beijing China m->b_wptr += ATU_TX_HDRLEN; 7979f758cafSpengcheng chen - Sun Microsystems - Beijing China 7989f758cafSpengcheng chen - Sun Microsystems - Beijing China /* copy and (implicitly) free old data */ 7999f758cafSpengcheng chen - Sun Microsystems - Beijing China mcopymsg(mp, m->b_wptr); 8009f758cafSpengcheng chen - Sun Microsystems - Beijing China m->b_wptr += pktlen; 8019f758cafSpengcheng chen - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)m->b_rptr; 8029f758cafSpengcheng chen - Sun Microsystems - Beijing China 8039f758cafSpengcheng chen - Sun Microsystems - Beijing China ni = ieee80211_find_txnode(ic, wh->i_addr1); 8049f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ni == NULL) { 8059f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_stats.is_tx_failed++; 8069f758cafSpengcheng chen - Sun Microsystems - Beijing China freemsg(m); 8079f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ENXIO; 8089f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 8099f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8109f758cafSpengcheng chen - Sun Microsystems - Beijing China 8119f758cafSpengcheng chen - Sun Microsystems - Beijing China if (type == IEEE80211_FC0_TYPE_DATA) 8129f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) ieee80211_encap(ic, m, ni); 8139f758cafSpengcheng chen - Sun Microsystems - Beijing China 8149f758cafSpengcheng chen - Sun Microsystems - Beijing China /* full WEP in device, prune WEP fields (IV, KID) */ 8159f758cafSpengcheng chen - Sun Microsystems - Beijing China if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 8169f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) memmove(m->b_rptr + IEEE80211_WEP_IVLEN 8179f758cafSpengcheng chen - Sun Microsystems - Beijing China + IEEE80211_WEP_KIDLEN, m->b_rptr, 8189f758cafSpengcheng chen - Sun Microsystems - Beijing China sizeof (struct ieee80211_frame)); 8199f758cafSpengcheng chen - Sun Microsystems - Beijing China m->b_rptr += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN; 8209f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8219f758cafSpengcheng chen - Sun Microsystems - Beijing China pktlen = msgdsize(m); 8229f758cafSpengcheng chen - Sun Microsystems - Beijing China m->b_rptr -= ATU_TX_HDRLEN; 8239f758cafSpengcheng chen - Sun Microsystems - Beijing China 8249f758cafSpengcheng chen - Sun Microsystems - Beijing China /* setup tx header */ 8259f758cafSpengcheng chen - Sun Microsystems - Beijing China desc = (struct atu_tx_hdr *)m->b_rptr; 8269f758cafSpengcheng chen - Sun Microsystems - Beijing China bzero(desc, ATU_TX_HDRLEN); 8279f758cafSpengcheng chen - Sun Microsystems - Beijing China desc->length = (uint16_t)pktlen; 8289f758cafSpengcheng chen - Sun Microsystems - Beijing China desc->tx_rate = ATU_DEF_TX_RATE; 8299f758cafSpengcheng chen - Sun Microsystems - Beijing China 8309f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_tx_trigger(sc, m); 8319f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!err) { 8329f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_stats.is_tx_frags++; 8339f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_stats.is_tx_bytes += pktlen; 8349f758cafSpengcheng chen - Sun Microsystems - Beijing China } else { 8359f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_stats.is_tx_failed++; 8369f758cafSpengcheng chen - Sun Microsystems - Beijing China freemsg(m); 8379f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8389f758cafSpengcheng chen - Sun Microsystems - Beijing China fail: 8399f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ni != NULL) 8409f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_free_node(ni); 8419f758cafSpengcheng chen - Sun Microsystems - Beijing China 8429f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 8439f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8449f758cafSpengcheng chen - Sun Microsystems - Beijing China 8459f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 8469f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_stop(struct atu_softc *sc) 8479f758cafSpengcheng chen - Sun Microsystems - Beijing China { 8489f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~ATU_FLAG_RUNNING; 8499f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_close_pipes(sc); 8509f758cafSpengcheng chen - Sun Microsystems - Beijing China 8519f758cafSpengcheng chen - Sun Microsystems - Beijing China return (atu_switch_radio(sc, B_FALSE)); 8529f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8539f758cafSpengcheng chen - Sun Microsystems - Beijing China 8549f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 8559f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_init(struct atu_softc *sc) 8569f758cafSpengcheng chen - Sun Microsystems - Beijing China { 8579f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 8589f758cafSpengcheng chen - Sun Microsystems - Beijing China 8599f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_stop(sc); 8609f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 8619f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 8629f758cafSpengcheng chen - Sun Microsystems - Beijing China 8639f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_open_pipes(sc); 8649f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 8659f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 8669f758cafSpengcheng chen - Sun Microsystems - Beijing China 8679f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_config(sc); 8689f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 8699f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: startup config failed\n", 8709f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 8719f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 8729f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8739f758cafSpengcheng chen - Sun Microsystems - Beijing China 8749f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_init_tx_queue(sc); 8759f758cafSpengcheng chen - Sun Microsystems - Beijing China 8769f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_init_rx_queue(sc); 8779f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 8789f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: rx queue init failed\n", sc->sc_name); 8799f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail; 8809f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8819f758cafSpengcheng chen - Sun Microsystems - Beijing China 8829f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= ATU_FLAG_RUNNING; 8839f758cafSpengcheng chen - Sun Microsystems - Beijing China 8849f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 8859f758cafSpengcheng chen - Sun Microsystems - Beijing China fail: 8869f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_stop(sc); 8879f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 8889f758cafSpengcheng chen - Sun Microsystems - Beijing China } 8899f758cafSpengcheng chen - Sun Microsystems - Beijing China 8909f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 8919f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_watchdog(void *arg) 8929f758cafSpengcheng chen - Sun Microsystems - Beijing China { 8939f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = arg; 8949f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 8959f758cafSpengcheng chen - Sun Microsystems - Beijing China 8969f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 8979f758cafSpengcheng chen - Sun Microsystems - Beijing China 8989f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 8999f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!ATU_RUNNING(sc)) { 9009f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 9019f758cafSpengcheng chen - Sun Microsystems - Beijing China return; 9029f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9039f758cafSpengcheng chen - Sun Microsystems - Beijing China 9049f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 9059f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (ic->ic_state) { 9069f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_AUTH: 9079f758cafSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_ASSOC: 9089f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_bss->in_fails > 0) 9099f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 9109f758cafSpengcheng chen - Sun Microsystems - Beijing China else 9119f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_watchdog(ic); 9129f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 9139f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9149f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9159f758cafSpengcheng chen - Sun Microsystems - Beijing China 9169f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 9179f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_dfu_stage1(void *arg) 9189f758cafSpengcheng chen - Sun Microsystems - Beijing China { 9199f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = arg; 9209f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t state, *ptr = NULL, status[6]; 9219f758cafSpengcheng chen - Sun Microsystems - Beijing China int block_size, bytes_left = 0, block = 0, err, i, count = 0; 9229f758cafSpengcheng chen - Sun Microsystems - Beijing China 9239f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 9249f758cafSpengcheng chen - Sun Microsystems - Beijing China * Uploading firmware is done with the DFU (Device Firmware Upgrade) 9259f758cafSpengcheng chen - Sun Microsystems - Beijing China * interface. See "Universal Serial Bus - Device Class Specification 9269f758cafSpengcheng chen - Sun Microsystems - Beijing China * for Device Firmware Upgrade" pdf for details of the protocol. 9279f758cafSpengcheng chen - Sun Microsystems - Beijing China * Maybe this could be moved to a separate 'firmware driver' once more 9289f758cafSpengcheng chen - Sun Microsystems - Beijing China * device drivers need it... For now we'll just do it here. 9299f758cafSpengcheng chen - Sun Microsystems - Beijing China * 9309f758cafSpengcheng chen - Sun Microsystems - Beijing China * Just for your information, the Atmel's DFU descriptor looks like 9319f758cafSpengcheng chen - Sun Microsystems - Beijing China * this: 9329f758cafSpengcheng chen - Sun Microsystems - Beijing China * 9339f758cafSpengcheng chen - Sun Microsystems - Beijing China * 07 size 9349f758cafSpengcheng chen - Sun Microsystems - Beijing China * 21 type 9359f758cafSpengcheng chen - Sun Microsystems - Beijing China * 01 capabilities : only firmware download, *need* reset 9369f758cafSpengcheng chen - Sun Microsystems - Beijing China * after download 9379f758cafSpengcheng chen - Sun Microsystems - Beijing China * 13 05 detach timeout : max 1299ms between DFU_DETACH and 9389f758cafSpengcheng chen - Sun Microsystems - Beijing China * reset 9399f758cafSpengcheng chen - Sun Microsystems - Beijing China * 00 04 max bytes of firmware per transaction : 1024 9409f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 9419f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++) 9429f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_radio == atu_fw_table[i].atur_type) { 9439f758cafSpengcheng chen - Sun Microsystems - Beijing China ptr = atu_fw_table[i].atur_int; 9449f758cafSpengcheng chen - Sun Microsystems - Beijing China bytes_left = atu_fw_table[i].atur_int_size; 9459f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9469f758cafSpengcheng chen - Sun Microsystems - Beijing China 9479f758cafSpengcheng chen - Sun Microsystems - Beijing China state = atu_get_dfu_state(sc); 9489f758cafSpengcheng chen - Sun Microsystems - Beijing China while (block >= 0 && state > 0) { 9499f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (state) { 9509f758cafSpengcheng chen - Sun Microsystems - Beijing China case DFUState_DnLoadSync: 9519f758cafSpengcheng chen - Sun Microsystems - Beijing China /* get DFU status */ 9529f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, 9539f758cafSpengcheng chen - Sun Microsystems - Beijing China status); 9549f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 9559f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU get status failed\n", 9569f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 9579f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 9589f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9599f758cafSpengcheng chen - Sun Microsystems - Beijing China /* success means state => DnLoadIdle */ 9609f758cafSpengcheng chen - Sun Microsystems - Beijing China state = DFUState_DnLoadIdle; 9619f758cafSpengcheng chen - Sun Microsystems - Beijing China continue; 9629f758cafSpengcheng chen - Sun Microsystems - Beijing China 9639f758cafSpengcheng chen - Sun Microsystems - Beijing China case DFUState_DFUIdle: 9649f758cafSpengcheng chen - Sun Microsystems - Beijing China case DFUState_DnLoadIdle: 9659f758cafSpengcheng chen - Sun Microsystems - Beijing China if (bytes_left >= DFU_MaxBlockSize) 9669f758cafSpengcheng chen - Sun Microsystems - Beijing China block_size = DFU_MaxBlockSize; 9679f758cafSpengcheng chen - Sun Microsystems - Beijing China else 9689f758cafSpengcheng chen - Sun Microsystems - Beijing China block_size = bytes_left; 9699f758cafSpengcheng chen - Sun Microsystems - Beijing China 9709f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, DFU_DNLOAD, block++, 0, 9719f758cafSpengcheng chen - Sun Microsystems - Beijing China block_size, ptr); 9729f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 9739f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU download failed\n", 9749f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 9759f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 9769f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9779f758cafSpengcheng chen - Sun Microsystems - Beijing China 9789f758cafSpengcheng chen - Sun Microsystems - Beijing China ptr += block_size; 9799f758cafSpengcheng chen - Sun Microsystems - Beijing China bytes_left -= block_size; 9809f758cafSpengcheng chen - Sun Microsystems - Beijing China if (block_size == 0) 9819f758cafSpengcheng chen - Sun Microsystems - Beijing China block = -1; 9829f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 9839f758cafSpengcheng chen - Sun Microsystems - Beijing China 9849f758cafSpengcheng chen - Sun Microsystems - Beijing China case DFUState_DFUError: 9859f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU state error\n", sc->sc_name); 9869f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 9879f758cafSpengcheng chen - Sun Microsystems - Beijing China 9889f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 9899f758cafSpengcheng chen - Sun Microsystems - Beijing China drv_usecwait(10*1000); 9909f758cafSpengcheng chen - Sun Microsystems - Beijing China if (++count > 100) { 9919f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU timeout\n", 9929f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 9939f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ETIME); 9949f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9959f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 9969f758cafSpengcheng chen - Sun Microsystems - Beijing China } 9979f758cafSpengcheng chen - Sun Microsystems - Beijing China 9989f758cafSpengcheng chen - Sun Microsystems - Beijing China state = atu_get_dfu_state(sc); 9999f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10009f758cafSpengcheng chen - Sun Microsystems - Beijing China if (state != DFUState_ManifestSync) 10019f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU state (%d) != ManifestSync\n", 10029f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name, state); 10039f758cafSpengcheng chen - Sun Microsystems - Beijing China 10049f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, status); 10059f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 10069f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU get status failed\n", 10079f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 10089f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 10099f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10109f758cafSpengcheng chen - Sun Microsystems - Beijing China 10119f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, DFU_REMAP, 0, 0, 0, NULL); 10129f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err && !(sc->sc_quirk & ATU_QUIRK_NO_REMAP)) { 10139f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: DFU remap failed\n", sc->sc_name); 10149f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 10159f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10169f758cafSpengcheng chen - Sun Microsystems - Beijing China 10179f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 10189f758cafSpengcheng chen - Sun Microsystems - Beijing China * after a lot of trying and measuring I found out the device needs 10199f758cafSpengcheng chen - Sun Microsystems - Beijing China * about 56 miliseconds after sending the remap command before 10209f758cafSpengcheng chen - Sun Microsystems - Beijing China * it's ready to communicate again. So we'll wait just a little bit 10219f758cafSpengcheng chen - Sun Microsystems - Beijing China * longer than that to be sure... 10229f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 10239f758cafSpengcheng chen - Sun Microsystems - Beijing China drv_usecwait((56+100)*1000); 10249f758cafSpengcheng chen - Sun Microsystems - Beijing China 10259f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 10269f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10279f758cafSpengcheng chen - Sun Microsystems - Beijing China 10289f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 10299f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_dfu_stage2(void *arg) 10309f758cafSpengcheng chen - Sun Microsystems - Beijing China { 10319f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = arg; 10329f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t *ptr = NULL; 10339f758cafSpengcheng chen - Sun Microsystems - Beijing China int block_size, bytes_left = 0, block = 0, err, i; 10349f758cafSpengcheng chen - Sun Microsystems - Beijing China 10359f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++) 10369f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_radio == atu_fw_table[i].atur_type) { 10379f758cafSpengcheng chen - Sun Microsystems - Beijing China ptr = atu_fw_table[i].atur_ext; 10389f758cafSpengcheng chen - Sun Microsystems - Beijing China bytes_left = atu_fw_table[i].atur_ext_size; 10399f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10409f758cafSpengcheng chen - Sun Microsystems - Beijing China 10419f758cafSpengcheng chen - Sun Microsystems - Beijing China while (bytes_left) { 10429f758cafSpengcheng chen - Sun Microsystems - Beijing China if (bytes_left > 1024) 10439f758cafSpengcheng chen - Sun Microsystems - Beijing China block_size = 1024; 10449f758cafSpengcheng chen - Sun Microsystems - Beijing China else 10459f758cafSpengcheng chen - Sun Microsystems - Beijing China block_size = bytes_left; 10469f758cafSpengcheng chen - Sun Microsystems - Beijing China 10479f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 10489f758cafSpengcheng chen - Sun Microsystems - Beijing China 0x0802, block, block_size, ptr); 10499f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 10509f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: stage2 firmware load failed\n", 10519f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 10529f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 10539f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10549f758cafSpengcheng chen - Sun Microsystems - Beijing China 10559f758cafSpengcheng chen - Sun Microsystems - Beijing China ptr += block_size; 10569f758cafSpengcheng chen - Sun Microsystems - Beijing China block++; 10579f758cafSpengcheng chen - Sun Microsystems - Beijing China bytes_left -= block_size; 10589f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10599f758cafSpengcheng chen - Sun Microsystems - Beijing China 10609f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0802, 10619f758cafSpengcheng chen - Sun Microsystems - Beijing China block, 0, NULL); 10629f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 10639f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: zero-length block load failed\n", 10649f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 10659f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 10669f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10679f758cafSpengcheng chen - Sun Microsystems - Beijing China 10689f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 10699f758cafSpengcheng chen - Sun Microsystems - Beijing China * The SMC2662w V.4 seems to require some time to do its thing with 10709f758cafSpengcheng chen - Sun Microsystems - Beijing China * the stage2 firmware... 20 ms isn't enough, but 21 ms works 100 10719f758cafSpengcheng chen - Sun Microsystems - Beijing China * times out of 100 tries. We'll wait a bit longer just to be sure 10729f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 10739f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_quirk & ATU_QUIRK_FW_DELAY) 10749f758cafSpengcheng chen - Sun Microsystems - Beijing China drv_usecwait((21 + 100) * 1000); 10759f758cafSpengcheng chen - Sun Microsystems - Beijing China 10769f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 10779f758cafSpengcheng chen - Sun Microsystems - Beijing China } 10789f758cafSpengcheng chen - Sun Microsystems - Beijing China 10799f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 10809f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_load_microcode(struct atu_softc *sc, boolean_t attach) 10819f758cafSpengcheng chen - Sun Microsystems - Beijing China { 10829f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_dev_reset_lvl_t reset; 10839f758cafSpengcheng chen - Sun Microsystems - Beijing China uint8_t mode, chan; 10849f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 10859f758cafSpengcheng chen - Sun Microsystems - Beijing China 10869f758cafSpengcheng chen - Sun Microsystems - Beijing China reset = attach ? USB_RESET_LVL_REATTACH : USB_RESET_LVL_DEFAULT; 10879f758cafSpengcheng chen - Sun Microsystems - Beijing China 10889f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_get_opmode(sc, &mode); 10899f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!err) { 10909f758cafSpengcheng chen - Sun Microsystems - Beijing China if (mode == ATU_DEV_READY) 10919f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 10929f758cafSpengcheng chen - Sun Microsystems - Beijing China /* 10939f758cafSpengcheng chen - Sun Microsystems - Beijing China * Opmode of SMC2662 V.4 does not change after stage2 10949f758cafSpengcheng chen - Sun Microsystems - Beijing China * firmware download. If succeeded reading the channel 10959f758cafSpengcheng chen - Sun Microsystems - Beijing China * number, stage2 firmware is already running. 10969f758cafSpengcheng chen - Sun Microsystems - Beijing China */ 10979f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_radio != RadioIntersil && 10989f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_get_mib(sc, MIB_PHY_CHANNEL, &chan) == 0) 10999f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 11009f758cafSpengcheng chen - Sun Microsystems - Beijing China 11019f758cafSpengcheng chen - Sun Microsystems - Beijing China if (mode == ATU_DEV_STAGE2) 11029f758cafSpengcheng chen - Sun Microsystems - Beijing China stage2: 11039f758cafSpengcheng chen - Sun Microsystems - Beijing China return (atu_dfu_stage2(sc)); 11049f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11059f758cafSpengcheng chen - Sun Microsystems - Beijing China 11069f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_dfu_stage1(sc); 11079f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 11089f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 11099f758cafSpengcheng chen - Sun Microsystems - Beijing China 11109f758cafSpengcheng chen - Sun Microsystems - Beijing China if (usb_reset_device(sc->sc_dip, reset) != USB_SUCCESS) 11119f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EIO); 11129f758cafSpengcheng chen - Sun Microsystems - Beijing China 11139f758cafSpengcheng chen - Sun Microsystems - Beijing China if (attach) 11149f758cafSpengcheng chen - Sun Microsystems - Beijing China return (EAGAIN); 11159f758cafSpengcheng chen - Sun Microsystems - Beijing China else 11169f758cafSpengcheng chen - Sun Microsystems - Beijing China goto stage2; 11179f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11189f758cafSpengcheng chen - Sun Microsystems - Beijing China 11199f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 11209f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_disconnect(dev_info_t *dip) 11219f758cafSpengcheng chen - Sun Microsystems - Beijing China { 11229f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc; 11239f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic; 11249f758cafSpengcheng chen - Sun Microsystems - Beijing China 11259f758cafSpengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 11269f758cafSpengcheng chen - Sun Microsystems - Beijing China ic = &sc->sc_ic; 11279f758cafSpengcheng chen - Sun Microsystems - Beijing China 11289f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 11299f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 11309f758cafSpengcheng chen - Sun Microsystems - Beijing China 11319f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 11329f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 11339f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 11349f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 11359f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 11369f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 11379f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11389f758cafSpengcheng chen - Sun Microsystems - Beijing China 11399f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~(ATU_FLAG_RUNNING | ATU_FLAG_RADIO_ON); 11409f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_close_pipes(sc); 11419f758cafSpengcheng chen - Sun Microsystems - Beijing China 11429f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 11439f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 11449f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11459f758cafSpengcheng chen - Sun Microsystems - Beijing China 11469f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 11479f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_reconnect(dev_info_t *dip) 11489f758cafSpengcheng chen - Sun Microsystems - Beijing China { 11499f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc; 11509f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 11519f758cafSpengcheng chen - Sun Microsystems - Beijing China 11529f758cafSpengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 11539f758cafSpengcheng chen - Sun Microsystems - Beijing China if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1, 11549f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_CHK_BASIC, NULL) != USB_SUCCESS) 11559f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 11569f758cafSpengcheng chen - Sun Microsystems - Beijing China 11579f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 11589f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_load_microcode(sc, B_FALSE); 11599f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!err) 11609f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_init(sc); 11619f758cafSpengcheng chen - Sun Microsystems - Beijing China 11629f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 11639f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err ? DDI_FAILURE : DDI_SUCCESS); 11649f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11659f758cafSpengcheng chen - Sun Microsystems - Beijing China 11669f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 11679f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 11689f758cafSpengcheng chen - Sun Microsystems - Beijing China { 11699f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc; 11709f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic; 11719f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_register_t *macp; 11729f758cafSpengcheng chen - Sun Microsystems - Beijing China wifi_data_t wd = {0}; 11739f758cafSpengcheng chen - Sun Microsystems - Beijing China int instance, i, err; 11749f758cafSpengcheng chen - Sun Microsystems - Beijing China 11759f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (cmd) { 11769f758cafSpengcheng chen - Sun Microsystems - Beijing China case DDI_ATTACH: 11779f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 11789f758cafSpengcheng chen - Sun Microsystems - Beijing China case DDI_RESUME: 11799f758cafSpengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(atu_soft_state_p, 11809f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_get_instance(dip)); 11819f758cafSpengcheng chen - Sun Microsystems - Beijing China if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1, 11829f758cafSpengcheng chen - Sun Microsystems - Beijing China USB_CHK_BASIC, NULL) != USB_SUCCESS) 11839f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 11849f758cafSpengcheng chen - Sun Microsystems - Beijing China 11859f758cafSpengcheng chen - Sun Microsystems - Beijing China if (atu_load_microcode(sc, B_FALSE) == 0) 11869f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_init(sc); 11879f758cafSpengcheng chen - Sun Microsystems - Beijing China 11889f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 11899f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 11909f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 11919f758cafSpengcheng chen - Sun Microsystems - Beijing China } 11929f758cafSpengcheng chen - Sun Microsystems - Beijing China 11939f758cafSpengcheng chen - Sun Microsystems - Beijing China instance = ddi_get_instance(dip); 11949f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ddi_soft_state_zalloc(atu_soft_state_p, instance) != DDI_SUCCESS) 11959f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 11969f758cafSpengcheng chen - Sun Microsystems - Beijing China 11979f758cafSpengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(atu_soft_state_p, instance); 11989f758cafSpengcheng chen - Sun Microsystems - Beijing China ic = &sc->sc_ic; 11999f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_dip = dip; 12009f758cafSpengcheng chen - Sun Microsystems - Beijing China 12019f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) snprintf(sc->sc_name, sizeof (sc->sc_name), "%s%d", 12029f758cafSpengcheng chen - Sun Microsystems - Beijing China "atu", instance); 12039f758cafSpengcheng chen - Sun Microsystems - Beijing China 12049f758cafSpengcheng chen - Sun Microsystems - Beijing China err = usb_client_attach(dip, USBDRV_VERSION, 0); 12059f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != USB_SUCCESS) 12069f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail1; 12079f758cafSpengcheng chen - Sun Microsystems - Beijing China 12089f758cafSpengcheng chen - Sun Microsystems - Beijing China err = usb_get_dev_data(dip, &sc->sc_udev, USB_PARSE_LVL_ALL, 0); 12099f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != USB_SUCCESS) { 12109f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_udev = NULL; 12119f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail2; 12129f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12139f758cafSpengcheng chen - Sun Microsystems - Beijing China 12149f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 0; i < sizeof (atu_dev_table)/sizeof (atu_dev_table[0]); i++) { 12159f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_dev_type *t = &atu_dev_table[i]; 12169f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_udev->dev_descr->idVendor == t->atu_vid && 12179f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_udev->dev_descr->idProduct == t->atu_pid) { 12189f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_radio = t->atu_radio; 12199f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_quirk = t->atu_quirk; 12209f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12219f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12229f758cafSpengcheng chen - Sun Microsystems - Beijing China 12239f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_load_microcode(sc, B_TRUE); 12249f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err == EAGAIN) { 12259f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= ATU_FLAG_REATTACH; /* reattaching */ 12269f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 12279f758cafSpengcheng chen - Sun Microsystems - Beijing China } else if (err) { 12289f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail2; 12299f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12309f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~ATU_FLAG_REATTACH; 12319f758cafSpengcheng chen - Sun Microsystems - Beijing China 12329f758cafSpengcheng chen - Sun Microsystems - Beijing China /* read device config & MAC address */ 12339f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_get_config(sc); 12349f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) { 12359f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: read device config failed\n", 12369f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 12379f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail2; 12389f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12399f758cafSpengcheng chen - Sun Microsystems - Beijing China 12409f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 12419f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL); 12429f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL); 12439f758cafSpengcheng chen - Sun Microsystems - Beijing China 12449f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_phytype = IEEE80211_T_DS; 12459f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_opmode = IEEE80211_M_STA; 12469f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_WEP; 12479f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_sup_rates[IEEE80211_MODE_11B] = atu_rateset; 12489f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_maxrssi = atu_fw_table[sc->sc_radio].max_rssi; 12499f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_state = IEEE80211_S_INIT; 12509f758cafSpengcheng chen - Sun Microsystems - Beijing China for (i = 1; i <= 14; i++) { 12519f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_sup_channels[i].ich_freq = 12529f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 12539f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_sup_channels[i].ich_flags = 12549f758cafSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ | 12559f758cafSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_PASSIVE; 12569f758cafSpengcheng chen - Sun Microsystems - Beijing China } 12579f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_xmit = atu_send; 12589f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_attach(ic); 12599f758cafSpengcheng chen - Sun Microsystems - Beijing China 12609f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_newstate = ic->ic_newstate; 12619f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_newstate = atu_newstate; 12629f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_watchdog = atu_watchdog; 12639f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_media_init(ic); 12649f758cafSpengcheng chen - Sun Microsystems - Beijing China 12659f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_def_txkey = 0; 12669f758cafSpengcheng chen - Sun Microsystems - Beijing China wd.wd_opmode = ic->ic_opmode; 12679f758cafSpengcheng chen - Sun Microsystems - Beijing China wd.wd_secalloc = WIFI_SEC_NONE; 12689f758cafSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 12699f758cafSpengcheng chen - Sun Microsystems - Beijing China 12709f758cafSpengcheng chen - Sun Microsystems - Beijing China macp = mac_alloc(MAC_VERSION); 12719f758cafSpengcheng chen - Sun Microsystems - Beijing China if (macp == NULL) 12729f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail3; 12739f758cafSpengcheng chen - Sun Microsystems - Beijing China 12749f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 12759f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_driver = sc; 12769f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_dip = dip; 12779f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_src_addr = ic->ic_macaddr; 12789f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_callbacks = &atu_m_callbacks; 12799f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_min_sdu = 0; 12809f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_max_sdu = IEEE80211_MTU; 12819f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_pdata = &wd; 12829f758cafSpengcheng chen - Sun Microsystems - Beijing China macp->m_pdata_size = sizeof (wd); 12839f758cafSpengcheng chen - Sun Microsystems - Beijing China 12849f758cafSpengcheng chen - Sun Microsystems - Beijing China err = mac_register(macp, &ic->ic_mach); 12859f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_free(macp); 12869f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 12879f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail3; 12889f758cafSpengcheng chen - Sun Microsystems - Beijing China 12899f758cafSpengcheng chen - Sun Microsystems - Beijing China err = usb_register_hotplug_cbs(sc->sc_dip, atu_disconnect, 12909f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_reconnect); 12919f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != USB_SUCCESS) 12929f758cafSpengcheng chen - Sun Microsystems - Beijing China goto fail4; 12939f758cafSpengcheng chen - Sun Microsystems - Beijing China 12949f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ddi_create_minor_node(dip, sc->sc_name, S_IFCHR, 12959f758cafSpengcheng chen - Sun Microsystems - Beijing China instance + 1, DDI_NT_NET_WIFI, 0); 12969f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 12979f758cafSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "%s: minor node creation failed\n", 12989f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_name); 12999f758cafSpengcheng chen - Sun Microsystems - Beijing China 13009f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 13019f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 13029f758cafSpengcheng chen - Sun Microsystems - Beijing China 13039f758cafSpengcheng chen - Sun Microsystems - Beijing China fail4: 13049f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) mac_unregister(ic->ic_mach); 13059f758cafSpengcheng chen - Sun Microsystems - Beijing China fail3: 13069f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 13079f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxlock); 13089f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txlock); 13099f758cafSpengcheng chen - Sun Microsystems - Beijing China fail2: 13109f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_client_detach(sc->sc_dip, sc->sc_udev); 13119f758cafSpengcheng chen - Sun Microsystems - Beijing China fail1: 13129f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_soft_state_free(atu_soft_state_p, instance); 13139f758cafSpengcheng chen - Sun Microsystems - Beijing China 13149f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 13159f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13169f758cafSpengcheng chen - Sun Microsystems - Beijing China 13179f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 13189f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 13199f758cafSpengcheng chen - Sun Microsystems - Beijing China { 13209f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc; 13219f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 13229f758cafSpengcheng chen - Sun Microsystems - Beijing China 13239f758cafSpengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 13249f758cafSpengcheng chen - Sun Microsystems - Beijing China 13259f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (cmd) { 13269f758cafSpengcheng chen - Sun Microsystems - Beijing China case DDI_DETACH: 13279f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 13289f758cafSpengcheng chen - Sun Microsystems - Beijing China case DDI_SUSPEND: 13299f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 13309f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(&sc->sc_ic); 13319f758cafSpengcheng chen - Sun Microsystems - Beijing China 13329f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 13339f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 13349f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 13359f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 13369f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 13379f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 13389f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13399f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_stop(sc); 13409f758cafSpengcheng chen - Sun Microsystems - Beijing China 13419f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 13429f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 13439f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 13449f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 13459f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13469f758cafSpengcheng chen - Sun Microsystems - Beijing China 13479f758cafSpengcheng chen - Sun Microsystems - Beijing China if (!ATU_REATTACH(sc)) { 13489f758cafSpengcheng chen - Sun Microsystems - Beijing China err = mac_disable(sc->sc_ic.ic_mach); 13499f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 13509f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 13519f758cafSpengcheng chen - Sun Microsystems - Beijing China 13529f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_stop(sc); 13539f758cafSpengcheng chen - Sun Microsystems - Beijing China 13549f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_unregister_hotplug_cbs(dip); 13559f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach); 13569f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_detach(&sc->sc_ic); 13579f758cafSpengcheng chen - Sun Microsystems - Beijing China 13589f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 13599f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txlock); 13609f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxlock); 13619f758cafSpengcheng chen - Sun Microsystems - Beijing China 13629f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_remove_minor_node(dip, NULL); 13639f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13649f758cafSpengcheng chen - Sun Microsystems - Beijing China 13659f758cafSpengcheng chen - Sun Microsystems - Beijing China usb_client_detach(dip, sc->sc_udev); 13669f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_soft_state_free(atu_soft_state_p, ddi_get_instance(dip)); 13679f758cafSpengcheng chen - Sun Microsystems - Beijing China 13689f758cafSpengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 13699f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13709f758cafSpengcheng chen - Sun Microsystems - Beijing China 13719f758cafSpengcheng chen - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(atu_dev_ops, nulldev, nulldev, atu_attach, 13729f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 13739f758cafSpengcheng chen - Sun Microsystems - Beijing China 13749f758cafSpengcheng chen - Sun Microsystems - Beijing China static struct modldrv atu_modldrv = { 13759f758cafSpengcheng chen - Sun Microsystems - Beijing China &mod_driverops, 13769f758cafSpengcheng chen - Sun Microsystems - Beijing China "atu driver v1.1", 13779f758cafSpengcheng chen - Sun Microsystems - Beijing China &atu_dev_ops 13789f758cafSpengcheng chen - Sun Microsystems - Beijing China }; 13799f758cafSpengcheng chen - Sun Microsystems - Beijing China 13809f758cafSpengcheng chen - Sun Microsystems - Beijing China static struct modlinkage modlinkage = { 13819f758cafSpengcheng chen - Sun Microsystems - Beijing China MODREV_1, 13829f758cafSpengcheng chen - Sun Microsystems - Beijing China (void *)&atu_modldrv, 13839f758cafSpengcheng chen - Sun Microsystems - Beijing China NULL 13849f758cafSpengcheng chen - Sun Microsystems - Beijing China }; 13859f758cafSpengcheng chen - Sun Microsystems - Beijing China 13869f758cafSpengcheng chen - Sun Microsystems - Beijing China int 13879f758cafSpengcheng chen - Sun Microsystems - Beijing China _info(struct modinfo *modinfop) 13889f758cafSpengcheng chen - Sun Microsystems - Beijing China { 13899f758cafSpengcheng chen - Sun Microsystems - Beijing China return (mod_info(&modlinkage, modinfop)); 13909f758cafSpengcheng chen - Sun Microsystems - Beijing China } 13919f758cafSpengcheng chen - Sun Microsystems - Beijing China 13929f758cafSpengcheng chen - Sun Microsystems - Beijing China int 13939f758cafSpengcheng chen - Sun Microsystems - Beijing China _init(void) 13949f758cafSpengcheng chen - Sun Microsystems - Beijing China { 13959f758cafSpengcheng chen - Sun Microsystems - Beijing China int status; 13969f758cafSpengcheng chen - Sun Microsystems - Beijing China 13979f758cafSpengcheng chen - Sun Microsystems - Beijing China status = ddi_soft_state_init(&atu_soft_state_p, 13989f758cafSpengcheng chen - Sun Microsystems - Beijing China sizeof (struct atu_softc), 1); 13999f758cafSpengcheng chen - Sun Microsystems - Beijing China if (status != 0) 14009f758cafSpengcheng chen - Sun Microsystems - Beijing China return (status); 14019f758cafSpengcheng chen - Sun Microsystems - Beijing China 14029f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_init_ops(&atu_dev_ops, "atu"); 14039f758cafSpengcheng chen - Sun Microsystems - Beijing China status = mod_install(&modlinkage); 14049f758cafSpengcheng chen - Sun Microsystems - Beijing China if (status != 0) { 14059f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_fini_ops(&atu_dev_ops); 14069f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_soft_state_fini(&atu_soft_state_p); 14079f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14089f758cafSpengcheng chen - Sun Microsystems - Beijing China return (status); 14099f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14109f758cafSpengcheng chen - Sun Microsystems - Beijing China 14119f758cafSpengcheng chen - Sun Microsystems - Beijing China int 14129f758cafSpengcheng chen - Sun Microsystems - Beijing China _fini(void) 14139f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14149f758cafSpengcheng chen - Sun Microsystems - Beijing China int status; 14159f758cafSpengcheng chen - Sun Microsystems - Beijing China 14169f758cafSpengcheng chen - Sun Microsystems - Beijing China status = mod_remove(&modlinkage); 14179f758cafSpengcheng chen - Sun Microsystems - Beijing China if (status == 0) { 14189f758cafSpengcheng chen - Sun Microsystems - Beijing China mac_fini_ops(&atu_dev_ops); 14199f758cafSpengcheng chen - Sun Microsystems - Beijing China ddi_soft_state_fini(&atu_soft_state_p); 14209f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14219f758cafSpengcheng chen - Sun Microsystems - Beijing China return (status); 14229f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14239f758cafSpengcheng chen - Sun Microsystems - Beijing China 14249f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 14259f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_start(void *arg) 14269f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14279f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 14289f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 14299f758cafSpengcheng chen - Sun Microsystems - Beijing China 14309f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 14319f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_init(sc); 14329f758cafSpengcheng chen - Sun Microsystems - Beijing China 14339f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 14349f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 14359f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14369f758cafSpengcheng chen - Sun Microsystems - Beijing China 14379f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 14389f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_stop(void *arg) 14399f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14409f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 14419f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 14429f758cafSpengcheng chen - Sun Microsystems - Beijing China 14439f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 14449f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 14459f758cafSpengcheng chen - Sun Microsystems - Beijing China 14469f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 14479f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 14489f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 14499f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 14509f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 14519f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 14529f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14539f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) atu_stop(sc); 14549f758cafSpengcheng chen - Sun Microsystems - Beijing China 14559f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 14569f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14579f758cafSpengcheng chen - Sun Microsystems - Beijing China 14589f758cafSpengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 14599f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 14609f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_unicst(void *arg, const uint8_t *macaddr) 14619f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14629f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ENOTSUP); 14639f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14649f758cafSpengcheng chen - Sun Microsystems - Beijing China 14659f758cafSpengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 14669f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 14679f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 14689f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14699f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ENOTSUP); 14709f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14719f758cafSpengcheng chen - Sun Microsystems - Beijing China 14729f758cafSpengcheng chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 14739f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 14749f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_promisc(void *arg, boolean_t on) 14759f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14769f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 14779f758cafSpengcheng chen - Sun Microsystems - Beijing China } 14789f758cafSpengcheng chen - Sun Microsystems - Beijing China 14799f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 14809f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t len, 14819f758cafSpengcheng chen - Sun Microsystems - Beijing China const void *buf) 14829f758cafSpengcheng chen - Sun Microsystems - Beijing China { 14839f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 14849f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 14859f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 14869f758cafSpengcheng chen - Sun Microsystems - Beijing China 14879f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ieee80211_setprop(ic, name, id, len, buf); 14889f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != ENETRESET) 14899f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 14909f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_des_esslen == 0) 14919f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 14929f758cafSpengcheng chen - Sun Microsystems - Beijing China 14939f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 14949f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ATU_RUNNING(sc)) { 14959f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 14969f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 14979f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 14989f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 14999f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 15009f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15019f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_init(sc); 15029f758cafSpengcheng chen - Sun Microsystems - Beijing China 15039f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 15049f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 15059f758cafSpengcheng chen - Sun Microsystems - Beijing China return (err); 15069f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 15079f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 15089f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15099f758cafSpengcheng chen - Sun Microsystems - Beijing China 15109f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 15119f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 15129f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15139f758cafSpengcheng chen - Sun Microsystems - Beijing China 1514*0dc2366fSVenugopal Iyer static int 1515*0dc2366fSVenugopal Iyer atu_m_getprop(void *arg, const char *name, mac_prop_id_t id, 1516*0dc2366fSVenugopal Iyer uint_t length, void *buf) 1517*0dc2366fSVenugopal Iyer { 1518*0dc2366fSVenugopal Iyer struct atu_softc *sc = (struct atu_softc *)arg; 1519*0dc2366fSVenugopal Iyer struct ieee80211com *ic = &sc->sc_ic; 1520*0dc2366fSVenugopal Iyer 1521*0dc2366fSVenugopal Iyer return (ieee80211_getprop(ic, name, id, length, buf)); 1522*0dc2366fSVenugopal Iyer } 1523*0dc2366fSVenugopal Iyer 1524*0dc2366fSVenugopal Iyer static void 1525*0dc2366fSVenugopal Iyer atu_m_propinfo(void *arg, const char *name, mac_prop_id_t id, 1526*0dc2366fSVenugopal Iyer mac_prop_info_handle_t mph) 1527*0dc2366fSVenugopal Iyer { 1528*0dc2366fSVenugopal Iyer struct atu_softc *sc = (struct atu_softc *)arg; 1529*0dc2366fSVenugopal Iyer struct ieee80211com *ic = &sc->sc_ic; 1530*0dc2366fSVenugopal Iyer 1531*0dc2366fSVenugopal Iyer ieee80211_propinfo(ic, name, id, mph); 1532*0dc2366fSVenugopal Iyer } 1533*0dc2366fSVenugopal Iyer 15349f758cafSpengcheng chen - Sun Microsystems - Beijing China static void 15359f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 15369f758cafSpengcheng chen - Sun Microsystems - Beijing China { 15379f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 15389f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 15399f758cafSpengcheng chen - Sun Microsystems - Beijing China int err; 15409f758cafSpengcheng chen - Sun Microsystems - Beijing China 15419f758cafSpengcheng chen - Sun Microsystems - Beijing China err = ieee80211_ioctl(ic, wq, mp); 15429f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err != ENETRESET || ic->ic_des_esslen == 0) 15439f758cafSpengcheng chen - Sun Microsystems - Beijing China return; 15449f758cafSpengcheng chen - Sun Microsystems - Beijing China 15459f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 15469f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ATU_RUNNING(sc)) { 15479f758cafSpengcheng chen - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 15489f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 15499f758cafSpengcheng chen - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 15509f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 15519f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 15529f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15539f758cafSpengcheng chen - Sun Microsystems - Beijing China err = atu_init(sc); 15549f758cafSpengcheng chen - Sun Microsystems - Beijing China 15559f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 15569f758cafSpengcheng chen - Sun Microsystems - Beijing China if (err) 15579f758cafSpengcheng chen - Sun Microsystems - Beijing China return; 15589f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 15599f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 15609f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15619f758cafSpengcheng chen - Sun Microsystems - Beijing China 15629f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 15639f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15649f758cafSpengcheng chen - Sun Microsystems - Beijing China 15659f758cafSpengcheng chen - Sun Microsystems - Beijing China static mblk_t * 15669f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_tx(void *arg, mblk_t *mp) 15679f758cafSpengcheng chen - Sun Microsystems - Beijing China { 15689f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 15699f758cafSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 15709f758cafSpengcheng chen - Sun Microsystems - Beijing China mblk_t *next; 15719f758cafSpengcheng chen - Sun Microsystems - Beijing China 15729f758cafSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_state != IEEE80211_S_RUN) { 15739f758cafSpengcheng chen - Sun Microsystems - Beijing China freemsgchain(mp); 15749f758cafSpengcheng chen - Sun Microsystems - Beijing China return (NULL); 15759f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15769f758cafSpengcheng chen - Sun Microsystems - Beijing China 15779f758cafSpengcheng chen - Sun Microsystems - Beijing China while (mp != NULL) { 15789f758cafSpengcheng chen - Sun Microsystems - Beijing China next = mp->b_next; 15799f758cafSpengcheng chen - Sun Microsystems - Beijing China mp->b_next = NULL; 15809f758cafSpengcheng chen - Sun Microsystems - Beijing China if (atu_send(ic, mp, IEEE80211_FC0_TYPE_DATA) == ENOMEM) { 15819f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 15829f758cafSpengcheng chen - Sun Microsystems - Beijing China sc->sc_need_sched = 1; 15839f758cafSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 15849f758cafSpengcheng chen - Sun Microsystems - Beijing China 15859f758cafSpengcheng chen - Sun Microsystems - Beijing China mp->b_next = next; 15869f758cafSpengcheng chen - Sun Microsystems - Beijing China return (mp); 15879f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15889f758cafSpengcheng chen - Sun Microsystems - Beijing China mp = next; 15899f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15909f758cafSpengcheng chen - Sun Microsystems - Beijing China 15919f758cafSpengcheng chen - Sun Microsystems - Beijing China return (mp); 15929f758cafSpengcheng chen - Sun Microsystems - Beijing China } 15939f758cafSpengcheng chen - Sun Microsystems - Beijing China 15949f758cafSpengcheng chen - Sun Microsystems - Beijing China static int 15959f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_stat(void *arg, uint_t stat, uint64_t *val) 15969f758cafSpengcheng chen - Sun Microsystems - Beijing China { 15979f758cafSpengcheng chen - Sun Microsystems - Beijing China struct atu_softc *sc = (struct atu_softc *)arg; 15989f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_ic; 15999f758cafSpengcheng chen - Sun Microsystems - Beijing China ieee80211_node_t *in; 16009f758cafSpengcheng chen - Sun Microsystems - Beijing China 16019f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_LOCK(sc); 16029f758cafSpengcheng chen - Sun Microsystems - Beijing China switch (stat) { 16039f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_IFSPEED: 16049f758cafSpengcheng chen - Sun Microsystems - Beijing China in = ic->ic_bss; 16059f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 16069f758cafSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_RATE(in->in_txrate) : 16079f758cafSpengcheng chen - Sun Microsystems - Beijing China ic->ic_fixed_rate) / 2 * 1000000; 16089f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16099f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_NOXMTBUF: 16109f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = sc->sc_tx_nobuf; 16119f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16129f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_NORCVBUF: 16139f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = sc->sc_rx_nobuf; 16149f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16159f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_IERRORS: 16169f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = sc->sc_rx_err; 16179f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16189f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_RBYTES: 16199f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_bytes; 16209f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16219f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_IPACKETS: 16229f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_frags; 16239f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16249f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_OBYTES: 16259f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_bytes; 16269f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16279f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_OPACKETS: 16289f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_frags; 16299f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16309f758cafSpengcheng chen - Sun Microsystems - Beijing China case MAC_STAT_OERRORS: 16319f758cafSpengcheng chen - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_failed; 16329f758cafSpengcheng chen - Sun Microsystems - Beijing China break; 16339f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_TX_FRAGS: 16349f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_TX: 16359f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_TX_FAILED: 16369f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_TX_RETRANS: 16379f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_TX_RERETRANS: 16389f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_RTS_SUCCESS: 16399f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_RTS_FAILURE: 16409f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_ACK_FAILURE: 16419f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_RX_FRAGS: 16429f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_RX: 16439f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_FCS_ERRORS: 16449f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_WEP_ERRORS: 16459f758cafSpengcheng chen - Sun Microsystems - Beijing China case WIFI_STAT_RX_DUPS: 16469f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 16479f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ieee80211_stat(ic, stat, val)); 16489f758cafSpengcheng chen - Sun Microsystems - Beijing China default: 16499f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 16509f758cafSpengcheng chen - Sun Microsystems - Beijing China return (ENOTSUP); 16519f758cafSpengcheng chen - Sun Microsystems - Beijing China } 16529f758cafSpengcheng chen - Sun Microsystems - Beijing China 16539f758cafSpengcheng chen - Sun Microsystems - Beijing China ATU_UNLOCK(sc); 16549f758cafSpengcheng chen - Sun Microsystems - Beijing China return (0); 16559f758cafSpengcheng chen - Sun Microsystems - Beijing China } 16569f758cafSpengcheng chen - Sun Microsystems - Beijing China 16579f758cafSpengcheng chen - Sun Microsystems - Beijing China static mac_callbacks_t atu_m_callbacks = { 1658*0dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 16599f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_stat, 16609f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_start, 16619f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_stop, 16629f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_promisc, 16639f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_multicst, 16649f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_unicst, 16659f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_tx, 1666*0dc2366fSVenugopal Iyer NULL, 16679f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_ioctl, 16689f758cafSpengcheng chen - Sun Microsystems - Beijing China NULL, 16699f758cafSpengcheng chen - Sun Microsystems - Beijing China NULL, 16709f758cafSpengcheng chen - Sun Microsystems - Beijing China NULL, 16719f758cafSpengcheng chen - Sun Microsystems - Beijing China atu_m_setprop, 1672*0dc2366fSVenugopal Iyer atu_m_getprop, 1673*0dc2366fSVenugopal Iyer atu_m_propinfo 16749f758cafSpengcheng chen - Sun Microsystems - Beijing China }; 1675