LCOV - code coverage report
Current view: top level - dev/usb - if_atu.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 865 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13