xref: /illumos-gate/usr/src/uts/common/io/atu/atu.c (revision 0dc2366f)
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
atu_usb_request(struct atu_softc * sc,uint8_t type,uint8_t request,uint16_t value,uint16_t index,uint16_t length,uint8_t * data)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
atu_get_mib(struct atu_softc * sc,uint8_t type,uint8_t size,uint8_t index,uint8_t * buf)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
atu_get_cmd_status(struct atu_softc * sc,uint8_t cmd,uint8_t * status)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
atu_get_dfu_state(struct atu_softc * sc)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
atu_get_opmode(struct atu_softc * sc,uint8_t * mode)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
atu_get_config(struct atu_softc * sc)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
atu_wait_completion(struct atu_softc * sc,uint8_t cmd,uint8_t * status)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
atu_send_command(struct atu_softc * sc,uint8_t * command,int size)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
atu_send_mib(struct atu_softc * sc,uint8_t type,uint8_t size,uint8_t index,void * data)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
atu_switch_radio(struct atu_softc * sc,boolean_t on)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
atu_config(struct atu_softc * sc)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
atu_start_scan(struct atu_softc * sc)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
atu_join(struct atu_softc * sc,struct ieee80211_node * node)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
atu_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)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
atu_open_pipes(struct atu_softc * sc)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
atu_close_pipes(struct atu_softc * sc)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
atu_rxeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)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
atu_txeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)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
atu_rx_trigger(struct atu_softc * sc)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
atu_tx_trigger(struct atu_softc * sc,mblk_t * mp)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
atu_init_rx_queue(struct atu_softc * sc)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
atu_init_tx_queue(struct atu_softc * sc)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
atu_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)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
atu_stop(struct atu_softc * sc)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
atu_init(struct atu_softc * sc)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
atu_watchdog(void * arg)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
atu_dfu_stage1(void * arg)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
atu_dfu_stage2(void * arg)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
atu_load_microcode(struct atu_softc * sc,boolean_t attach)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
atu_disconnect(dev_info_t * dip)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
atu_reconnect(dev_info_t * dip)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
atu_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
atu_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
_info(struct modinfo * modinfop)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
_init(void)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
_fini(void)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
atu_m_start(void * arg)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
atu_m_stop(void * arg)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
atu_m_unicst(void * arg,const uint8_t * macaddr)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
atu_m_multicst(void * arg,boolean_t add,const uint8_t * mca)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
atu_m_promisc(void * arg,boolean_t on)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
atu_m_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t len,const void * buf)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
atu_m_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t length,void * buf)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
atu_m_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t mph)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
atu_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)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 *
atu_m_tx(void * arg,mblk_t * mp)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
atu_m_stat(void * arg,uint_t stat,uint64_t * val)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