[BACK]Return to if_atu.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/if_atu.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_atu.c,v 1.86 2007/07/18 18:10:31 damien Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2003, 2004
        !             4:  *     Daan Vreeken <Danovitsch@Vitsch.net>.  All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. All advertising materials mentioning features or use of this software
        !            15:  *    must display the following acknowledgement:
        !            16:  *     This product includes software developed by Daan Vreeken.
        !            17:  * 4. Neither the name of the author nor the names of any co-contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY Daan Vreeken AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL Daan Vreeken OR THE VOICES IN HIS HEAD
        !            25:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            26:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            27:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            28:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            31:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: /*
        !            35:  * Atmel AT76c503 / AT76c503a / AT76c505 / AT76c505a  USB WLAN driver
        !            36:  * version 0.5 - 2004-08-03
        !            37:  *
        !            38:  * Originally written by Daan Vreeken <Danovitsch @ Vitsch . net>
        !            39:  *  http://vitsch.net/bsd/atuwi
        !            40:  *
        !            41:  * Contributed to by :
        !            42:  *  Chris Whitehouse, Alistair Phillips, Peter Pilka, Martijn van Buul,
        !            43:  *  Suihong Liang, Arjan van Leeuwen, Stuart Walsh
        !            44:  *
        !            45:  * Ported to OpenBSD by Theo de Raadt and David Gwynne.
        !            46:  */
        !            47:
        !            48: #include "bpfilter.h"
        !            49:
        !            50: #include <sys/param.h>
        !            51: #include <sys/sockio.h>
        !            52: #include <sys/mbuf.h>
        !            53: #include <sys/kernel.h>
        !            54: #include <sys/socket.h>
        !            55: #include <sys/systm.h>
        !            56: #include <sys/malloc.h>
        !            57: #include <sys/kthread.h>
        !            58: #include <sys/queue.h>
        !            59: #include <sys/device.h>
        !            60:
        !            61: #include <machine/bus.h>
        !            62:
        !            63: #include <dev/usb/usb.h>
        !            64: #include <dev/usb/usbdi.h>
        !            65: #include <dev/usb/usbdi_util.h>
        !            66: #include <dev/usb/usbdivar.h>
        !            67:
        !            68: #include <dev/usb/usbdevs.h>
        !            69:
        !            70: #if NBPFILTER > 0
        !            71: #include <net/bpf.h>
        !            72: #endif
        !            73:
        !            74: #include <net/if.h>
        !            75: #include <net/if_dl.h>
        !            76: #include <net/if_media.h>
        !            77:
        !            78: #ifdef INET
        !            79: #include <netinet/in.h>
        !            80: #include <netinet/if_ether.h>
        !            81: #endif
        !            82:
        !            83: #include <net80211/ieee80211_var.h>
        !            84: #include <net80211/ieee80211_radiotap.h>
        !            85:
        !            86: #ifdef USB_DEBUG
        !            87: #define ATU_DEBUG
        !            88: #endif
        !            89:
        !            90: #include <dev/usb/if_atureg.h>
        !            91:
        !            92: #ifdef ATU_DEBUG
        !            93: #define DPRINTF(x)     do { if (atudebug) printf x; } while (0)
        !            94: #define DPRINTFN(n,x)  do { if (atudebug>(n)) printf x; } while (0)
        !            95: int atudebug = 1;
        !            96: #else
        !            97: #define DPRINTF(x)
        !            98: #define DPRINTFN(n,x)
        !            99: #endif
        !           100:
        !           101: int atu_match(struct device *, void *, void *);
        !           102: void atu_attach(struct device *, struct device *, void *);
        !           103: int atu_detach(struct device *, int);
        !           104: int atu_activate(struct device *, enum devact);
        !           105:
        !           106: struct cfdriver atu_cd = {
        !           107:        NULL, "atu", DV_IFNET
        !           108: };
        !           109:
        !           110: const struct cfattach atu_ca = {
        !           111:        sizeof(struct atu_softc),
        !           112:        atu_match,
        !           113:        atu_attach,
        !           114:        atu_detach,
        !           115:        atu_activate,
        !           116: };
        !           117:
        !           118: /*
        !           119:  * Various supported device vendors/products/radio type.
        !           120:  */
        !           121: struct atu_type atu_devs[] = {
        !           122:        { USB_VENDOR_3COM,      USB_PRODUCT_3COM_3CRSHEW696,
        !           123:          RadioRFMD,            ATU_NO_QUIRK },
        !           124:        { USB_VENDOR_ABOCOM,    USB_PRODUCT_ABOCOM_BWU613,
        !           125:          RadioRFMD,            ATU_NO_QUIRK },
        !           126:        { USB_VENDOR_ACCTON,    USB_PRODUCT_ACCTON_2664W,
        !           127:          AT76C503_rfmd_acc,    ATU_NO_QUIRK },
        !           128:        { USB_VENDOR_ACERP,     USB_PRODUCT_ACERP_AWL300,
        !           129:          RadioIntersil,        ATU_NO_QUIRK },
        !           130:        { USB_VENDOR_ACERP,     USB_PRODUCT_ACERP_AWL400,
        !           131:          RadioRFMD,            ATU_NO_QUIRK },
        !           132:        { USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_802UAT1,
        !           133:          RadioRFMD,            ATU_NO_QUIRK },
        !           134:        { USB_VENDOR_ADDTRON,   USB_PRODUCT_ADDTRON_AWU120,
        !           135:          RadioIntersil,        ATU_NO_QUIRK },
        !           136:        { USB_VENDOR_AINCOMM,   USB_PRODUCT_AINCOMM_AWU2000B,
        !           137:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           138:        { USB_VENDOR_ASKEY,     USB_PRODUCT_ASKEY_VOYAGER1010,
        !           139:          RadioIntersil,        ATU_NO_QUIRK },
        !           140:        { USB_VENDOR_ASKEY,     USB_PRODUCT_ASKEY_WLL013I,
        !           141:          RadioIntersil,        ATU_NO_QUIRK },
        !           142:        { USB_VENDOR_ASKEY,     USB_PRODUCT_ASKEY_WLL013,
        !           143:          RadioRFMD,            ATU_NO_QUIRK },
        !           144:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C503I1,
        !           145:          RadioIntersil,        ATU_NO_QUIRK },
        !           146:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C503I2,
        !           147:          AT76C503_i3863,       ATU_NO_QUIRK },
        !           148:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C503RFMD,
        !           149:          RadioRFMD,            ATU_NO_QUIRK },
        !           150:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C505RFMD,
        !           151:          AT76C505_rfmd,        ATU_NO_QUIRK },
        !           152:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C505RFMD2958,
        !           153:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           154:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C505A, /* SMC2662 V.4 */
        !           155:          RadioRFMD2958_SMC,    ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
        !           156:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_AT76C505AS, /* quirk? */
        !           157:          RadioRFMD2958_SMC,    ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
        !           158:        { USB_VENDOR_ATMEL,     USB_PRODUCT_ATMEL_WN210,
        !           159:          RadioRFMD,            ATU_NO_QUIRK },
        !           160:        { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_F5D6050,
        !           161:          RadioRFMD,            ATU_NO_QUIRK },
        !           162:        { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_C11U,
        !           163:          RadioIntersil,        ATU_NO_QUIRK },
        !           164:        { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_WL210,
        !           165:          RadioIntersil,        ATU_NO_QUIRK },
        !           166:        { USB_VENDOR_COMPAQ,    USB_PRODUCT_COMPAQ_IPAQWLAN,
        !           167:          RadioRFMD,            ATU_NO_QUIRK },
        !           168:        { USB_VENDOR_COREGA,    USB_PRODUCT_COREGA_WLUSB_11_STICK,
        !           169:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           170:        { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CHUSB611G,
        !           171:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           172:        { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_WL200U,
        !           173:          RadioRFMD,            ATU_NO_QUIRK },
        !           174:        { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_WL240U,
        !           175:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           176:        { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_XH1153,
        !           177:          RadioRFMD,            ATU_NO_QUIRK },
        !           178:        { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_DWL120E,
        !           179:          RadioRFMD,            ATU_NO_QUIRK },
        !           180:        { USB_VENDOR_GIGABYTE,  USB_PRODUCT_GIGABYTE_GNWLBM101,
        !           181:          RadioRFMD,            ATU_NO_QUIRK },
        !           182:        { USB_VENDOR_GIGASET,   USB_PRODUCT_GIGASET_WLAN, /* quirk? */
        !           183:          RadioRFMD2958_SMC,    ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
        !           184:        { USB_VENDOR_HP,        USB_PRODUCT_HP_HN210W,
        !           185:          RadioIntersil,        ATU_NO_QUIRK },
        !           186:        { USB_VENDOR_INTEL,     USB_PRODUCT_INTEL_AP310,
        !           187:          RadioIntersil,        ATU_NO_QUIRK },
        !           188:        { USB_VENDOR_IODATA,    USB_PRODUCT_IODATA_USBWNB11A,
        !           189:          RadioIntersil,        ATU_NO_QUIRK },
        !           190:        { USB_VENDOR_LEXAR,     USB_PRODUCT_LEXAR_2662WAR,
        !           191:          RadioRFMD,            ATU_NO_QUIRK },
        !           192:        { USB_VENDOR_LINKSYS,   USB_PRODUCT_LINKSYS_WUSB11,
        !           193:          RadioIntersil,        ATU_NO_QUIRK },
        !           194:        { USB_VENDOR_LINKSYS2,  USB_PRODUCT_LINKSYS2_WUSB11,
        !           195:          RadioRFMD,            ATU_NO_QUIRK },
        !           196:        { USB_VENDOR_LINKSYS2,  USB_PRODUCT_LINKSYS2_NWU11B,
        !           197:          RadioRFMD,            ATU_NO_QUIRK },
        !           198:        { USB_VENDOR_LINKSYS3,  USB_PRODUCT_LINKSYS3_WUSB11V28,
        !           199:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           200:        { USB_VENDOR_MSI,       USB_PRODUCT_MSI_WLAN,
        !           201:          RadioRFMD2958,        ATU_NO_QUIRK },
        !           202:        { USB_VENDOR_NETGEAR2,  USB_PRODUCT_NETGEAR2_MA101,
        !           203:          RadioIntersil,        ATU_NO_QUIRK },
        !           204:        { USB_VENDOR_NETGEAR2,  USB_PRODUCT_NETGEAR2_MA101B,
        !           205:          RadioRFMD,            ATU_NO_QUIRK },
        !           206:        { USB_VENDOR_OQO,       USB_PRODUCT_OQO_WIFI01,
        !           207:          RadioRFMD2958_SMC,    ATU_QUIRK_NO_REMAP | ATU_QUIRK_FW_DELAY },
        !           208:        { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_GW_US11S,
        !           209:          RadioRFMD,            ATU_NO_QUIRK },
        !           210:        { USB_VENDOR_SAMSUNG,   USB_PRODUCT_SAMSUNG_SWL2100W,
        !           211:          AT76C503_i3863,       ATU_NO_QUIRK },
        !           212:        { USB_VENDOR_SIEMENS2,  USB_PRODUCT_SIEMENS2_WLL013,
        !           213:          RadioRFMD,            ATU_NO_QUIRK },
        !           214:        { USB_VENDOR_SMC3,      USB_PRODUCT_SMC3_2662WV1,
        !           215:          RadioIntersil,        ATU_NO_QUIRK },
        !           216:        { USB_VENDOR_SMC3,      USB_PRODUCT_SMC3_2662WV2,
        !           217:          AT76C503_rfmd_acc,    ATU_NO_QUIRK },
        !           218:        { USB_VENDOR_TEKRAM,    USB_PRODUCT_TEKRAM_U300C,
        !           219:          RadioIntersil,        ATU_NO_QUIRK },
        !           220:        { USB_VENDOR_ZCOM,      USB_PRODUCT_ZCOM_M4Y750,
        !           221:          RadioIntersil,        ATU_NO_QUIRK },
        !           222: };
        !           223:
        !           224: struct atu_radfirm {
        !           225:        enum    atu_radio_type atur_type;
        !           226:        char    *atur_internal;
        !           227:        char    *atur_external;
        !           228:        u_int8_t max_rssi;
        !           229: } atu_radfirm[] = {
        !           230:        { RadioRFMD,            "atu-rfmd-int",         "atu-rfmd-ext", 0 },
        !           231:        { RadioRFMD2958,        "atu-rfmd2958-int",     "atu-rfmd2958-ext", 81 },
        !           232:        { RadioRFMD2958_SMC,    "atu-rfmd2958smc-int",  "atu-rfmd2958smc-ext", 0 },
        !           233:        { RadioIntersil,        "atu-intersil-int",     "atu-intersil-ext", 0 },
        !           234:        {
        !           235:                AT76C503_i3863,
        !           236:                "atu-at76c503-i3863-int",
        !           237:                "atu-at76c503-i3863-ext",
        !           238:                0
        !           239:        },
        !           240:        {
        !           241:                AT76C503_rfmd_acc,
        !           242:                "atu-at76c503-rfmd-acc-int",
        !           243:                "atu-at76c503-rfmd-acc-ext",
        !           244:                0
        !           245:        },
        !           246:        {
        !           247:                AT76C505_rfmd,
        !           248:                "atu-at76c505-rfmd-int",
        !           249:                "atu-at76c505-rfmd-ext",
        !           250:                0
        !           251:        }
        !           252: };
        !           253:
        !           254: int    atu_newbuf(struct atu_softc *, struct atu_chain *, struct mbuf *);
        !           255: void   atu_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
        !           256: void   atu_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
        !           257: void   atu_start(struct ifnet *);
        !           258: int    atu_ioctl(struct ifnet *, u_long, caddr_t);
        !           259: int    atu_init(struct ifnet *);
        !           260: void   atu_stop(struct ifnet *, int);
        !           261: void   atu_watchdog(struct ifnet *);
        !           262: usbd_status atu_usb_request(struct atu_softc *sc, u_int8_t type,
        !           263:            u_int8_t request, u_int16_t value, u_int16_t index,
        !           264:            u_int16_t length, u_int8_t *data);
        !           265: int    atu_send_command(struct atu_softc *sc, u_int8_t *command, int size);
        !           266: int    atu_get_cmd_status(struct atu_softc *sc, u_int8_t cmd,
        !           267:            u_int8_t *status);
        !           268: int    atu_wait_completion(struct atu_softc *sc, u_int8_t cmd,
        !           269:            u_int8_t *status);
        !           270: int    atu_send_mib(struct atu_softc *sc, u_int8_t type,
        !           271:            u_int8_t size, u_int8_t index, void *data);
        !           272: int    atu_get_mib(struct atu_softc *sc, u_int8_t type,
        !           273:            u_int8_t size, u_int8_t index, u_int8_t *buf);
        !           274: #if 0
        !           275: int    atu_start_ibss(struct atu_softc *sc);
        !           276: #endif
        !           277: int    atu_start_scan(struct atu_softc *sc);
        !           278: int    atu_switch_radio(struct atu_softc *sc, int state);
        !           279: int    atu_initial_config(struct atu_softc *sc);
        !           280: int    atu_join(struct atu_softc *sc, struct ieee80211_node *node);
        !           281: int8_t atu_get_dfu_state(struct atu_softc *sc);
        !           282: u_int8_t atu_get_opmode(struct atu_softc *sc, u_int8_t *mode);
        !           283: void   atu_internal_firmware(void *);
        !           284: void   atu_external_firmware(void *);
        !           285: int    atu_get_card_config(struct atu_softc *sc);
        !           286: int    atu_media_change(struct ifnet *ifp);
        !           287: void   atu_media_status(struct ifnet *ifp, struct ifmediareq *req);
        !           288: int    atu_tx_list_init(struct atu_softc *);
        !           289: int    atu_rx_list_init(struct atu_softc *);
        !           290: void   atu_xfer_list_free(struct atu_softc *sc, struct atu_chain *ch,
        !           291:            int listlen);
        !           292:
        !           293: void atu_task(void *);
        !           294: int atu_newstate(struct ieee80211com *, enum ieee80211_state, int);
        !           295: int atu_tx_start(struct atu_softc *, struct ieee80211_node *,
        !           296:     struct atu_chain *, struct mbuf *);
        !           297: void atu_complete_attach(struct atu_softc *);
        !           298: u_int8_t atu_calculate_padding(int);
        !           299:
        !           300: usbd_status
        !           301: atu_usb_request(struct atu_softc *sc, u_int8_t type,
        !           302:     u_int8_t request, u_int16_t value, u_int16_t index, u_int16_t length,
        !           303:     u_int8_t *data)
        !           304: {
        !           305:        usb_device_request_t    req;
        !           306:        usbd_xfer_handle        xfer;
        !           307:        usbd_status             err;
        !           308:        int                     total_len = 0, s;
        !           309:
        !           310:        req.bmRequestType = type;
        !           311:        req.bRequest = request;
        !           312:        USETW(req.wValue, value);
        !           313:        USETW(req.wIndex, index);
        !           314:        USETW(req.wLength, length);
        !           315:
        !           316: #ifdef ATU_DEBUG
        !           317:        if (atudebug) {
        !           318:                if ((data == NULL) || (type & UT_READ)) {
        !           319:                        DPRINTFN(20, ("%s: req=%02x val=%02x ind=%02x "
        !           320:                            "len=%02x\n", sc->atu_dev.dv_xname, request,
        !           321:                            value, index, length));
        !           322:                } else {
        !           323:                        DPRINTFN(20, ("%s: req=%02x val=%02x ind=%02x "
        !           324:                            "len=%02x [%8D]\n", sc->atu_dev.dv_xname,
        !           325:                            request, value, index, length, data, " "));
        !           326:                }
        !           327:        }
        !           328: #endif /* ATU_DEBUG */
        !           329:
        !           330:        s = splnet();
        !           331:
        !           332:        xfer = usbd_alloc_xfer(sc->atu_udev);
        !           333:        usbd_setup_default_xfer(xfer, sc->atu_udev, 0, 500000, &req, data,
        !           334:            length, USBD_SHORT_XFER_OK, 0);
        !           335:
        !           336:        err = usbd_sync_transfer(xfer);
        !           337:
        !           338:        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
        !           339:
        !           340: #ifdef ATU_DEBUG
        !           341:        if (atudebug) {
        !           342:                if (type & UT_READ) {
        !           343:                        DPRINTFN(20, ("%s: transfered 0x%x bytes in\n",
        !           344:                            sc->atu_dev.dv_xname, total_len));
        !           345:                        DPRINTFN(20, ("%s: dump [%10D]\n",
        !           346:                            sc->atu_dev.dv_xname, data, " "));
        !           347:                } else {
        !           348:                        if (total_len != length)
        !           349:                                DPRINTF(("%s: ARG! wrote only %x bytes\n",
        !           350:                                    sc->atu_dev.dv_xname, total_len));
        !           351:                }
        !           352:        }
        !           353: #endif /* ATU_DEBUG */
        !           354:
        !           355:        usbd_free_xfer(xfer);
        !           356:
        !           357:        splx(s);
        !           358:        return(err);
        !           359: }
        !           360:
        !           361: int
        !           362: atu_send_command(struct atu_softc *sc, u_int8_t *command, int size)
        !           363: {
        !           364:        return atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0000,
        !           365:            0x0000, size, command);
        !           366: }
        !           367:
        !           368: int
        !           369: atu_get_cmd_status(struct atu_softc *sc, u_int8_t cmd, u_int8_t *status)
        !           370: {
        !           371:        /*
        !           372:         * all other drivers (including Windoze) request 40 bytes of status
        !           373:         * and get a short-xfer of just 6 bytes. we can save 34 bytes of
        !           374:         * buffer if we just request those 6 bytes in the first place :)
        !           375:         */
        !           376:        /*
        !           377:        return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x22, cmd,
        !           378:            0x0000, 40, status);
        !           379:        */
        !           380:        return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x22, cmd,
        !           381:            0x0000, 6, status);
        !           382: }
        !           383:
        !           384: int
        !           385: atu_wait_completion(struct atu_softc *sc, u_int8_t cmd, u_int8_t *status)
        !           386: {
        !           387:        int                     idle_count = 0, err;
        !           388:        u_int8_t                statusreq[6];
        !           389:
        !           390:        DPRINTFN(15, ("%s: wait-completion: cmd=%02x\n",
        !           391:            sc->atu_dev.dv_xname, cmd));
        !           392:
        !           393:        while (1) {
        !           394:                err = atu_get_cmd_status(sc, cmd, statusreq);
        !           395:                if (err)
        !           396:                        return err;
        !           397:
        !           398: #ifdef ATU_DEBUG
        !           399:                if (atudebug) {
        !           400:                        DPRINTFN(20, ("%s: status=%s cmd=%02x\n",
        !           401:                            sc->atu_dev.dv_xname,
        !           402:                        ether_sprintf(statusreq), cmd));
        !           403:                }
        !           404: #endif /* ATU_DEBUG */
        !           405:
        !           406:                /*
        !           407:                 * during normal operations waiting on STATUS_IDLE
        !           408:                 * will never happen more than once
        !           409:                 */
        !           410:                if ((statusreq[5] == STATUS_IDLE) && (idle_count++ > 20)) {
        !           411:                        DPRINTF(("%s: AAARRGGG!!! FIX ME!\n",
        !           412:                            sc->atu_dev.dv_xname));
        !           413:                        return 0;
        !           414:                }
        !           415:
        !           416:                if ((statusreq[5] != STATUS_IN_PROGRESS) &&
        !           417:                    (statusreq[5] != STATUS_IDLE)) {
        !           418:                        if (status != NULL)
        !           419:                                *status = statusreq[5];
        !           420:                        return 0;
        !           421:                }
        !           422:                usbd_delay_ms(sc->atu_udev, 25);
        !           423:        }
        !           424: }
        !           425:
        !           426: int
        !           427: atu_send_mib(struct atu_softc *sc, u_int8_t type, u_int8_t size,
        !           428:     u_int8_t index, void *data)
        !           429: {
        !           430:        int                             err;
        !           431:        struct atu_cmd_set_mib          request;
        !           432:
        !           433:        /*
        !           434:         * We don't construct a MIB packet first and then memcpy it into an
        !           435:         * Atmel-command-packet, we just construct it the right way at once :)
        !           436:         */
        !           437:
        !           438:        memset(&request, 0, sizeof(request));
        !           439:
        !           440:        request.AtCmd = CMD_SET_MIB;
        !           441:        USETW(request.AtSize, size + 4);
        !           442:
        !           443:        request.MIBType = type;
        !           444:        request.MIBSize = size;
        !           445:        request.MIBIndex = index;
        !           446:        request.MIBReserved = 0;
        !           447:
        !           448:        /*
        !           449:         * For 1 and 2 byte requests we assume a direct value,
        !           450:         * everything bigger than 2 bytes we assume a pointer to the data
        !           451:         */
        !           452:        switch (size) {
        !           453:        case 0:
        !           454:                break;
        !           455:        case 1:
        !           456:                request.data[0]=(long)data & 0x000000ff;
        !           457:                break;
        !           458:        case 2:
        !           459:                request.data[0]=(long)data & 0x000000ff;
        !           460:                request.data[1]=(long)data >> 8;
        !           461:                break;
        !           462:        default:
        !           463:                memcpy(request.data, data, size);
        !           464:                break;
        !           465:        }
        !           466:
        !           467:        err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0000,
        !           468:            0x0000, size+8, (uByte *)&request);
        !           469:        if (err)
        !           470:                return (err);
        !           471:
        !           472:        DPRINTFN(15, ("%s: sendmib : waitcompletion...\n",
        !           473:            sc->atu_dev.dv_xname));
        !           474:        return atu_wait_completion(sc, CMD_SET_MIB, NULL);
        !           475: }
        !           476:
        !           477: int
        !           478: atu_get_mib(struct atu_softc *sc, u_int8_t type, u_int8_t size,
        !           479:     u_int8_t index, u_int8_t *buf)
        !           480: {
        !           481:
        !           482:        /* linux/at76c503.c - 478 */
        !           483:        return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x033,
        !           484:            type << 8, index, size, buf);
        !           485: }
        !           486:
        !           487: #if 0
        !           488: int
        !           489: atu_start_ibss(struct atu_softc *sc)
        !           490: {
        !           491:        int                             err;
        !           492:        struct atu_cmd_start_ibss       Request;
        !           493:
        !           494:        Request.Cmd = CMD_START_IBSS;
        !           495:        Request.Reserved = 0;
        !           496:        Request.Size = sizeof(Request) - 4;
        !           497:
        !           498:        memset(Request.BSSID, 0x00, sizeof(Request.BSSID));
        !           499:        memset(Request.SSID, 0x00, sizeof(Request.SSID));
        !           500:        memcpy(Request.SSID, sc->atu_ssid, sc->atu_ssidlen);
        !           501:        Request.SSIDSize = sc->atu_ssidlen;
        !           502:        if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
        !           503:                Request.Channel = (u_int8_t)sc->atu_desired_channel;
        !           504:        else
        !           505:                Request.Channel = ATU_DEFAULT_CHANNEL;
        !           506:        Request.BSSType = AD_HOC_MODE;
        !           507:        memset(Request.Res, 0x00, sizeof(Request.Res));
        !           508:
        !           509:        /* Write config to adapter */
        !           510:        err = atu_send_command(sc, (u_int8_t *)&Request, sizeof(Request));
        !           511:        if (err) {
        !           512:                DPRINTF(("%s: start ibss failed!\n",
        !           513:                    sc->atu_dev.dv_xname));
        !           514:                return err;
        !           515:        }
        !           516:
        !           517:        /* Wait for the adapter to do its thing */
        !           518:        err = atu_wait_completion(sc, CMD_START_IBSS, NULL);
        !           519:        if (err) {
        !           520:                DPRINTF(("%s: error waiting for start_ibss\n",
        !           521:                    sc->atu_dev.dv_xname));
        !           522:                return err;
        !           523:        }
        !           524:
        !           525:        /* Get the current BSSID */
        !           526:        err = atu_get_mib(sc, MIB_MAC_MGMT__CURRENT_BSSID, sc->atu_bssid);
        !           527:        if (err) {
        !           528:                DPRINTF(("%s: could not get BSSID!\n",
        !           529:                    sc->atu_dev.dv_xname));
        !           530:                return err;
        !           531:        }
        !           532:
        !           533:        DPRINTF(("%s: started a new IBSS (BSSID=%s)\n",
        !           534:            sc->atu_dev.dv_xname, ether_sprintf(sc->atu_bssid)));
        !           535:        return 0;
        !           536: }
        !           537: #endif
        !           538:
        !           539: int
        !           540: atu_start_scan(struct atu_softc *sc)
        !           541: {
        !           542:        struct ieee80211com             *ic = &sc->sc_ic;
        !           543:        struct atu_cmd_do_scan          Scan;
        !           544:        usbd_status                     err;
        !           545:        int                             Cnt;
        !           546:
        !           547:        memset(&Scan, 0, sizeof(Scan));
        !           548:
        !           549:        Scan.Cmd = CMD_START_SCAN;
        !           550:        Scan.Reserved = 0;
        !           551:        USETW(Scan.Size, sizeof(Scan) - 4);
        !           552:
        !           553:        /* use the broadcast BSSID (in active scan) */
        !           554:        for (Cnt=0; Cnt<6; Cnt++)
        !           555:                Scan.BSSID[Cnt] = 0xff;
        !           556:
        !           557:        memcpy(Scan.SSID, ic->ic_des_essid, ic->ic_des_esslen);
        !           558:        Scan.SSID_Len = ic->ic_des_esslen;
        !           559:
        !           560:        /* default values for scan */
        !           561:        Scan.ScanType = ATU_SCAN_ACTIVE;
        !           562:        if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
        !           563:                Scan.Channel = (u_int8_t)sc->atu_desired_channel;
        !           564:        else
        !           565:                Scan.Channel = sc->atu_channel;
        !           566:
        !           567:        /* we like scans to be quick :) */
        !           568:        /* the time we wait before sending probe's */
        !           569:        USETW(Scan.ProbeDelay, 0);
        !           570:        /* the time we stay on one channel */
        !           571:        USETW(Scan.MinChannelTime, 100);
        !           572:        USETW(Scan.MaxChannelTime, 200);
        !           573:        /* whether or not we scan all channels */
        !           574:        Scan.InternationalScan = 0xc1;
        !           575:
        !           576: #ifdef ATU_DEBUG
        !           577:        if (atudebug) {
        !           578:                DPRINTFN(20, ("%s: scan cmd len=%02x\n",
        !           579:                    sc->atu_dev.dv_xname, sizeof(Scan)));
        !           580:                DPRINTFN(20, ("%s: scan cmd: %52D\n", sc->atu_dev.dv_xname,
        !           581:                    (u_int8_t *)&Scan, " "));
        !           582:        }
        !           583: #endif /* ATU_DEBUG */
        !           584:
        !           585:        /* Write config to adapter */
        !           586:        err = atu_send_command(sc, (u_int8_t *)&Scan, sizeof(Scan));
        !           587:        if (err)
        !           588:                return err;
        !           589:
        !           590:        /*
        !           591:         * We don't wait for the command to finish... the mgmt-thread will do
        !           592:         * that for us
        !           593:         */
        !           594:        /*
        !           595:        err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
        !           596:        if (err)
        !           597:                return err;
        !           598:        */
        !           599:        return 0;
        !           600: }
        !           601:
        !           602: int
        !           603: atu_switch_radio(struct atu_softc *sc, int state)
        !           604: {
        !           605:        usbd_status             err;
        !           606:        struct atu_cmd          CmdRadio;
        !           607:
        !           608:        if (sc->atu_radio == RadioIntersil) {
        !           609:                /*
        !           610:                 * Intersil doesn't seem to need/support switching the radio
        !           611:                 * on/off
        !           612:                 */
        !           613:                return 0;
        !           614:        }
        !           615:
        !           616:        memset(&CmdRadio, 0, sizeof(CmdRadio));
        !           617:        CmdRadio.Cmd = CMD_RADIO_ON;
        !           618:
        !           619:        if (sc->atu_radio_on != state) {
        !           620:                if (state == 0)
        !           621:                        CmdRadio.Cmd = CMD_RADIO_OFF;
        !           622:
        !           623:                err = atu_send_command(sc, (u_int8_t *)&CmdRadio,
        !           624:                    sizeof(CmdRadio));
        !           625:                if (err)
        !           626:                        return err;
        !           627:
        !           628:                err = atu_wait_completion(sc, CmdRadio.Cmd, NULL);
        !           629:                if (err)
        !           630:                        return err;
        !           631:
        !           632:                DPRINTFN(10, ("%s: radio turned %s\n",
        !           633:                    sc->atu_dev.dv_xname, state ? "on" : "off"));
        !           634:                sc->atu_radio_on = state;
        !           635:        }
        !           636:        return 0;
        !           637: }
        !           638:
        !           639: int
        !           640: atu_initial_config(struct atu_softc *sc)
        !           641: {
        !           642:        struct ieee80211com             *ic = &sc->sc_ic;
        !           643:        u_int32_t                       i;
        !           644:        usbd_status                     err;
        !           645: /*     u_int8_t                        rates[4] = {0x82, 0x84, 0x8B, 0x96};*/
        !           646:        u_int8_t                        rates[4] = {0x82, 0x04, 0x0B, 0x16};
        !           647:        struct atu_cmd_card_config      cmd;
        !           648:        u_int8_t                        reg_domain;
        !           649:
        !           650:        DPRINTFN(10, ("%s: sending mac-addr\n", sc->atu_dev.dv_xname));
        !           651:        err = atu_send_mib(sc, MIB_MAC_ADDR__ADDR, ic->ic_myaddr);
        !           652:        if (err) {
        !           653:                DPRINTF(("%s: error setting mac-addr\n",
        !           654:                    sc->atu_dev.dv_xname));
        !           655:                return err;
        !           656:        }
        !           657:
        !           658:        /*
        !           659:        DPRINTF(("%s: sending reg-domain\n", sc->atu_dev.dv_xname));
        !           660:        err = atu_send_mib(sc, MIB_PHY__REG_DOMAIN, NR(0x30));
        !           661:        if (err) {
        !           662:                DPRINTF(("%s: error setting mac-addr\n",
        !           663:                    sc->atu_dev.dv_xname));
        !           664:                return err;
        !           665:        }
        !           666:        */
        !           667:
        !           668:        memset(&cmd, 0, sizeof(cmd));
        !           669:        cmd.Cmd = CMD_STARTUP;
        !           670:        cmd.Reserved = 0;
        !           671:        USETW(cmd.Size, sizeof(cmd) - 4);
        !           672:
        !           673:        if (sc->atu_desired_channel != IEEE80211_CHAN_ANY)
        !           674:                cmd.Channel = (u_int8_t)sc->atu_desired_channel;
        !           675:        else
        !           676:                cmd.Channel = sc->atu_channel;
        !           677:        cmd.AutoRateFallback = 1;
        !           678:        memcpy(cmd.BasicRateSet, rates, 4);
        !           679:
        !           680:        /* ShortRetryLimit should be 7 according to 802.11 spec */
        !           681:        cmd.ShortRetryLimit = 7;
        !           682:        USETW(cmd.RTS_Threshold, 2347);
        !           683:        USETW(cmd.FragThreshold, 2346);
        !           684:
        !           685:        /* Doesn't seem to work, but we'll set it to 1 anyway */
        !           686:        cmd.PromiscuousMode = 1;
        !           687:
        !           688:        /* this goes into the beacon we transmit */
        !           689:        cmd.PrivacyInvoked = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
        !           690:
        !           691:        cmd.ExcludeUnencrypted = 0;
        !           692:        switch (ic->ic_nw_keys[ic->ic_wep_txkey].k_cipher) {
        !           693:        case IEEE80211_CIPHER_WEP40:
        !           694:                cmd.EncryptionType = ATU_WEP_40BITS;
        !           695:                break;
        !           696:        case IEEE80211_CIPHER_WEP104:
        !           697:                cmd.EncryptionType = ATU_WEP_104BITS;
        !           698:                break;
        !           699:        default:
        !           700:                cmd.EncryptionType = ATU_WEP_OFF;
        !           701:                break;
        !           702:        }
        !           703:
        !           704:        cmd.WEP_DefaultKeyID = ic->ic_wep_txkey;
        !           705:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
        !           706:                memcpy(cmd.WEP_DefaultKey[i], ic->ic_nw_keys[i].k_key,
        !           707:                    ic->ic_nw_keys[i].k_len);
        !           708:        }
        !           709:
        !           710:        /* Setting the SSID here doesn't seem to do anything */
        !           711:        memcpy(cmd.SSID, ic->ic_des_essid, ic->ic_des_esslen);
        !           712:        cmd.SSID_Len = ic->ic_des_esslen;
        !           713:
        !           714:        cmd.ShortPreamble = 0;
        !           715:        USETW(cmd.BeaconPeriod, 100);
        !           716:        /* cmd.BeaconPeriod = 65535; */
        !           717:
        !           718:        /*
        !           719:         * TODO:
        !           720:         * read reg domain MIB_PHY @ 0x17 (1 byte), (reply = 0x30)
        !           721:         * we should do something usefull with this info. right now it's just
        !           722:         * ignored
        !           723:         */
        !           724:        err = atu_get_mib(sc, MIB_PHY__REG_DOMAIN, &reg_domain);
        !           725:        if (err) {
        !           726:                DPRINTF(("%s: could not get regdomain!\n",
        !           727:                    sc->atu_dev.dv_xname));
        !           728:        } else {
        !           729:                DPRINTF(("%s: we're in reg domain 0x%x according to the "
        !           730:                    "adapter\n", sc->atu_dev.dv_xname, reg_domain));
        !           731:        }
        !           732:
        !           733: #ifdef ATU_DEBUG
        !           734:        if (atudebug) {
        !           735:                DPRINTFN(20, ("%s: configlen=%02x\n", sc->atu_dev.dv_xname,
        !           736:                    sizeof(cmd)));
        !           737:                DPRINTFN(20, ("%s: configdata= %108D\n",
        !           738:                    sc->atu_dev.dv_xname, (u_int8_t *)&cmd, " "));
        !           739:        }
        !           740: #endif /* ATU_DEBUG */
        !           741:
        !           742:        /* Windoze : driver says exclude-unencrypted=1 & encr-type=1 */
        !           743:
        !           744:        err = atu_send_command(sc, (u_int8_t *)&cmd, sizeof(cmd));
        !           745:        if (err)
        !           746:                return err;
        !           747:        err = atu_wait_completion(sc, CMD_STARTUP, NULL);
        !           748:        if (err)
        !           749:                return err;
        !           750:
        !           751:        /* Turn on radio now */
        !           752:        err = atu_switch_radio(sc, 1);
        !           753:        if (err)
        !           754:                return err;
        !           755:
        !           756:        /* preamble type = short */
        !           757:        err = atu_send_mib(sc, MIB_LOCAL__PREAMBLE, NR(PREAMBLE_SHORT));
        !           758:        if (err)
        !           759:                return err;
        !           760:
        !           761:        /* frag = 1536 */
        !           762:        err = atu_send_mib(sc, MIB_MAC__FRAG, NR(2346));
        !           763:        if (err)
        !           764:                return err;
        !           765:
        !           766:        /* rts = 1536 */
        !           767:        err = atu_send_mib(sc, MIB_MAC__RTS, NR(2347));
        !           768:        if (err)
        !           769:                return err;
        !           770:
        !           771:        /* auto rate fallback = 1 */
        !           772:        err = atu_send_mib(sc, MIB_LOCAL__AUTO_RATE_FALLBACK, NR(1));
        !           773:        if (err)
        !           774:                return err;
        !           775:
        !           776:        /* power mode = full on, no power saving */
        !           777:        err = atu_send_mib(sc, MIB_MAC_MGMT__POWER_MODE,
        !           778:            NR(POWER_MODE_ACTIVE));
        !           779:        if (err)
        !           780:                return err;
        !           781:
        !           782:        DPRINTFN(10, ("%s: completed initial config\n",
        !           783:           sc->atu_dev.dv_xname));
        !           784:        return 0;
        !           785: }
        !           786:
        !           787: int
        !           788: atu_join(struct atu_softc *sc, struct ieee80211_node *node)
        !           789: {
        !           790:        struct atu_cmd_join             join;
        !           791:        u_int8_t                        status;
        !           792:        usbd_status                     err;
        !           793:
        !           794:        memset(&join, 0, sizeof(join));
        !           795:
        !           796:        join.Cmd = CMD_JOIN;
        !           797:        join.Reserved = 0x00;
        !           798:        USETW(join.Size, sizeof(join) - 4);
        !           799:
        !           800:        DPRINTFN(15, ("%s: pre-join sc->atu_bssid=%s\n",
        !           801:            sc->atu_dev.dv_xname, ether_sprintf(sc->atu_bssid)));
        !           802:        DPRINTFN(15, ("%s: mode=%d\n", sc->atu_dev.dv_xname,
        !           803:            sc->atu_mode));
        !           804:        memcpy(join.bssid, node->ni_bssid, IEEE80211_ADDR_LEN);
        !           805:        memcpy(join.essid, node->ni_essid, node->ni_esslen);
        !           806:        join.essid_size = node->ni_esslen;
        !           807:        if (node->ni_capinfo & IEEE80211_CAPINFO_IBSS)
        !           808:                join.bss_type = AD_HOC_MODE;
        !           809:        else
        !           810:                join.bss_type = INFRASTRUCTURE_MODE;
        !           811:        join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->ni_chan);
        !           812:
        !           813:        USETW(join.timeout, ATU_JOIN_TIMEOUT);
        !           814:        join.reserved = 0x00;
        !           815:
        !           816:        DPRINTFN(10, ("%s: trying to join BSSID=%s\n",
        !           817:            sc->atu_dev.dv_xname, ether_sprintf(join.bssid)));
        !           818:        err = atu_send_command(sc, (u_int8_t *)&join, sizeof(join));
        !           819:        if (err) {
        !           820:                DPRINTF(("%s: ERROR trying to join IBSS\n",
        !           821:                    sc->atu_dev.dv_xname));
        !           822:                return err;
        !           823:        }
        !           824:        err = atu_wait_completion(sc, CMD_JOIN, &status);
        !           825:        if (err) {
        !           826:                DPRINTF(("%s: error joining BSS!\n",
        !           827:                    sc->atu_dev.dv_xname));
        !           828:                return err;
        !           829:        }
        !           830:        if (status != STATUS_COMPLETE) {
        !           831:                DPRINTF(("%s: error joining... [status=%02x]\n",
        !           832:                    sc->atu_dev.dv_xname, status));
        !           833:                return status;
        !           834:        } else {
        !           835:                DPRINTFN(10, ("%s: joined BSS\n", sc->atu_dev.dv_xname));
        !           836:        }
        !           837:        return err;
        !           838: }
        !           839:
        !           840: /*
        !           841:  * Get the state of the DFU unit
        !           842:  */
        !           843: int8_t
        !           844: atu_get_dfu_state(struct atu_softc *sc)
        !           845: {
        !           846:        u_int8_t        state;
        !           847:
        !           848:        if (atu_usb_request(sc, DFU_GETSTATE, 0, 0, 1, &state))
        !           849:                return -1;
        !           850:        return state;
        !           851: }
        !           852:
        !           853: /*
        !           854:  * Get MAC opmode
        !           855:  */
        !           856: u_int8_t
        !           857: atu_get_opmode(struct atu_softc *sc, u_int8_t *mode)
        !           858: {
        !           859:
        !           860:        return atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33, 0x0001,
        !           861:            0x0000, 1, mode);
        !           862: }
        !           863:
        !           864: /*
        !           865:  * Upload the internal firmware into the device
        !           866:  */
        !           867: void
        !           868: atu_internal_firmware(void *arg)
        !           869: {
        !           870:        struct atu_softc *sc = arg;
        !           871:        u_char  state, *ptr = NULL, *firm = NULL, status[6];
        !           872:        int block_size, block = 0, err, i;
        !           873:        size_t  bytes_left = 0;
        !           874:        char    *name = "unknown-device";
        !           875:
        !           876:        /*
        !           877:         * Uploading firmware is done with the DFU (Device Firmware Upgrade)
        !           878:         * interface. See "Universal Serial Bus - Device Class Specification
        !           879:         * for Device Firmware Upgrade" pdf for details of the protocol.
        !           880:         * Maybe this could be moved to a seperate 'firmware driver' once more
        !           881:         * device drivers need it... For now we'll just do it here.
        !           882:         *
        !           883:         * Just for your information, the Atmel's DFU descriptor looks like
        !           884:         * this:
        !           885:         *
        !           886:         * 07           size
        !           887:         * 21           type
        !           888:         * 01           capabilities : only firmware download, need reset
        !           889:         *                after download
        !           890:         * 13 05        detach timeout : max 1299ms between DFU_DETACH and
        !           891:         *                reset
        !           892:         * 00 04        max bytes of firmware per transaction : 1024
        !           893:         */
        !           894:
        !           895:        /* Choose the right firmware for the device */
        !           896:        for (i = 0; i < sizeof(atu_radfirm)/sizeof(atu_radfirm[0]); i++)
        !           897:                if (sc->atu_radio == atu_radfirm[i].atur_type)
        !           898:                        name = atu_radfirm[i].atur_internal;
        !           899:
        !           900:        DPRINTF(("%s: loading firmware %s...\n",
        !           901:            sc->atu_dev.dv_xname, name));
        !           902:        err = loadfirmware(name, &firm, &bytes_left);
        !           903:        if (err != 0) {
        !           904:                printf("%s: %s loadfirmware error %d\n",
        !           905:                    sc->atu_dev.dv_xname, name, err);
        !           906:                return;
        !           907:        }
        !           908:
        !           909:        ptr = firm;
        !           910:        state = atu_get_dfu_state(sc);
        !           911:
        !           912:        while (block >= 0 && state > 0) {
        !           913:                switch (state) {
        !           914:                case DFUState_DnLoadSync:
        !           915:                        /* get DFU status */
        !           916:                        err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0 , 6,
        !           917:                            status);
        !           918:                        if (err) {
        !           919:                                DPRINTF(("%s: dfu_getstatus failed!\n",
        !           920:                                    sc->atu_dev.dv_xname));
        !           921:                                free(firm, M_DEVBUF);
        !           922:                                return;
        !           923:                        }
        !           924:                        /* success means state => DnLoadIdle */
        !           925:                        state = DFUState_DnLoadIdle;
        !           926:                        continue;
        !           927:                        break;
        !           928:
        !           929:                case DFUState_DFUIdle:
        !           930:                case DFUState_DnLoadIdle:
        !           931:                        if (bytes_left>=DFU_MaxBlockSize)
        !           932:                                block_size = DFU_MaxBlockSize;
        !           933:                        else
        !           934:                                block_size = bytes_left;
        !           935:                        DPRINTFN(15, ("%s: firmware block %d\n",
        !           936:                            sc->atu_dev.dv_xname, block));
        !           937:
        !           938:                        err = atu_usb_request(sc, DFU_DNLOAD, block++, 0,
        !           939:                            block_size, ptr);
        !           940:                        if (err) {
        !           941:                                DPRINTF(("%s: dfu_dnload failed\n",
        !           942:                                    sc->atu_dev.dv_xname));
        !           943:                                free(firm, M_DEVBUF);
        !           944:                                return;
        !           945:                        }
        !           946:
        !           947:                        ptr += block_size;
        !           948:                        bytes_left -= block_size;
        !           949:                        if (block_size == 0)
        !           950:                                block = -1;
        !           951:                        break;
        !           952:
        !           953:                default:
        !           954:                        DPRINTFN(20, ("%s: sleeping for a while\n",
        !           955:                            sc->atu_dev.dv_xname));
        !           956:                        usbd_delay_ms(sc->atu_udev, 100);
        !           957:                        break;
        !           958:                }
        !           959:
        !           960:                state = atu_get_dfu_state(sc);
        !           961:        }
        !           962:        free(firm, M_DEVBUF);
        !           963:
        !           964:        if (state != DFUState_ManifestSync) {
        !           965:                DPRINTF(("%s: state != manifestsync... eek!\n",
        !           966:                    sc->atu_dev.dv_xname));
        !           967:        }
        !           968:
        !           969:        err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, status);
        !           970:        if (err) {
        !           971:                DPRINTF(("%s: dfu_getstatus failed!\n",
        !           972:                    sc->atu_dev.dv_xname));
        !           973:                return;
        !           974:        }
        !           975:
        !           976:        DPRINTFN(15, ("%s: sending remap\n", sc->atu_dev.dv_xname));
        !           977:        err = atu_usb_request(sc, DFU_REMAP, 0, 0, 0, NULL);
        !           978:        if ((err) && (!ISSET(sc->atu_quirk, ATU_QUIRK_NO_REMAP))) {
        !           979:                DPRINTF(("%s: remap failed!\n", sc->atu_dev.dv_xname));
        !           980:                return;
        !           981:        }
        !           982:
        !           983:        /* after a lot of trying and measuring I found out the device needs
        !           984:         * about 56 miliseconds after sending the remap command before
        !           985:         * it's ready to communicate again. So we'll wait just a little bit
        !           986:         * longer than that to be sure...
        !           987:         */
        !           988:        usbd_delay_ms(sc->atu_udev, 56+100);
        !           989:
        !           990:        printf("%s: reattaching after firmware upload\n",
        !           991:            sc->atu_dev.dv_xname);
        !           992:        usb_needs_reattach(sc->atu_udev);
        !           993: }
        !           994:
        !           995: void
        !           996: atu_external_firmware(void *arg)
        !           997: {
        !           998:        struct atu_softc *sc = arg;
        !           999:        u_char  *ptr = NULL, *firm = NULL;
        !          1000:        int     block_size, block = 0, err, i;
        !          1001:        size_t  bytes_left = 0;
        !          1002:        char    *name = "unknown-device";
        !          1003:
        !          1004:        for (i = 0; i < sizeof(atu_radfirm)/sizeof(atu_radfirm[0]); i++)
        !          1005:                if (sc->atu_radio == atu_radfirm[i].atur_type)
        !          1006:                        name = atu_radfirm[i].atur_external;
        !          1007:
        !          1008:        DPRINTF(("%s: loading external firmware %s\n",
        !          1009:            sc->atu_dev.dv_xname, name));
        !          1010:        err = loadfirmware(name, &firm, &bytes_left);
        !          1011:        if (err != 0) {
        !          1012:                printf("%s: %s loadfirmware error %d\n",
        !          1013:                    sc->atu_dev.dv_xname, name, err);
        !          1014:                return;
        !          1015:        }
        !          1016:        ptr = firm;
        !          1017:
        !          1018:        while (bytes_left) {
        !          1019:                if (bytes_left > 1024)
        !          1020:                        block_size = 1024;
        !          1021:                else
        !          1022:                        block_size = bytes_left;
        !          1023:
        !          1024:                DPRINTFN(15, ("%s: block:%d size:%d\n",
        !          1025:                    sc->atu_dev.dv_xname, block, block_size));
        !          1026:                err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e,
        !          1027:                    0x0802, block, block_size, ptr);
        !          1028:                if (err) {
        !          1029:                        DPRINTF(("%s: could not load external firmware "
        !          1030:                            "block\n", sc->atu_dev.dv_xname));
        !          1031:                        free(firm, M_DEVBUF);
        !          1032:                        return;
        !          1033:                }
        !          1034:
        !          1035:                ptr += block_size;
        !          1036:                block++;
        !          1037:                bytes_left -= block_size;
        !          1038:        }
        !          1039:        free(firm, M_DEVBUF);
        !          1040:
        !          1041:        err = atu_usb_request(sc, UT_WRITE_VENDOR_DEVICE, 0x0e, 0x0802,
        !          1042:            block, 0, NULL);
        !          1043:        if (err) {
        !          1044:                DPRINTF(("%s: could not load last zero-length firmware "
        !          1045:                    "block\n", sc->atu_dev.dv_xname));
        !          1046:                return;
        !          1047:        }
        !          1048:
        !          1049:        /*
        !          1050:         * The SMC2662w V.4 seems to require some time to do its thing with
        !          1051:         * the external firmware... 20 ms isn't enough, but 21 ms works 100
        !          1052:         * times out of 100 tries. We'll wait a bit longer just to be sure
        !          1053:         */
        !          1054:        if (sc->atu_quirk & ATU_QUIRK_FW_DELAY)
        !          1055:                usbd_delay_ms(sc->atu_udev, 21 + 100);
        !          1056:
        !          1057:        DPRINTFN(10, ("%s: external firmware upload done\n",
        !          1058:            sc->atu_dev.dv_xname));
        !          1059:        /* complete configuration after the firmwares have been uploaded */
        !          1060:        atu_complete_attach(sc);
        !          1061: }
        !          1062:
        !          1063: int
        !          1064: atu_get_card_config(struct atu_softc *sc)
        !          1065: {
        !          1066:        struct ieee80211com             *ic = &sc->sc_ic;
        !          1067:        struct atu_rfmd_conf            rfmd_conf;
        !          1068:        struct atu_intersil_conf        intersil_conf;
        !          1069:        int                             err;
        !          1070:
        !          1071:        switch (sc->atu_radio) {
        !          1072:
        !          1073:        case RadioRFMD:
        !          1074:        case RadioRFMD2958:
        !          1075:        case RadioRFMD2958_SMC:
        !          1076:        case AT76C503_rfmd_acc:
        !          1077:        case AT76C505_rfmd:
        !          1078:                err = atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33,
        !          1079:                    0x0a02, 0x0000, sizeof(rfmd_conf),
        !          1080:                    (u_int8_t *)&rfmd_conf);
        !          1081:                if (err) {
        !          1082:                        DPRINTF(("%s: could not get rfmd config!\n",
        !          1083:                            sc->atu_dev.dv_xname));
        !          1084:                        return err;
        !          1085:                }
        !          1086:                memcpy(ic->ic_myaddr, rfmd_conf.MACAddr, IEEE80211_ADDR_LEN);
        !          1087:                break;
        !          1088:
        !          1089:        case RadioIntersil:
        !          1090:        case AT76C503_i3863:
        !          1091:                err = atu_usb_request(sc, UT_READ_VENDOR_INTERFACE, 0x33,
        !          1092:                    0x0902, 0x0000, sizeof(intersil_conf),
        !          1093:                    (u_int8_t *)&intersil_conf);
        !          1094:                if (err) {
        !          1095:                        DPRINTF(("%s: could not get intersil config!\n",
        !          1096:                            sc->atu_dev.dv_xname));
        !          1097:                        return err;
        !          1098:                }
        !          1099:                memcpy(ic->ic_myaddr, intersil_conf.MACAddr,
        !          1100:                    IEEE80211_ADDR_LEN);
        !          1101:                break;
        !          1102:        }
        !          1103:        return 0;
        !          1104: }
        !          1105:
        !          1106: /*
        !          1107:  * Probe for an AT76c503 chip.
        !          1108:  */
        !          1109: int
        !          1110: atu_match(struct device *parent, void *match, void *aux)
        !          1111: {
        !          1112:        struct usb_attach_arg   *uaa = aux;
        !          1113:        int                     i;
        !          1114:
        !          1115:        if (!uaa->iface)
        !          1116:                return(UMATCH_NONE);
        !          1117:
        !          1118:        for (i = 0; i < sizeof(atu_devs)/sizeof(atu_devs[0]); i++) {
        !          1119:                struct atu_type *t = &atu_devs[i];
        !          1120:
        !          1121:                if (uaa->vendor == t->atu_vid &&
        !          1122:                    uaa->product == t->atu_pid) {
        !          1123:                        return(UMATCH_VENDOR_PRODUCT);
        !          1124:                }
        !          1125:        }
        !          1126:        return(UMATCH_NONE);
        !          1127: }
        !          1128:
        !          1129: int
        !          1130: atu_media_change(struct ifnet *ifp)
        !          1131: {
        !          1132: #ifdef ATU_DEBUG
        !          1133:        struct atu_softc        *sc = ifp->if_softc;
        !          1134: #endif /* ATU_DEBUG */
        !          1135:        int                     err;
        !          1136:
        !          1137:        DPRINTFN(10, ("%s: atu_media_change\n", sc->atu_dev.dv_xname));
        !          1138:
        !          1139:        err = ieee80211_media_change(ifp);
        !          1140:        if (err == ENETRESET) {
        !          1141:                if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
        !          1142:                    (IFF_RUNNING|IFF_UP))
        !          1143:                        atu_init(ifp);
        !          1144:                err = 0;
        !          1145:        }
        !          1146:
        !          1147:        return (err);
        !          1148: }
        !          1149:
        !          1150: void
        !          1151: atu_media_status(struct ifnet *ifp, struct ifmediareq *req)
        !          1152: {
        !          1153: #ifdef ATU_DEBUG
        !          1154:        struct atu_softc        *sc = ifp->if_softc;
        !          1155: #endif /* ATU_DEBUG */
        !          1156:
        !          1157:        DPRINTFN(10, ("%s: atu_media_status\n", sc->atu_dev.dv_xname));
        !          1158:
        !          1159:        ieee80211_media_status(ifp, req);
        !          1160: }
        !          1161:
        !          1162: void
        !          1163: atu_task(void *arg)
        !          1164: {
        !          1165:        struct atu_softc        *sc = (struct atu_softc *)arg;
        !          1166:        struct ieee80211com     *ic = &sc->sc_ic;
        !          1167:        struct ifnet            *ifp = &ic->ic_if;
        !          1168:        usbd_status             err;
        !          1169:        int                     s;
        !          1170:
        !          1171:        DPRINTFN(10, ("%s: atu_task\n", sc->atu_dev.dv_xname));
        !          1172:
        !          1173:        if (sc->sc_state != ATU_S_OK)
        !          1174:                return;
        !          1175:
        !          1176:        switch (sc->sc_cmd) {
        !          1177:        case ATU_C_SCAN:
        !          1178:
        !          1179:                err = atu_start_scan(sc);
        !          1180:                if (err) {
        !          1181:                        DPRINTFN(1, ("%s: atu_init: couldn't start scan!\n",
        !          1182:                            sc->atu_dev.dv_xname));
        !          1183:                        return;
        !          1184:                }
        !          1185:
        !          1186:                err = atu_wait_completion(sc, CMD_START_SCAN, NULL);
        !          1187:                if (err) {
        !          1188:                        DPRINTF(("%s: atu_init: error waiting for scan\n",
        !          1189:                            sc->atu_dev.dv_xname));
        !          1190:                        return;
        !          1191:                }
        !          1192:
        !          1193:                DPRINTF(("%s: ==========================> END OF SCAN!\n",
        !          1194:                    sc->atu_dev.dv_xname));
        !          1195:
        !          1196:                s = splnet();
        !          1197:                /* ieee80211_next_scan(ifp); */
        !          1198:                ieee80211_end_scan(ifp);
        !          1199:                splx(s);
        !          1200:
        !          1201:                DPRINTF(("%s: ----------------------======> END OF SCAN2!\n",
        !          1202:                    sc->atu_dev.dv_xname));
        !          1203:                break;
        !          1204:
        !          1205:        case ATU_C_JOIN:
        !          1206:                atu_join(sc, ic->ic_bss);
        !          1207:        }
        !          1208: }
        !          1209:
        !          1210: int
        !          1211: atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        !          1212: {
        !          1213:        struct ifnet            *ifp = &ic->ic_if;
        !          1214:        struct atu_softc        *sc = ifp->if_softc;
        !          1215:        enum ieee80211_state    ostate = ic->ic_state;
        !          1216:
        !          1217:        DPRINTFN(10, ("%s: atu_newstate: %s -> %s\n", sc->atu_dev.dv_xname,
        !          1218:            ieee80211_state_name[ostate], ieee80211_state_name[nstate]));
        !          1219:
        !          1220:        switch (nstate) {
        !          1221:        case IEEE80211_S_SCAN:
        !          1222:                memcpy(ic->ic_chan_scan, ic->ic_chan_active,
        !          1223:                    sizeof(ic->ic_chan_active));
        !          1224:                ieee80211_free_allnodes(ic);
        !          1225:
        !          1226:                /* tell the event thread that we want a scan */
        !          1227:                sc->sc_cmd = ATU_C_SCAN;
        !          1228:                usb_add_task(sc->atu_udev, &sc->sc_task);
        !          1229:
        !          1230:                /* handle this ourselves */
        !          1231:                ic->ic_state = nstate;
        !          1232:                return (0);
        !          1233:
        !          1234:        case IEEE80211_S_AUTH:
        !          1235:        case IEEE80211_S_RUN:
        !          1236:                if (ostate == IEEE80211_S_SCAN) {
        !          1237:                        sc->sc_cmd = ATU_C_JOIN;
        !          1238:                        usb_add_task(sc->atu_udev, &sc->sc_task);
        !          1239:                }
        !          1240:                break;
        !          1241:        default:
        !          1242:                /* nothing to do */
        !          1243:                break;
        !          1244:        }
        !          1245:
        !          1246:        return (*sc->sc_newstate)(ic, nstate, arg);
        !          1247: }
        !          1248:
        !          1249: /*
        !          1250:  * Attach the interface. Allocate softc structures, do
        !          1251:  * setup and ethernet/BPF attach.
        !          1252:  */
        !          1253: void
        !          1254: atu_attach(struct device *parent, struct device *self, void *aux)
        !          1255: {
        !          1256:        struct atu_softc                *sc = (struct atu_softc *)self;
        !          1257:        struct usb_attach_arg           *uaa = aux;
        !          1258:        char                            *devinfop;
        !          1259:        usbd_status                     err;
        !          1260:        usbd_device_handle              dev = uaa->device;
        !          1261:        u_int8_t                        mode, channel;
        !          1262:        int i;
        !          1263:
        !          1264:        sc->sc_state = ATU_S_UNCONFIG;
        !          1265:
        !          1266:        devinfop = usbd_devinfo_alloc(dev, 0);
        !          1267:        printf("\n%s: %s", sc->atu_dev.dv_xname, devinfop);
        !          1268:        usbd_devinfo_free(devinfop);
        !          1269:
        !          1270:        err = usbd_set_config_no(dev, ATU_CONFIG_NO, 1);
        !          1271:        if (err) {
        !          1272:                printf("%s: setting config no failed\n",
        !          1273:                    sc->atu_dev.dv_xname);
        !          1274:                return;
        !          1275:        }
        !          1276:
        !          1277:        err = usbd_device2interface_handle(dev, ATU_IFACE_IDX, &sc->atu_iface);
        !          1278:        if (err) {
        !          1279:                printf("%s: getting interface handle failed\n",
        !          1280:                    sc->atu_dev.dv_xname);
        !          1281:                return;
        !          1282:        }
        !          1283:
        !          1284:        sc->atu_unit = self->dv_unit;
        !          1285:        sc->atu_udev = dev;
        !          1286:
        !          1287:        /*
        !          1288:         * look up the radio_type for the device
        !          1289:         * basically does the same as USB_MATCH
        !          1290:         */
        !          1291:        for (i = 0; i < sizeof(atu_devs)/sizeof(atu_devs[0]); i++) {
        !          1292:                struct atu_type *t = &atu_devs[i];
        !          1293:
        !          1294:                if (uaa->vendor == t->atu_vid &&
        !          1295:                    uaa->product == t->atu_pid) {
        !          1296:                        sc->atu_radio = t->atu_radio;
        !          1297:                        sc->atu_quirk = t->atu_quirk;
        !          1298:                }
        !          1299:        }
        !          1300:
        !          1301:        /*
        !          1302:         * Check in the interface descriptor if we're in DFU mode
        !          1303:         * If we're in DFU mode, we upload the external firmware
        !          1304:         * If we're not, the PC must have rebooted without power-cycling
        !          1305:         * the device.. I've tried this out, a reboot only requeres the
        !          1306:         * external firmware to be reloaded :)
        !          1307:         *
        !          1308:         * Hmm. The at76c505a doesn't report a DFU descriptor when it's
        !          1309:         * in DFU mode... Let's just try to get the opmode
        !          1310:         */
        !          1311:        err = atu_get_opmode(sc, &mode);
        !          1312:        DPRINTFN(20, ("%s: opmode: %d\n", sc->atu_dev.dv_xname, mode));
        !          1313:        if (err || (mode != MODE_NETCARD && mode != MODE_NOFLASHNETCARD)) {
        !          1314:                DPRINTF(("%s: starting internal firmware download\n",
        !          1315:                    sc->atu_dev.dv_xname));
        !          1316:
        !          1317:                printf("\n");
        !          1318:
        !          1319:                if (rootvp == NULL)
        !          1320:                        mountroothook_establish(atu_internal_firmware, sc);
        !          1321:                else
        !          1322:                        atu_internal_firmware(sc);
        !          1323:                /*
        !          1324:                 * atu_internal_firmware will cause a reset of the device
        !          1325:                 * so we don't want to do any more configuration after this
        !          1326:                 * point.
        !          1327:                 */
        !          1328:                return;
        !          1329:        }
        !          1330:
        !          1331:        uaa->iface = sc->atu_iface;
        !          1332:
        !          1333:        if (mode != MODE_NETCARD) {
        !          1334:                DPRINTFN(15, ("%s: device needs external firmware\n",
        !          1335:                    sc->atu_dev.dv_xname));
        !          1336:
        !          1337:                if (mode != MODE_NOFLASHNETCARD) {
        !          1338:                        DPRINTF(("%s: EEK! unexpected opmode=%d\n",
        !          1339:                            sc->atu_dev.dv_xname, mode));
        !          1340:                }
        !          1341:
        !          1342:                /*
        !          1343:                 * There is no difference in opmode before and after external
        !          1344:                 * firmware upload with the SMC2662 V.4 . So instead we'll try
        !          1345:                 * to read the channel number. If we succeed, external
        !          1346:                 * firmwaremust have been already uploaded...
        !          1347:                 */
        !          1348:                if (sc->atu_radio != RadioIntersil) {
        !          1349:                        err = atu_get_mib(sc, MIB_PHY__CHANNEL, &channel);
        !          1350:                        if (!err) {
        !          1351:                                DPRINTF(("%s: external firmware has already"
        !          1352:                                    " been downloaded\n",
        !          1353:                                    sc->atu_dev.dv_xname));
        !          1354:                                atu_complete_attach(sc);
        !          1355:                                return;
        !          1356:                        }
        !          1357:                }
        !          1358:
        !          1359:                if (rootvp == NULL)
        !          1360:                        mountroothook_establish(atu_external_firmware, sc);
        !          1361:                else
        !          1362:                        atu_external_firmware(sc);
        !          1363:
        !          1364:                /*
        !          1365:                 * atu_external_firmware will call atu_complete_attach after
        !          1366:                 * it's finished so we can just return.
        !          1367:                 */
        !          1368:        } else {
        !          1369:                /* all the firmwares are in place, so complete the attach */
        !          1370:                atu_complete_attach(sc);
        !          1371:        }
        !          1372: }
        !          1373:
        !          1374: void
        !          1375: atu_complete_attach(struct atu_softc *sc)
        !          1376: {
        !          1377:        struct ieee80211com             *ic = &sc->sc_ic;
        !          1378:        struct ifnet                    *ifp = &ic->ic_if;
        !          1379:        usb_interface_descriptor_t      *id;
        !          1380:        usb_endpoint_descriptor_t       *ed;
        !          1381:        usbd_status                     err;
        !          1382:        int                             i;
        !          1383: #ifdef ATU_DEBUG
        !          1384:        struct atu_fw                   fw;
        !          1385: #endif
        !          1386:
        !          1387:        id = usbd_get_interface_descriptor(sc->atu_iface);
        !          1388:
        !          1389:        /* Find endpoints. */
        !          1390:        for (i = 0; i < id->bNumEndpoints; i++) {
        !          1391:                ed = usbd_interface2endpoint_descriptor(sc->atu_iface, i);
        !          1392:                if (!ed) {
        !          1393:                        DPRINTF(("%s: num_endp:%d\n", sc->atu_dev.dv_xname,
        !          1394:                            sc->atu_iface->idesc->bNumEndpoints));
        !          1395:                        DPRINTF(("%s: couldn't get ep %d\n",
        !          1396:                            sc->atu_dev.dv_xname, i));
        !          1397:                        return;
        !          1398:                }
        !          1399:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
        !          1400:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
        !          1401:                        sc->atu_ed[ATU_ENDPT_RX] = ed->bEndpointAddress;
        !          1402:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
        !          1403:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
        !          1404:                        sc->atu_ed[ATU_ENDPT_TX] = ed->bEndpointAddress;
        !          1405:                }
        !          1406:        }
        !          1407:
        !          1408:        /* read device config & get MAC address */
        !          1409:        err = atu_get_card_config(sc);
        !          1410:        if (err) {
        !          1411:                printf("\n%s: could not get card cfg!\n",
        !          1412:                    sc->atu_dev.dv_xname);
        !          1413:                return;
        !          1414:        }
        !          1415:
        !          1416: #ifdef ATU_DEBUG
        !          1417:        /* DEBUG : try to get firmware version */
        !          1418:        err = atu_get_mib(sc, MIB_FW_VERSION, sizeof(fw), 0,
        !          1419:            (u_int8_t *)&fw);
        !          1420:        if (!err) {
        !          1421:                DPRINTFN(15, ("%s: firmware: maj:%d min:%d patch:%d "
        !          1422:                    "build:%d\n", sc->atu_dev.dv_xname, fw.major, fw.minor,
        !          1423:                    fw.patch, fw.build));
        !          1424:        } else {
        !          1425:                DPRINTF(("%s: get firmware version failed\n",
        !          1426:                    sc->atu_dev.dv_xname));
        !          1427:        }
        !          1428: #endif /* ATU_DEBUG */
        !          1429:
        !          1430:        /* Show the world our MAC address */
        !          1431:        printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
        !          1432:
        !          1433:        sc->atu_cdata.atu_tx_inuse = 0;
        !          1434:
        !          1435:        bzero(sc->atu_bssid, ETHER_ADDR_LEN);
        !          1436:        sc->atu_channel = ATU_DEFAULT_CHANNEL;
        !          1437:        sc->atu_desired_channel = IEEE80211_CHAN_ANY;
        !          1438:        sc->atu_mode = INFRASTRUCTURE_MODE;
        !          1439:
        !          1440:        ic->ic_softc = sc;
        !          1441:        ic->ic_phytype = IEEE80211_T_DS;
        !          1442:        ic->ic_opmode = IEEE80211_M_STA;
        !          1443:        ic->ic_state = IEEE80211_S_INIT;
        !          1444:        ic->ic_caps = IEEE80211_C_IBSS | IEEE80211_C_WEP | IEEE80211_C_SCANALL;
        !          1445:        ic->ic_max_rssi = atu_radfirm[sc->atu_radio].max_rssi;
        !          1446:
        !          1447:        ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
        !          1448:
        !          1449:        for (i = 1; i <= 14; i++) {
        !          1450:                ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B |
        !          1451:                    IEEE80211_CHAN_PASSIVE;
        !          1452:                ic->ic_channels[i].ic_freq = ieee80211_ieee2mhz(i,
        !          1453:                    ic->ic_channels[i].ic_flags);
        !          1454:        }
        !          1455:
        !          1456:        ic->ic_ibss_chan = &ic->ic_channels[0];
        !          1457:
        !          1458:        ifp->if_softc = sc;
        !          1459:        memcpy(ifp->if_xname, sc->atu_dev.dv_xname, IFNAMSIZ);
        !          1460:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !          1461:        ifp->if_start = atu_start;
        !          1462:        ifp->if_ioctl = atu_ioctl;
        !          1463:        ifp->if_watchdog = atu_watchdog;
        !          1464:        ifp->if_mtu = ATU_DEFAULT_MTU;
        !          1465:        IFQ_SET_READY(&ifp->if_snd);
        !          1466:
        !          1467:        /* Call MI attach routine. */
        !          1468:        if_attach(ifp);
        !          1469:        ieee80211_ifattach(ifp);
        !          1470:
        !          1471:        sc->sc_newstate = ic->ic_newstate;
        !          1472:        ic->ic_newstate = atu_newstate;
        !          1473:
        !          1474:        /* setup ifmedia interface */
        !          1475:        ieee80211_media_init(ifp, atu_media_change, atu_media_status);
        !          1476:
        !          1477:        usb_init_task(&sc->sc_task, atu_task, sc);
        !          1478:
        !          1479: #if NBPFILTER > 0
        !          1480:        bpfattach(&sc->sc_radiobpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
        !          1481:            sizeof(struct ieee80211_frame) + 64);
        !          1482:
        !          1483:        bzero(&sc->sc_rxtapu, sizeof(sc->sc_rxtapu));
        !          1484:        sc->sc_rxtap.rr_ihdr.it_len = sizeof(sc->sc_rxtapu);
        !          1485:        sc->sc_rxtap.rr_ihdr.it_present = htole32(ATU_RX_RADIOTAP_PRESENT);
        !          1486:
        !          1487:        bzero(&sc->sc_txtapu, sizeof(sc->sc_txtapu));
        !          1488:        sc->sc_txtap.rt_ihdr.it_len = sizeof(sc->sc_txtapu);
        !          1489:        sc->sc_txtap.rt_ihdr.it_present = htole32(ATU_TX_RADIOTAP_PRESENT);
        !          1490: #endif
        !          1491:
        !          1492:        sc->sc_state = ATU_S_OK;
        !          1493: }
        !          1494:
        !          1495: int
        !          1496: atu_detach(struct device *self, int flags)
        !          1497: {
        !          1498:        struct atu_softc        *sc = (struct atu_softc *)self;
        !          1499:        struct ifnet            *ifp = &sc->sc_ic.ic_if;
        !          1500:
        !          1501:        DPRINTFN(10, ("%s: atu_detach state=%d\n", sc->atu_dev.dv_xname,
        !          1502:            sc->sc_state));
        !          1503:
        !          1504:        if (sc->sc_state != ATU_S_UNCONFIG) {
        !          1505:                atu_stop(ifp, 1);
        !          1506:                ieee80211_ifdetach(ifp);
        !          1507:                if_detach(ifp);
        !          1508:
        !          1509:                if (sc->atu_ep[ATU_ENDPT_TX] != NULL)
        !          1510:                        usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_TX]);
        !          1511:                if (sc->atu_ep[ATU_ENDPT_RX] != NULL)
        !          1512:                        usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_RX]);
        !          1513:
        !          1514:                usb_rem_task(sc->atu_udev, &sc->sc_task);
        !          1515:        }
        !          1516:
        !          1517:        return(0);
        !          1518: }
        !          1519:
        !          1520: int
        !          1521: atu_activate(struct device *self, enum devact act)
        !          1522: {
        !          1523:        struct atu_softc *sc = (struct atu_softc *)self;
        !          1524:
        !          1525:        switch (act) {
        !          1526:        case DVACT_ACTIVATE:
        !          1527:                break;
        !          1528:        case DVACT_DEACTIVATE:
        !          1529:                if (sc->sc_state != ATU_S_UNCONFIG)
        !          1530:                        sc->sc_state = ATU_S_DEAD;
        !          1531:                break;
        !          1532:        }
        !          1533:        return (0);
        !          1534: }
        !          1535:
        !          1536: /*
        !          1537:  * Initialize an RX descriptor and attach an MBUF cluster.
        !          1538:  */
        !          1539: int
        !          1540: atu_newbuf(struct atu_softc *sc, struct atu_chain *c, struct mbuf *m)
        !          1541: {
        !          1542:        struct mbuf             *m_new = NULL;
        !          1543:
        !          1544:        if (m == NULL) {
        !          1545:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !          1546:                if (m_new == NULL) {
        !          1547:                        DPRINTF(("%s: no memory for rx list\n",
        !          1548:                            sc->atu_dev.dv_xname));
        !          1549:                        return(ENOBUFS);
        !          1550:                }
        !          1551:
        !          1552:                MCLGET(m_new, M_DONTWAIT);
        !          1553:                if (!(m_new->m_flags & M_EXT)) {
        !          1554:                        DPRINTF(("%s: no memory for rx list\n",
        !          1555:                            sc->atu_dev.dv_xname));
        !          1556:                        m_freem(m_new);
        !          1557:                        return(ENOBUFS);
        !          1558:                }
        !          1559:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
        !          1560:        } else {
        !          1561:                m_new = m;
        !          1562:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
        !          1563:                m_new->m_data = m_new->m_ext.ext_buf;
        !          1564:        }
        !          1565:        c->atu_mbuf = m_new;
        !          1566:        return(0);
        !          1567: }
        !          1568:
        !          1569: int
        !          1570: atu_rx_list_init(struct atu_softc *sc)
        !          1571: {
        !          1572:        struct atu_cdata        *cd = &sc->atu_cdata;
        !          1573:        struct atu_chain        *c;
        !          1574:        int                     i;
        !          1575:
        !          1576:        DPRINTFN(15, ("%s: atu_rx_list_init: enter\n",
        !          1577:            sc->atu_dev.dv_xname));
        !          1578:
        !          1579:        for (i = 0; i < ATU_RX_LIST_CNT; i++) {
        !          1580:                c = &cd->atu_rx_chain[i];
        !          1581:                c->atu_sc = sc;
        !          1582:                c->atu_idx = i;
        !          1583:                if (c->atu_xfer == NULL) {
        !          1584:                        c->atu_xfer = usbd_alloc_xfer(sc->atu_udev);
        !          1585:                        if (c->atu_xfer == NULL)
        !          1586:                                return (ENOBUFS);
        !          1587:                        c->atu_buf = usbd_alloc_buffer(c->atu_xfer,
        !          1588:                            ATU_RX_BUFSZ);
        !          1589:                        if (c->atu_buf == NULL) /* XXX free xfer */
        !          1590:                                return (ENOBUFS);
        !          1591:                        if (atu_newbuf(sc, c, NULL) == ENOBUFS) /* XXX free? */
        !          1592:                                return(ENOBUFS);
        !          1593:                }
        !          1594:        }
        !          1595:        return (0);
        !          1596: }
        !          1597:
        !          1598: int
        !          1599: atu_tx_list_init(struct atu_softc *sc)
        !          1600: {
        !          1601:        struct atu_cdata        *cd = &sc->atu_cdata;
        !          1602:        struct atu_chain        *c;
        !          1603:        int                     i;
        !          1604:
        !          1605:        DPRINTFN(15, ("%s: atu_tx_list_init\n",
        !          1606:            sc->atu_dev.dv_xname));
        !          1607:
        !          1608:        SLIST_INIT(&cd->atu_tx_free);
        !          1609:        sc->atu_cdata.atu_tx_inuse = 0;
        !          1610:
        !          1611:        for (i = 0; i < ATU_TX_LIST_CNT; i++) {
        !          1612:                c = &cd->atu_tx_chain[i];
        !          1613:                c->atu_sc = sc;
        !          1614:                c->atu_idx = i;
        !          1615:                if (c->atu_xfer == NULL) {
        !          1616:                        c->atu_xfer = usbd_alloc_xfer(sc->atu_udev);
        !          1617:                        if (c->atu_xfer == NULL)
        !          1618:                                return(ENOBUFS);
        !          1619:                        c->atu_mbuf = NULL;
        !          1620:                        c->atu_buf = usbd_alloc_buffer(c->atu_xfer,
        !          1621:                            ATU_TX_BUFSZ);
        !          1622:                        if (c->atu_buf == NULL)
        !          1623:                                return(ENOBUFS); /* XXX free xfer */
        !          1624:                        SLIST_INSERT_HEAD(&cd->atu_tx_free, c, atu_list);
        !          1625:                }
        !          1626:        }
        !          1627:        return(0);
        !          1628: }
        !          1629:
        !          1630: void
        !          1631: atu_xfer_list_free(struct atu_softc *sc, struct atu_chain *ch,
        !          1632:     int listlen)
        !          1633: {
        !          1634:        int                     i;
        !          1635:
        !          1636:        /* Free resources. */
        !          1637:        for (i = 0; i < listlen; i++) {
        !          1638:                if (ch[i].atu_buf != NULL)
        !          1639:                        ch[i].atu_buf = NULL;
        !          1640:                if (ch[i].atu_mbuf != NULL) {
        !          1641:                        m_freem(ch[i].atu_mbuf);
        !          1642:                        ch[i].atu_mbuf = NULL;
        !          1643:                }
        !          1644:                if (ch[i].atu_xfer != NULL) {
        !          1645:                        usbd_free_xfer(ch[i].atu_xfer);
        !          1646:                        ch[i].atu_xfer = NULL;
        !          1647:                }
        !          1648:        }
        !          1649: }
        !          1650:
        !          1651: /*
        !          1652:  * A frame has been uploaded: pass the resulting mbuf chain up to
        !          1653:  * the higher level protocols.
        !          1654:  */
        !          1655: void
        !          1656: atu_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        !          1657: {
        !          1658:        struct atu_chain        *c = (struct atu_chain *)priv;
        !          1659:        struct atu_softc        *sc = c->atu_sc;
        !          1660:        struct ieee80211com     *ic = &sc->sc_ic;
        !          1661:        struct ifnet            *ifp = &ic->ic_if;
        !          1662:        struct atu_rx_hdr       *h;
        !          1663:        struct ieee80211_frame  *wh;
        !          1664:        struct ieee80211_node   *ni;
        !          1665:        struct mbuf             *m;
        !          1666:        u_int32_t               len;
        !          1667:        int                     s;
        !          1668:
        !          1669:        DPRINTFN(25, ("%s: atu_rxeof\n", sc->atu_dev.dv_xname));
        !          1670:
        !          1671:        if (sc->sc_state != ATU_S_OK)
        !          1672:                return;
        !          1673:
        !          1674:        if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
        !          1675:                goto done;
        !          1676:
        !          1677:        if (status != USBD_NORMAL_COMPLETION) {
        !          1678:                DPRINTF(("%s: status != USBD_NORMAL_COMPLETION\n",
        !          1679:                    sc->atu_dev.dv_xname));
        !          1680:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
        !          1681:                        return;
        !          1682:                }
        !          1683: #if 0
        !          1684:                if (status == USBD_IOERROR) {
        !          1685:                        DPRINTF(("%s: rx: EEK! lost device?\n",
        !          1686:                            sc->atu_dev.dv_xname));
        !          1687:
        !          1688:                        /*
        !          1689:                         * My experience with USBD_IOERROR is that trying to
        !          1690:                         * restart the transfer will always fail and we'll
        !          1691:                         * keep on looping restarting transfers untill someone
        !          1692:                         * pulls the plug of the device.
        !          1693:                         * So we don't restart the transfer, but just let it
        !          1694:                         * die... If someone knows of a situation where we can
        !          1695:                         * recover from USBD_IOERROR, let me know.
        !          1696:                         */
        !          1697:                        splx(s);
        !          1698:                        return;
        !          1699:                }
        !          1700: #endif /* 0 */
        !          1701:
        !          1702:                if (usbd_ratecheck(&sc->atu_rx_notice)) {
        !          1703:                        DPRINTF(("%s: usb error on rx: %s\n",
        !          1704:                            sc->atu_dev.dv_xname, usbd_errstr(status)));
        !          1705:                }
        !          1706:                if (status == USBD_STALLED)
        !          1707:                        usbd_clear_endpoint_stall_async(
        !          1708:                            sc->atu_ep[ATU_ENDPT_RX]);
        !          1709:                goto done;
        !          1710:        }
        !          1711:
        !          1712:        usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
        !          1713:
        !          1714:        if (len <= 1) {
        !          1715:                DPRINTF(("%s: atu_rxeof: too short\n",
        !          1716:                    sc->atu_dev.dv_xname));
        !          1717:                goto done;
        !          1718:        }
        !          1719:
        !          1720:        h = (struct atu_rx_hdr *)c->atu_buf;
        !          1721:        len = UGETW(h->length) - 4; /* XXX magic number */
        !          1722:
        !          1723:        m = c->atu_mbuf;
        !          1724:        memcpy(mtod(m, char *), c->atu_buf + ATU_RX_HDRLEN, len);
        !          1725:        m->m_pkthdr.rcvif = ifp;
        !          1726:        m->m_pkthdr.len = m->m_len = len;
        !          1727:
        !          1728:        wh = mtod(m, struct ieee80211_frame *);
        !          1729:        ni = ieee80211_find_rxnode(ic, wh);
        !          1730:
        !          1731:        ifp->if_ipackets++;
        !          1732:
        !          1733:        s = splnet();
        !          1734:
        !          1735:        if (atu_newbuf(sc, c, NULL) == ENOBUFS) {
        !          1736:                ifp->if_ierrors++;
        !          1737:                goto done1; /* XXX if we can't allocate, why restart it? */
        !          1738:        }
        !          1739:
        !          1740: #if NBPFILTER > 0
        !          1741:        if (sc->sc_radiobpf != NULL) {
        !          1742:                struct mbuf mb;
        !          1743:                struct atu_rx_radiotap_header *rr = &sc->sc_rxtap;
        !          1744:
        !          1745:                rr->rr_flags = 0;
        !          1746:                rr->rr_chan_freq =
        !          1747:                    htole16(ic->ic_bss->ni_chan->ic_freq);
        !          1748:                rr->rr_chan_flags =
        !          1749:                    htole16(ic->ic_bss->ni_chan->ic_flags);
        !          1750:                rr->rr_rssi = h->rssi;
        !          1751:                rr->rr_max_rssi = ic->ic_max_rssi;
        !          1752:
        !          1753:                mb.m_data = (caddr_t)rr;
        !          1754:                mb.m_len = sizeof(sc->sc_txtapu);
        !          1755:                mb.m_next = m;
        !          1756:                mb.m_nextpkt = NULL;
        !          1757:                mb.m_type = 0;
        !          1758:                mb.m_flags = 0;
        !          1759:                bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
        !          1760:        }
        !          1761: #endif /* NPBFILTER > 0 */
        !          1762:
        !          1763:        if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
        !          1764:                /*
        !          1765:                 * WEP is decrypted by hardware. Clear WEP bit
        !          1766:                 * header for ieee80211_input().
        !          1767:                 */
        !          1768:                wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
        !          1769:        }
        !          1770:
        !          1771:        ieee80211_input(ifp, m, ni, h->rssi, UGETDW(h->rx_time));
        !          1772:
        !          1773:        ieee80211_release_node(ic, ni);
        !          1774: done1:
        !          1775:        splx(s);
        !          1776: done:
        !          1777:        /* Setup new transfer. */
        !          1778:        usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_RX], c, c->atu_buf,
        !          1779:            ATU_RX_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
        !          1780:                atu_rxeof);
        !          1781:        usbd_transfer(c->atu_xfer);
        !          1782: }
        !          1783:
        !          1784: /*
        !          1785:  * A frame was downloaded to the chip. It's safe for us to clean up
        !          1786:  * the list buffers.
        !          1787:  */
        !          1788: void
        !          1789: atu_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        !          1790: {
        !          1791:        struct atu_chain        *c = (struct atu_chain *)priv;
        !          1792:        struct atu_softc        *sc = c->atu_sc;
        !          1793:        struct ifnet            *ifp = &sc->sc_ic.ic_if;
        !          1794:        usbd_status             err;
        !          1795:        int                     s;
        !          1796:
        !          1797:        DPRINTFN(25, ("%s: atu_txeof status=%d\n", sc->atu_dev.dv_xname,
        !          1798:            status));
        !          1799:
        !          1800:        if (c->atu_mbuf != NULL) {
        !          1801:                m_freem(c->atu_mbuf);
        !          1802:                c->atu_mbuf = NULL;
        !          1803:        }
        !          1804:
        !          1805:        if (status != USBD_NORMAL_COMPLETION) {
        !          1806:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
        !          1807:                        return;
        !          1808:
        !          1809:                DPRINTF(("%s: usb error on tx: %s\n", sc->atu_dev.dv_xname,
        !          1810:                    usbd_errstr(status)));
        !          1811:                if (status == USBD_STALLED)
        !          1812:                        usbd_clear_endpoint_stall_async(sc->atu_ep[ATU_ENDPT_TX]);
        !          1813:                return;
        !          1814:        }
        !          1815:
        !          1816:        usbd_get_xfer_status(c->atu_xfer, NULL, NULL, NULL, &err);
        !          1817:
        !          1818:        if (err)
        !          1819:                ifp->if_oerrors++;
        !          1820:        else
        !          1821:                ifp->if_opackets++;
        !          1822:
        !          1823:        s = splnet();
        !          1824:        SLIST_INSERT_HEAD(&sc->atu_cdata.atu_tx_free, c, atu_list);
        !          1825:        sc->atu_cdata.atu_tx_inuse--;
        !          1826:        if (sc->atu_cdata.atu_tx_inuse == 0)
        !          1827:                ifp->if_timer = 0;
        !          1828:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1829:        splx(s);
        !          1830:
        !          1831:        atu_start(ifp);
        !          1832: }
        !          1833:
        !          1834: u_int8_t
        !          1835: atu_calculate_padding(int size)
        !          1836: {
        !          1837:        size %= 64;
        !          1838:
        !          1839:        if (size < 50)
        !          1840:                return (50 - size);
        !          1841:        if (size >=61)
        !          1842:                return (64 + 50 - size);
        !          1843:        return (0);
        !          1844: }
        !          1845:
        !          1846: int
        !          1847: atu_tx_start(struct atu_softc *sc, struct ieee80211_node *ni,
        !          1848:     struct atu_chain *c, struct mbuf *m)
        !          1849: {
        !          1850:        int                     len;
        !          1851:        struct atu_tx_hdr       *h;
        !          1852:        usbd_status             err;
        !          1853:        u_int8_t                pad;
        !          1854: #if NBPFILTER > 0
        !          1855:        struct ieee80211com *ic = &sc->sc_ic;
        !          1856: #endif
        !          1857:
        !          1858:        DPRINTFN(25, ("%s: atu_tx_start\n", sc->atu_dev.dv_xname));
        !          1859:
        !          1860:        /* Don't try to send when we're shutting down the driver */
        !          1861:        if (sc->sc_state != ATU_S_OK) {
        !          1862:                m_freem(m);
        !          1863:                return(EIO);
        !          1864:        }
        !          1865:
        !          1866: #if NBPFILTER > 0
        !          1867:        if (sc->sc_radiobpf != NULL) {
        !          1868:                struct mbuf mb;
        !          1869:                struct atu_tx_radiotap_header *rt = &sc->sc_txtap;
        !          1870:
        !          1871:                rt->rt_flags = 0;
        !          1872:                rt->rt_chan_freq =
        !          1873:                    htole16(ic->ic_bss->ni_chan->ic_freq);
        !          1874:                rt->rt_chan_flags =
        !          1875:                    htole16(ic->ic_bss->ni_chan->ic_flags);
        !          1876:
        !          1877:                mb.m_data = (caddr_t)rt;
        !          1878:                mb.m_len = sizeof(sc->sc_txtapu);
        !          1879:                mb.m_next = m;
        !          1880:                mb.m_nextpkt = NULL;
        !          1881:                mb.m_type = 0;
        !          1882:                mb.m_flags = 0;
        !          1883:                bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
        !          1884:        }
        !          1885: #endif
        !          1886:
        !          1887:        /*
        !          1888:         * Copy the mbuf data into a contiguous buffer, leaving
        !          1889:         * enough room for the atmel headers
        !          1890:         */
        !          1891:        len = m->m_pkthdr.len;
        !          1892:
        !          1893:        m_copydata(m, 0, m->m_pkthdr.len, c->atu_buf + ATU_TX_HDRLEN);
        !          1894:
        !          1895:        h = (struct atu_tx_hdr *)c->atu_buf;
        !          1896:        memset(h, 0, ATU_TX_HDRLEN);
        !          1897:        USETW(h->length, len);
        !          1898:        h->tx_rate = 4; /* XXX rate = auto */
        !          1899:        len += ATU_TX_HDRLEN;
        !          1900:
        !          1901:        pad = atu_calculate_padding(len);
        !          1902:        len += pad;
        !          1903:        h->padding = pad;
        !          1904:
        !          1905:        c->atu_length = len;
        !          1906:        c->atu_mbuf = m;
        !          1907:
        !          1908:        usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_TX],
        !          1909:            c, c->atu_buf, c->atu_length, USBD_NO_COPY, ATU_TX_TIMEOUT,
        !          1910:            atu_txeof);
        !          1911:
        !          1912:        /* Let's get this thing into the air! */
        !          1913:        c->atu_in_xfer = 1;
        !          1914:        err = usbd_transfer(c->atu_xfer);
        !          1915:        if (err != USBD_IN_PROGRESS) {
        !          1916:                DPRINTFN(25, ("%s: atu_tx_start: err=%d\n",
        !          1917:                    sc->atu_dev.dv_xname, err));
        !          1918:                c->atu_mbuf = NULL;
        !          1919:                m_freem(m);
        !          1920:                return(EIO);
        !          1921:        }
        !          1922:
        !          1923:        return (0);
        !          1924: }
        !          1925:
        !          1926: void
        !          1927: atu_start(struct ifnet *ifp)
        !          1928: {
        !          1929:        struct atu_softc        *sc = ifp->if_softc;
        !          1930:        struct ieee80211com     *ic = &sc->sc_ic;
        !          1931:        struct atu_cdata        *cd = &sc->atu_cdata;
        !          1932:        struct ieee80211_node   *ni;
        !          1933:        struct ieee80211_frame  *wh;
        !          1934:        struct atu_chain        *c;
        !          1935:        struct mbuf             *m = NULL;
        !          1936:        int                     s;
        !          1937:
        !          1938:        DPRINTFN(25, ("%s: atu_start: enter\n", sc->atu_dev.dv_xname));
        !          1939:
        !          1940:        if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP)) {
        !          1941:                DPRINTFN(30, ("%s: atu_start: not running or up\n",
        !          1942:                    sc->atu_dev.dv_xname));
        !          1943:                return;
        !          1944:        }
        !          1945:
        !          1946:        if (ifp->if_flags & IFF_OACTIVE) {
        !          1947:                DPRINTFN(30, ("%s: atu_start: IFF_OACTIVE\n",
        !          1948:                    sc->atu_dev.dv_xname));
        !          1949:                return;
        !          1950:        }
        !          1951:
        !          1952:        for (;;) {
        !          1953:                /* grab a TX buffer */
        !          1954:                s = splnet();
        !          1955:                c = SLIST_FIRST(&cd->atu_tx_free);
        !          1956:                if (c != NULL) {
        !          1957:                        SLIST_REMOVE_HEAD(&cd->atu_tx_free, atu_list);
        !          1958:                        cd->atu_tx_inuse++;
        !          1959:                        if (cd->atu_tx_inuse == ATU_TX_LIST_CNT)
        !          1960:                                ifp->if_flags |= IFF_OACTIVE;
        !          1961:                }
        !          1962:                splx(s);
        !          1963:                if (c == NULL) {
        !          1964:                        DPRINTFN(10, ("%s: out of tx xfers\n",
        !          1965:                            sc->atu_dev.dv_xname));
        !          1966:                        ifp->if_flags |= IFF_OACTIVE;
        !          1967:                        break;
        !          1968:                }
        !          1969:
        !          1970:                /*
        !          1971:                 * Poll the management queue for frames, it has priority over
        !          1972:                 * normal data frames.
        !          1973:                 */
        !          1974:                IF_DEQUEUE(&ic->ic_mgtq, m);
        !          1975:                if (m == NULL) {
        !          1976:                        DPRINTFN(10, ("%s: atu_start: data packet\n",
        !          1977:                            sc->atu_dev.dv_xname));
        !          1978:                        if (ic->ic_state != IEEE80211_S_RUN) {
        !          1979:                                DPRINTFN(25, ("%s: no data till running\n",
        !          1980:                                    sc->atu_dev.dv_xname));
        !          1981:                                /* put the xfer back on the list */
        !          1982:                                s = splnet();
        !          1983:                                SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
        !          1984:                                    atu_list);
        !          1985:                                cd->atu_tx_inuse--;
        !          1986:                                splx(s);
        !          1987:                                break;
        !          1988:                        }
        !          1989:
        !          1990:                        IFQ_DEQUEUE(&ifp->if_snd, m);
        !          1991:                        if (m == NULL) {
        !          1992:                                DPRINTFN(25, ("%s: nothing to send\n",
        !          1993:                                    sc->atu_dev.dv_xname));
        !          1994:                                s = splnet();
        !          1995:                                SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
        !          1996:                                    atu_list);
        !          1997:                                cd->atu_tx_inuse--;
        !          1998:                                splx(s);
        !          1999:                                break;
        !          2000:                        }
        !          2001:
        !          2002: #if NBPFILTER > 0
        !          2003:                        if (ifp->if_bpf)
        !          2004:                                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
        !          2005: #endif
        !          2006:
        !          2007:                        m = ieee80211_encap(ifp, m, &ni);
        !          2008:                        if (m == NULL)
        !          2009:                                goto bad;
        !          2010:                        wh = mtod(m, struct ieee80211_frame *);
        !          2011:
        !          2012: #if NBPFILTER > 0
        !          2013:                        if (ic->ic_rawbpf != NULL)
        !          2014:                                bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
        !          2015: #endif
        !          2016:                } else {
        !          2017:                        DPRINTFN(25, ("%s: atu_start: mgmt packet\n",
        !          2018:                            sc->atu_dev.dv_xname));
        !          2019:
        !          2020:                        /*
        !          2021:                         * Hack!  The referenced node pointer is in the
        !          2022:                         * rcvif field of the packet header.  This is
        !          2023:                         * placed there by ieee80211_mgmt_output because
        !          2024:                         * we need to hold the reference with the frame
        !          2025:                         * and there's no other way (other than packet
        !          2026:                         * tags which we consider too expensive to use)
        !          2027:                         * to pass it along.
        !          2028:                         */
        !          2029:                        ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
        !          2030:                        m->m_pkthdr.rcvif = NULL;
        !          2031:
        !          2032:                        wh = mtod(m, struct ieee80211_frame *);
        !          2033:                        /* sc->sc_stats.ast_tx_mgmt++; */
        !          2034:                }
        !          2035:
        !          2036:                if (atu_tx_start(sc, ni, c, m)) {
        !          2037: bad:
        !          2038:                        s = splnet();
        !          2039:                        SLIST_INSERT_HEAD(&cd->atu_tx_free, c,
        !          2040:                            atu_list);
        !          2041:                        cd->atu_tx_inuse--;
        !          2042:                        splx(s);
        !          2043:                        /* ifp_if_oerrors++; */
        !          2044:                        if (ni != NULL)
        !          2045:                                ieee80211_release_node(ic, ni);
        !          2046:                        continue;
        !          2047:                }
        !          2048:                ifp->if_timer = 5;
        !          2049:        }
        !          2050: }
        !          2051:
        !          2052: int
        !          2053: atu_init(struct ifnet *ifp)
        !          2054: {
        !          2055:        struct atu_softc        *sc = ifp->if_softc;
        !          2056:        struct ieee80211com     *ic = &sc->sc_ic;
        !          2057:        struct atu_chain        *c;
        !          2058:        usbd_status             err;
        !          2059:        int                     i, s;
        !          2060:
        !          2061:        s = splnet();
        !          2062:
        !          2063:        DPRINTFN(10, ("%s: atu_init\n", sc->atu_dev.dv_xname));
        !          2064:
        !          2065:        if (ifp->if_flags & IFF_RUNNING) {
        !          2066:                splx(s);
        !          2067:                return(0);
        !          2068:        }
        !          2069:
        !          2070:        /* Init TX ring */
        !          2071:        if (atu_tx_list_init(sc))
        !          2072:                printf("%s: tx list init failed\n", sc->atu_dev.dv_xname);
        !          2073:
        !          2074:        /* Init RX ring */
        !          2075:        if (atu_rx_list_init(sc))
        !          2076:                printf("%s: rx list init failed\n", sc->atu_dev.dv_xname);
        !          2077:
        !          2078:        /* Load the multicast filter. */
        !          2079:        /*atu_setmulti(sc); */
        !          2080:
        !          2081:        /* Open RX and TX pipes. */
        !          2082:        err = usbd_open_pipe(sc->atu_iface, sc->atu_ed[ATU_ENDPT_RX],
        !          2083:            USBD_EXCLUSIVE_USE, &sc->atu_ep[ATU_ENDPT_RX]);
        !          2084:        if (err) {
        !          2085:                DPRINTF(("%s: open rx pipe failed: %s\n",
        !          2086:                    sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2087:                splx(s);
        !          2088:                return(EIO);
        !          2089:        }
        !          2090:
        !          2091:        err = usbd_open_pipe(sc->atu_iface, sc->atu_ed[ATU_ENDPT_TX],
        !          2092:            USBD_EXCLUSIVE_USE, &sc->atu_ep[ATU_ENDPT_TX]);
        !          2093:        if (err) {
        !          2094:                DPRINTF(("%s: open tx pipe failed: %s\n",
        !          2095:                    sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2096:                splx(s);
        !          2097:                return(EIO);
        !          2098:        }
        !          2099:
        !          2100:        /* Start up the receive pipe. */
        !          2101:        for (i = 0; i < ATU_RX_LIST_CNT; i++) {
        !          2102:                c = &sc->atu_cdata.atu_rx_chain[i];
        !          2103:
        !          2104:                usbd_setup_xfer(c->atu_xfer, sc->atu_ep[ATU_ENDPT_RX], c,
        !          2105:                    c->atu_buf, ATU_RX_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
        !          2106:                    USBD_NO_TIMEOUT, atu_rxeof);
        !          2107:                usbd_transfer(c->atu_xfer);
        !          2108:        }
        !          2109:
        !          2110:        DPRINTFN(10, ("%s: starting up using MAC=%s\n",
        !          2111:            sc->atu_dev.dv_xname, ether_sprintf(ic->ic_myaddr)));
        !          2112:
        !          2113:        /* Do initial setup */
        !          2114:        err = atu_initial_config(sc);
        !          2115:        if (err) {
        !          2116:                DPRINTF(("%s: initial config failed!\n",
        !          2117:                    sc->atu_dev.dv_xname));
        !          2118:                splx(s);
        !          2119:                return(EIO);
        !          2120:        }
        !          2121:        DPRINTFN(10, ("%s: initialised transceiver\n",
        !          2122:            sc->atu_dev.dv_xname));
        !          2123:
        !          2124:        /* sc->atu_rxfilt = ATU_RXFILT_UNICAST|ATU_RXFILT_BROADCAST; */
        !          2125:
        !          2126:        /* If we want promiscuous mode, set the allframes bit. */
        !          2127:        /*
        !          2128:        if (ifp->if_flags & IFF_PROMISC)
        !          2129:                sc->atu_rxfilt |= ATU_RXFILT_PROMISC;
        !          2130:        */
        !          2131:
        !          2132:        ifp->if_flags |= IFF_RUNNING;
        !          2133:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2134:        splx(s);
        !          2135:
        !          2136:        /* XXX the following HAS to be replaced */
        !          2137:        s = splnet();
        !          2138:        err = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
        !          2139:        if (err)
        !          2140:                DPRINTFN(1, ("%s: atu_init: error calling "
        !          2141:                    "ieee80211_net_state", sc->atu_dev.dv_xname));
        !          2142:        splx(s);
        !          2143:
        !          2144:        return 0;
        !          2145: }
        !          2146:
        !          2147: int
        !          2148: atu_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !          2149: {
        !          2150:        struct atu_softc        *sc = ifp->if_softc;
        !          2151:        struct ifaddr           *ifa;
        !          2152:        int                     err = 0, s;
        !          2153:
        !          2154:        s = splnet();
        !          2155:        switch (command) {
        !          2156:        case SIOCSIFADDR:
        !          2157:                DPRINTFN(15, ("%s: SIOCSIFADDR\n", sc->atu_dev.dv_xname));
        !          2158:
        !          2159:                ifa = (struct ifaddr *)data;
        !          2160:                ifp->if_flags |= IFF_UP;
        !          2161:                atu_init(ifp);
        !          2162:
        !          2163:                switch (ifa->ifa_addr->sa_family) {
        !          2164: #ifdef INET
        !          2165:                case AF_INET:
        !          2166:                        arp_ifinit(&sc->sc_ic.ic_ac, ifa);
        !          2167:                        break;
        !          2168: #endif /* INET */
        !          2169:                }
        !          2170:                break;
        !          2171:
        !          2172:        case SIOCSIFFLAGS:
        !          2173:                DPRINTFN(15, ("%s: SIOCSIFFLAGS\n", sc->atu_dev.dv_xname));
        !          2174:
        !          2175:                if (ifp->if_flags & IFF_UP) {
        !          2176:                        if (ifp->if_flags & IFF_RUNNING &&
        !          2177:                            ifp->if_flags & IFF_PROMISC &&
        !          2178:                            !(sc->atu_if_flags & IFF_PROMISC)) {
        !          2179: /* enable promisc */
        !          2180: #if 0
        !          2181:                                sc->atu_rxfilt |= ATU_RXFILT_PROMISC;
        !          2182:                                atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
        !          2183:                                    sc->atu_rxfilt);
        !          2184: #endif
        !          2185:                        } else if (ifp->if_flags & IFF_RUNNING &&
        !          2186:                            !(ifp->if_flags & IFF_PROMISC) &&
        !          2187:                            sc->atu_if_flags & IFF_PROMISC) {
        !          2188: /* disable promisc */
        !          2189: #if 0
        !          2190:                                sc->atu_rxfilt &= ~ATU_RXFILT_PROMISC;
        !          2191:                                atu_setword(sc, ATU_CMD_SET_PKT_FILTER,
        !          2192:                                    sc->atu_rxfilt);
        !          2193: #endif
        !          2194:                        } else if (!(ifp->if_flags & IFF_RUNNING))
        !          2195:                                atu_init(ifp);
        !          2196:
        !          2197:                        DPRINTFN(15, ("%s: ioctl calling atu_init()\n",
        !          2198:                            sc->atu_dev.dv_xname));
        !          2199:                        atu_init(ifp);
        !          2200:                        err = atu_switch_radio(sc, 1);
        !          2201:                } else {
        !          2202:                        if (ifp->if_flags & IFF_RUNNING)
        !          2203:                                atu_stop(ifp, 0);
        !          2204:                        err = atu_switch_radio(sc, 0);
        !          2205:                }
        !          2206:                sc->atu_if_flags = ifp->if_flags;
        !          2207:                err = 0;
        !          2208:                break;
        !          2209:
        !          2210:        case SIOCADDMULTI:
        !          2211:                DPRINTFN(15, ("%s: SIOCADDMULTI\n", sc->atu_dev.dv_xname));
        !          2212:                /* TODO: implement */
        !          2213:                err = 0;
        !          2214:                break;
        !          2215:
        !          2216:        case SIOCDELMULTI:
        !          2217:                DPRINTFN(15, ("%s: SIOCDELMULTI\n", sc->atu_dev.dv_xname));
        !          2218:                /* TODO: implement */
        !          2219:                err = 0;
        !          2220:                break;
        !          2221:
        !          2222:        default:
        !          2223:                DPRINTFN(15, ("%s: ieee80211_ioctl (%lu)\n",
        !          2224:                    sc->atu_dev.dv_xname, command));
        !          2225:                err = ieee80211_ioctl(ifp, command, data);
        !          2226:                break;
        !          2227:        }
        !          2228:
        !          2229:        if (err == ENETRESET) {
        !          2230:                if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
        !          2231:                    (IFF_RUNNING|IFF_UP)) {
        !          2232:                        DPRINTF(("%s: atu_ioctl(): netreset\n",
        !          2233:                            sc->atu_dev.dv_xname));
        !          2234:                        atu_init(ifp);
        !          2235:                }
        !          2236:                err = 0;
        !          2237:        }
        !          2238:
        !          2239:        splx(s);
        !          2240:        return (err);
        !          2241: }
        !          2242:
        !          2243: void
        !          2244: atu_watchdog(struct ifnet *ifp)
        !          2245: {
        !          2246:        struct atu_softc        *sc = ifp->if_softc;
        !          2247:        struct atu_chain        *c;
        !          2248:        usbd_status             stat;
        !          2249:        int                     cnt, s;
        !          2250:
        !          2251:        DPRINTF(("%s: atu_watchdog\n", sc->atu_dev.dv_xname));
        !          2252:
        !          2253:        ifp->if_timer = 0;
        !          2254:
        !          2255:        if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
        !          2256:                return;
        !          2257:
        !          2258:        if (sc->sc_state != ATU_S_OK)
        !          2259:                return;
        !          2260:
        !          2261:        sc = ifp->if_softc;
        !          2262:        s = splnet();
        !          2263:        ifp->if_oerrors++;
        !          2264:        DPRINTF(("%s: watchdog timeout\n", sc->atu_dev.dv_xname));
        !          2265:
        !          2266:        /*
        !          2267:         * TODO:
        !          2268:         * we should change this since we have multiple TX transfers...
        !          2269:         */
        !          2270:        for (cnt = 0; cnt < ATU_TX_LIST_CNT; cnt++) {
        !          2271:                c = &sc->atu_cdata.atu_tx_chain[cnt];
        !          2272:                if (c->atu_in_xfer) {
        !          2273:                        usbd_get_xfer_status(c->atu_xfer, NULL, NULL, NULL,
        !          2274:                            &stat);
        !          2275:                        atu_txeof(c->atu_xfer, c, stat);
        !          2276:                }
        !          2277:        }
        !          2278:
        !          2279:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          2280:                atu_start(ifp);
        !          2281:        splx(s);
        !          2282:
        !          2283:        ieee80211_watchdog(ifp);
        !          2284: }
        !          2285:
        !          2286: /*
        !          2287:  * Stop the adapter and free any mbufs allocated to the
        !          2288:  * RX and TX lists.
        !          2289:  */
        !          2290: void
        !          2291: atu_stop(struct ifnet *ifp, int disable)
        !          2292: {
        !          2293:        struct atu_softc        *sc = ifp->if_softc;
        !          2294:        struct atu_cdata        *cd;
        !          2295:        usbd_status             err;
        !          2296:        int s;
        !          2297:
        !          2298:        s = splnet();
        !          2299:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2300:        ifp->if_timer = 0;
        !          2301:
        !          2302:        /* Stop transfers. */
        !          2303:        if (sc->atu_ep[ATU_ENDPT_RX] != NULL) {
        !          2304:                err = usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_RX]);
        !          2305:                if (err) {
        !          2306:                        DPRINTF(("%s: abort rx pipe failed: %s\n",
        !          2307:                            sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2308:                }
        !          2309:                err = usbd_close_pipe(sc->atu_ep[ATU_ENDPT_RX]);
        !          2310:                if (err) {
        !          2311:                        DPRINTF(("%s: close rx pipe failed: %s\n",
        !          2312:                            sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2313:                }
        !          2314:                sc->atu_ep[ATU_ENDPT_RX] = NULL;
        !          2315:        }
        !          2316:
        !          2317:        if (sc->atu_ep[ATU_ENDPT_TX] != NULL) {
        !          2318:                err = usbd_abort_pipe(sc->atu_ep[ATU_ENDPT_TX]);
        !          2319:                if (err) {
        !          2320:                        DPRINTF(("%s: abort tx pipe failed: %s\n",
        !          2321:                            sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2322:                }
        !          2323:                err = usbd_close_pipe(sc->atu_ep[ATU_ENDPT_TX]);
        !          2324:                if (err) {
        !          2325:                        DPRINTF(("%s: close tx pipe failed: %s\n",
        !          2326:                            sc->atu_dev.dv_xname, usbd_errstr(err)));
        !          2327:                }
        !          2328:                sc->atu_ep[ATU_ENDPT_TX] = NULL;
        !          2329:        }
        !          2330:
        !          2331:        /* Free RX/TX/MGMT list resources. */
        !          2332:        cd = &sc->atu_cdata;
        !          2333:        atu_xfer_list_free(sc, cd->atu_rx_chain, ATU_RX_LIST_CNT);
        !          2334:        atu_xfer_list_free(sc, cd->atu_tx_chain, ATU_TX_LIST_CNT);
        !          2335:
        !          2336:        /* Let's be nice and turn off the radio before we leave */
        !          2337:        atu_switch_radio(sc, 0);
        !          2338:
        !          2339:        splx(s);
        !          2340: }

CVSweb