[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_zyd.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*      $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */
  2 /*      $NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $      */
  3 /*      $FreeBSD: src/sys/dev/usb/if_zyd.c,v 1.23 2008/10/27 16:46:50 sam Exp $ */
  4 
  5 /*-
  6  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
  7  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
  8  *
  9  * Permission to use, copy, modify, and distribute this software for any
 10  * purpose with or without fee is hereby granted, provided that the above
 11  * copyright notice and this permission notice appear in all copies.
 12  *
 13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 20  */
 21 
 22 /*
 23  * ZyDAS ZD1211/ZD1211B USB WLAN driver.
 24  */
 25 
 26 #include <sys/param.h>
 27 #include <sys/systm.h>
 28 #include <sys/sockio.h>
 29 #include <sys/mbuf.h>
 30 #include <sys/malloc.h>
 31 #include <sys/kernel.h>
 32 #include <sys/module.h>
 33 #include <sys/socket.h>
 34 #include <sys/sysctl.h>
 35 #include <sys/endian.h>
 36 #include <sys/linker.h>
 37 
 38 #include <net/if.h>
 39 #include <net/if_arp.h>
 40 #include <net/ethernet.h>
 41 #include <net/if_dl.h>
 42 #include <net/if_media.h>
 43 #include <net/if_types.h>
 44 
 45 #include <sys/bus.h>
 46 #include <machine/bus.h>
 47 
 48 #include <net80211/ieee80211_var.h>
 49 #include <net80211/ieee80211_amrr.h>
 50 #include <net80211/ieee80211_phy.h>
 51 #include <net80211/ieee80211_radiotap.h>
 52 #include <net80211/ieee80211_regdomain.h>
 53 
 54 #include <net/bpf.h>
 55 
 56 #include <dev/usb/usb.h>
 57 #include <dev/usb/usbdi.h>
 58 #include <dev/usb/usbdi_util.h>
 59 #include <dev/usb/usbdivar.h>
 60 #include "usbdevs.h"
 61 #include <dev/usb/usb_ethersubr.h>
 62 
 63 #include <dev/mii/mii.h>
 64 #include <dev/mii/miivar.h>
 65 
 66 #include <dev/usb/if_zydreg.h>
 67 #include <dev/usb/if_zydfw.h>
 68 
 69 #define ZYD_DEBUG
 70 #ifdef ZYD_DEBUG
 71 #define DPRINTF(x)      do { if (zyddebug > 0) printf x; } while (0)
 72 #define DPRINTFN(n, x)  do { if (zyddebug > (n)) printf x; } while (0)
 73 int zyddebug = 0;
 74 #else
 75 #define DPRINTF(x)
 76 #define DPRINTFN(n, x)
 77 #endif
 78 
 79 static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
 80 static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
 81 
 82 /* various supported device vendors/products */
 83 #define ZYD_ZD1211_DEV(v, p)    \
 84         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211 }
 85 #define ZYD_ZD1211B_DEV(v, p)   \
 86         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B }
 87 static const struct zyd_type {
 88         struct usb_devno        dev;
 89         uint8_t                 rev;
 90 #define ZYD_ZD1211      0
 91 #define ZYD_ZD1211B     1
 92 } zyd_devs[] = {
 93         ZYD_ZD1211_DEV(3COM2,           3CRUSB10075),
 94         ZYD_ZD1211_DEV(ABOCOM,          WL54),
 95         ZYD_ZD1211_DEV(ASUS,            WL159G),
 96         ZYD_ZD1211_DEV(CYBERTAN,        TG54USB),
 97         ZYD_ZD1211_DEV(DRAYTEK,         VIGOR550),
 98         ZYD_ZD1211_DEV(PLANEX2,         GWUS54GD),
 99         ZYD_ZD1211_DEV(PLANEX2,         GWUS54GZL),
100         ZYD_ZD1211_DEV(PLANEX3,         GWUS54GZ),
101         ZYD_ZD1211_DEV(PLANEX3,         GWUS54MINI),
102         ZYD_ZD1211_DEV(SAGEM,           XG760A),
103         ZYD_ZD1211_DEV(SENAO,           NUB8301),
104         ZYD_ZD1211_DEV(SITECOMEU,       WL113),
105         ZYD_ZD1211_DEV(SWEEX,           ZD1211),
106         ZYD_ZD1211_DEV(TEKRAM,          QUICKWLAN),
107         ZYD_ZD1211_DEV(TEKRAM,          ZD1211_1),
108         ZYD_ZD1211_DEV(TEKRAM,          ZD1211_2),
109         ZYD_ZD1211_DEV(TWINMOS,         G240),
110         ZYD_ZD1211_DEV(UMEDIA,          ALL0298V2),
111         ZYD_ZD1211_DEV(UMEDIA,          TEW429UB_A),
112         ZYD_ZD1211_DEV(UMEDIA,          TEW429UB),
113         ZYD_ZD1211_DEV(WISTRONNEWEB,    UR055G),
114         ZYD_ZD1211_DEV(ZCOM,            ZD1211),
115         ZYD_ZD1211_DEV(ZYDAS,           ZD1211),
116         ZYD_ZD1211_DEV(ZYXEL,           AG225H),
117         ZYD_ZD1211_DEV(ZYXEL,           ZYAIRG220),
118         ZYD_ZD1211_DEV(ZYXEL,           G200V2),
119         ZYD_ZD1211_DEV(ZYXEL,           G202),
120 
121         ZYD_ZD1211B_DEV(ACCTON,         SMCWUSBG),
122         ZYD_ZD1211B_DEV(ACCTON,         ZD1211B),
123         ZYD_ZD1211B_DEV(ASUS,           A9T_WIFI),
124         ZYD_ZD1211B_DEV(BELKIN,         F5D7050_V4000),
125         ZYD_ZD1211B_DEV(BELKIN,         ZD1211B),
126         ZYD_ZD1211B_DEV(CISCOLINKSYS,   WUSBF54G),
127         ZYD_ZD1211B_DEV(FIBERLINE,      WL430U),
128         ZYD_ZD1211B_DEV(MELCO,          KG54L),
129         ZYD_ZD1211B_DEV(PHILIPS,        SNU5600),
130         ZYD_ZD1211B_DEV(PLANEX2,        GW_US54GXS),
131         ZYD_ZD1211B_DEV(SAGEM,          XG76NA),
132         ZYD_ZD1211B_DEV(SITECOMEU,      ZD1211B),
133         ZYD_ZD1211B_DEV(UMEDIA,         TEW429UBC1),
134 #if 0   /* Shall we needs? */
135         ZYD_ZD1211B_DEV(UNKNOWN1,       ZD1211B_1),
136         ZYD_ZD1211B_DEV(UNKNOWN1,       ZD1211B_2),
137         ZYD_ZD1211B_DEV(UNKNOWN2,       ZD1211B),
138         ZYD_ZD1211B_DEV(UNKNOWN3,       ZD1211B),
139 #endif
140         ZYD_ZD1211B_DEV(USR,            USR5423),
141         ZYD_ZD1211B_DEV(VTECH,          ZD1211B),
142         ZYD_ZD1211B_DEV(ZCOM,           ZD1211B),
143         ZYD_ZD1211B_DEV(ZYDAS,          ZD1211B),
144         ZYD_ZD1211B_DEV(ZYXEL,          M202),
145         ZYD_ZD1211B_DEV(ZYXEL,          G220V2),
146 };
147 #define zyd_lookup(v, p)        \
148         ((const struct zyd_type *)usb_lookup(zyd_devs, v, p))
149 
150 static device_probe_t zyd_match;
151 static device_attach_t zyd_attach;
152 static device_detach_t zyd_detach;
153 
154 static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
155                     const char name[IFNAMSIZ], int unit, int opmode,
156                     int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
157                     const uint8_t mac[IEEE80211_ADDR_LEN]);
158 static void     zyd_vap_delete(struct ieee80211vap *);
159 static int      zyd_attachhook(struct zyd_softc *);
160 static int      zyd_complete_attach(struct zyd_softc *);
161 static int      zyd_open_pipes(struct zyd_softc *);
162 static void     zyd_close_pipes(struct zyd_softc *);
163 static int      zyd_alloc_tx_list(struct zyd_softc *);
164 static void     zyd_free_tx_list(struct zyd_softc *);
165 static int      zyd_alloc_rx_list(struct zyd_softc *);
166 static void     zyd_free_rx_list(struct zyd_softc *);
167 static struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *,
168                             const uint8_t mac[IEEE80211_ADDR_LEN]);
169 static void     zyd_task(void *);
170 static int      zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int);
171 static int      zyd_cmd(struct zyd_softc *, uint16_t, const void *, int,
172                     void *, int, u_int);
173 static int      zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
174 static int      zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
175 static int      zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
176 static int      zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
177 static int      zyd_rfwrite(struct zyd_softc *, uint32_t);
178 static void     zyd_lock_phy(struct zyd_softc *);
179 static void     zyd_unlock_phy(struct zyd_softc *);
180 static int      zyd_rfmd_init(struct zyd_rf *);
181 static int      zyd_rfmd_switch_radio(struct zyd_rf *, int);
182 static int      zyd_rfmd_set_channel(struct zyd_rf *, uint8_t);
183 static int      zyd_al2230_init(struct zyd_rf *);
184 static int      zyd_al2230_switch_radio(struct zyd_rf *, int);
185 static int      zyd_al2230_set_channel(struct zyd_rf *, uint8_t);
186 static int      zyd_al2230_init_b(struct zyd_rf *);
187 static int      zyd_al7230B_init(struct zyd_rf *);
188 static int      zyd_al7230B_switch_radio(struct zyd_rf *, int);
189 static int      zyd_al7230B_set_channel(struct zyd_rf *, uint8_t);
190 static int      zyd_al2210_init(struct zyd_rf *);
191 static int      zyd_al2210_switch_radio(struct zyd_rf *, int);
192 static int      zyd_al2210_set_channel(struct zyd_rf *, uint8_t);
193 static int      zyd_gct_init(struct zyd_rf *);
194 static int      zyd_gct_switch_radio(struct zyd_rf *, int);
195 static int      zyd_gct_set_channel(struct zyd_rf *, uint8_t);
196 static int      zyd_maxim_init(struct zyd_rf *);
197 static int      zyd_maxim_switch_radio(struct zyd_rf *, int);
198 static int      zyd_maxim_set_channel(struct zyd_rf *, uint8_t);
199 static int      zyd_maxim2_init(struct zyd_rf *);
200 static int      zyd_maxim2_switch_radio(struct zyd_rf *, int);
201 static int      zyd_maxim2_set_channel(struct zyd_rf *, uint8_t);
202 static int      zyd_rf_attach(struct zyd_softc *, uint8_t);
203 static const char *zyd_rf_name(uint8_t);
204 static int      zyd_hw_init(struct zyd_softc *);
205 static int      zyd_read_eeprom(struct zyd_softc *);
206 static int      zyd_set_macaddr(struct zyd_softc *, const uint8_t *);
207 static int      zyd_set_bssid(struct zyd_softc *, const uint8_t *);
208 static int      zyd_switch_radio(struct zyd_softc *, int);
209 static void     zyd_set_led(struct zyd_softc *, int, int);
210 static void     zyd_set_multi(void *);
211 static void     zyd_update_mcast(struct ifnet *);
212 static int      zyd_set_rxfilter(struct zyd_softc *);
213 static void     zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *);
214 static int      zyd_set_beacon_interval(struct zyd_softc *, int);
215 static void     zyd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
216 static void     zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t);
217 static void     zyd_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
218 static void     zyd_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
219 static int      zyd_tx_mgt(struct zyd_softc *, struct mbuf *,
220                     struct ieee80211_node *);
221 static int      zyd_tx_data(struct zyd_softc *, struct mbuf *,
222                     struct ieee80211_node *);
223 static void     zyd_start(struct ifnet *);
224 static int      zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
225                     const struct ieee80211_bpf_params *);
226 static void     zyd_watchdog(void *);
227 static int      zyd_ioctl(struct ifnet *, u_long, caddr_t);
228 static void     zyd_init_locked(struct zyd_softc *);
229 static void     zyd_init(void *);
230 static void     zyd_stop(struct zyd_softc *, int);
231 static int      zyd_loadfirmware(struct zyd_softc *, u_char *, size_t);
232 static void     zyd_newassoc(struct ieee80211_node *, int);
233 static void     zyd_scantask(void *);
234 static void     zyd_scan_start(struct ieee80211com *);
235 static void     zyd_scan_end(struct ieee80211com *);
236 static void     zyd_set_channel(struct ieee80211com *);
237 static void     zyd_wakeup(struct zyd_softc *);
238 
239 static int
240 zyd_match(device_t dev)
241 {
242         struct usb_attach_arg *uaa = device_get_ivars(dev);
243 
244         if (!uaa->iface)
245                 return UMATCH_NONE;
246 
247         return (zyd_lookup(uaa->vendor, uaa->product) != NULL) ?
248             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
249 }
250 
251 static int
252 zyd_attachhook(struct zyd_softc *sc)
253 {
254         u_char *firmware;
255         int len, error;
256 
257         if (sc->mac_rev == ZYD_ZD1211) {
258                 firmware = (u_char *)zd1211_firmware;
259                 len = sizeof(zd1211_firmware);
260         } else {
261                 firmware = (u_char *)zd1211b_firmware;
262                 len = sizeof(zd1211b_firmware);
263         }
264 
265         error = zyd_loadfirmware(sc, firmware, len);
266         if (error != 0) {
267                 device_printf(sc->sc_dev,
268                     "could not load firmware (error=%d)\n", error);
269                 return error;
270         }
271 
272         sc->sc_flags |= ZYD_FLAG_FWLOADED;
273 
274         /* complete the attach process */
275         return zyd_complete_attach(sc);
276 }
277 
278 static int
279 zyd_attach(device_t dev)
280 {
281         int error = ENXIO;
282         struct zyd_softc *sc = device_get_softc(dev);
283         struct usb_attach_arg *uaa = device_get_ivars(dev);
284         usb_device_descriptor_t* ddesc;
285         struct ifnet *ifp;
286 
287         sc->sc_dev = dev;
288 
289         ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
290         if (ifp == NULL) {
291                 device_printf(dev, "can not if_alloc()\n");
292                 return ENXIO;
293         }
294 
295         sc->sc_udev = uaa->device;
296         sc->sc_flags = 0;
297         sc->mac_rev = zyd_lookup(uaa->vendor, uaa->product)->rev;
298 
299         ddesc = usbd_get_device_descriptor(sc->sc_udev);
300         if (UGETW(ddesc->bcdDevice) < 0x4330) {
301                 device_printf(dev, "device version mismatch: 0x%x "
302                     "(only >= 43.30 supported)\n",
303                     UGETW(ddesc->bcdDevice));
304                 goto bad;
305         }
306 
307         ifp->if_softc = sc;
308         if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
309         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
310             IFF_NEEDSGIANT; /* USB stack is still under Giant lock */
311         ifp->if_init = zyd_init;
312         ifp->if_ioctl = zyd_ioctl;
313         ifp->if_start = zyd_start;
314         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
315         IFQ_SET_READY(&ifp->if_snd);
316 
317         STAILQ_INIT(&sc->sc_rqh);
318 
319         error = zyd_attachhook(sc);
320         if (error != 0) {
321 bad:
322                 if_free(ifp);
323                 return error;
324         }
325 
326         return 0;
327 }
328 
329 static int
330 zyd_complete_attach(struct zyd_softc *sc)
331 {
332         struct ifnet *ifp = sc->sc_ifp;
333         struct ieee80211com *ic = ifp->if_l2com;
334         usbd_status error;
335         uint8_t bands;
336 
337         mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
338             MTX_DEF | MTX_RECURSE);
339 
340         usb_init_task(&sc->sc_scantask, zyd_scantask, sc);
341         usb_init_task(&sc->sc_task, zyd_task, sc);
342         usb_init_task(&sc->sc_mcasttask, zyd_set_multi, sc);
343 
344         callout_init(&sc->sc_watchdog_ch, 0);
345 
346         error = usbd_set_config_no(sc->sc_udev, ZYD_CONFIG_NO, 1);
347         if (error != 0) {
348                 device_printf(sc->sc_dev, "setting config no failed\n");
349                 error = ENXIO;
350                 goto fail;
351         }
352 
353         error = usbd_device2interface_handle(sc->sc_udev, ZYD_IFACE_INDEX,
354             &sc->sc_iface);
355         if (error != 0) {
356                 device_printf(sc->sc_dev, "getting interface handle failed\n");
357                 error = ENXIO;
358                 goto fail;
359         }
360 
361         if ((error = zyd_open_pipes(sc)) != 0) {
362                 device_printf(sc->sc_dev, "could not open pipes\n");
363                 goto fail;
364         }
365 
366         if ((error = zyd_read_eeprom(sc)) != 0) {
367                 device_printf(sc->sc_dev, "could not read EEPROM\n");
368                 goto fail;
369         }
370 
371         if ((error = zyd_rf_attach(sc, sc->rf_rev)) != 0) {
372                 device_printf(sc->sc_dev, "could not attach RF, rev 0x%x\n",
373                     sc->rf_rev);
374                 goto fail;
375         }
376 
377         if ((error = zyd_hw_init(sc)) != 0) {
378                 device_printf(sc->sc_dev, "hardware initialization failed\n");
379                 goto fail;
380         }
381 
382         device_printf(sc->sc_dev,
383             "HMAC ZD1211%s, FW %02x.%02x, RF %s, PA %x, address %s\n",
384             (sc->mac_rev == ZYD_ZD1211) ? "": "B",
385             sc->fw_rev >> 8, sc->fw_rev & 0xff, zyd_rf_name(sc->rf_rev),
386             sc->pa_rev, ether_sprintf(ic->ic_myaddr));
387 
388         IEEE80211_ADDR_COPY(sc->sc_bssid, ic->ic_myaddr);
389 
390         ic->ic_ifp = ifp;
391         ic->ic_phytype = IEEE80211_T_OFDM;      /* not only, but not used */
392         ic->ic_opmode = IEEE80211_M_STA;
393 
394         /* set device capabilities */
395         ic->ic_caps =
396                   IEEE80211_C_STA               /* station mode */
397                 | IEEE80211_C_MONITOR           /* monitor mode */
398                 | IEEE80211_C_SHPREAMBLE        /* short preamble supported */
399                 | IEEE80211_C_SHSLOT    /* short slot time supported */
400                 | IEEE80211_C_BGSCAN            /* capable of bg scanning */
401                 | IEEE80211_C_WPA               /* 802.11i */
402                 ;
403 
404         bands = 0;
405         setbit(&bands, IEEE80211_MODE_11B);
406         setbit(&bands, IEEE80211_MODE_11G);
407         ieee80211_init_channels(ic, NULL, &bands);
408 
409         ieee80211_ifattach(ic);
410         ic->ic_newassoc = zyd_newassoc;
411         ic->ic_raw_xmit = zyd_raw_xmit;
412         ic->ic_node_alloc = zyd_node_alloc;
413         ic->ic_scan_start = zyd_scan_start;
414         ic->ic_scan_end = zyd_scan_end;
415         ic->ic_set_channel = zyd_set_channel;
416 
417         ic->ic_vap_create = zyd_vap_create;
418         ic->ic_vap_delete = zyd_vap_delete;
419         ic->ic_update_mcast = zyd_update_mcast;
420 
421         bpfattach(ifp, DLT_IEEE802_11_RADIO,
422             sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap));
423 
424         sc->sc_rxtap_len = sizeof(sc->sc_rxtap);
425         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
426         sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT);
427 
428         sc->sc_txtap_len = sizeof(sc->sc_txtap);
429         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
430         sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT);
431 
432         if (bootverbose)
433                 ieee80211_announce(ic);
434 
435         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
436 
437         return error;
438 
439 fail:
440         mtx_destroy(&sc->sc_mtx);
441 
442         return error;
443 }
444 
445 static int
446 zyd_detach(device_t dev)
447 {
448         struct zyd_softc *sc = device_get_softc(dev);
449         struct ifnet *ifp = sc->sc_ifp;
450         struct ieee80211com *ic = ifp->if_l2com;
451 
452         if (!device_is_attached(dev))
453                 return 0;
454 
455         /* protect a race when we have listeners related with the driver.  */
456         ifp->if_flags &= ~IFF_UP;
457 
458         zyd_stop(sc, 1);
459         bpfdetach(ifp);
460         ieee80211_ifdetach(ic);
461 
462         /* set a flag to indicate we're detaching.  */
463         sc->sc_flags |= ZYD_FLAG_DETACHING;
464 
465         usb_rem_task(sc->sc_udev, &sc->sc_scantask);
466         usb_rem_task(sc->sc_udev, &sc->sc_task);
467         callout_stop(&sc->sc_watchdog_ch);
468 
469         zyd_wakeup(sc);
470         zyd_close_pipes(sc);
471 
472         if_free(ifp);
473         mtx_destroy(&sc->sc_mtx);
474 
475         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
476 
477         return 0;
478 }
479 
480 static struct ieee80211vap *
481 zyd_vap_create(struct ieee80211com *ic,
482         const char name[IFNAMSIZ], int unit, int opmode, int flags,
483         const uint8_t bssid[IEEE80211_ADDR_LEN],
484         const uint8_t mac[IEEE80211_ADDR_LEN])
485 {
486         struct zyd_vap *zvp;
487         struct ieee80211vap *vap;
488 
489         if (!TAILQ_EMPTY(&ic->ic_vaps))         /* only one at a time */
490                 return NULL;
491         zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap),
492             M_80211_VAP, M_NOWAIT | M_ZERO);
493         if (zvp == NULL)
494                 return NULL;
495         vap = &zvp->vap;
496         /* enable s/w bmiss handling for sta mode */
497         ieee80211_vap_setup(ic, vap, name, unit, opmode,
498             flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
499 
500         /* override state transition machine */
501         zvp->newstate = vap->iv_newstate;
502         vap->iv_newstate = zyd_newstate;
503 
504         ieee80211_amrr_init(&zvp->amrr, vap,
505             IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
506             IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
507             1000 /* 1 sec */);
508 
509         /* complete setup */
510         ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
511         ic->ic_opmode = opmode;
512         return vap;
513 }
514 
515 static void
516 zyd_vap_delete(struct ieee80211vap *vap)
517 {
518         struct zyd_vap *zvp = ZYD_VAP(vap);
519 
520         ieee80211_amrr_cleanup(&zvp->amrr);
521         ieee80211_vap_detach(vap);
522         free(zvp, M_80211_VAP);
523 }
524 
525 static int
526 zyd_open_pipes(struct zyd_softc *sc)
527 {
528         usb_endpoint_descriptor_t *edesc;
529         int isize;
530         usbd_status error;
531 
532         /* interrupt in */
533         edesc = usbd_get_endpoint_descriptor(sc->sc_iface, 0x83);
534         if (edesc == NULL)
535                 return EINVAL;
536 
537         isize = UGETW(edesc->wMaxPacketSize);
538         if (isize == 0) /* should not happen */
539                 return EINVAL;
540 
541         sc->ibuf = malloc(isize, M_USBDEV, M_NOWAIT);
542         if (sc->ibuf == NULL)
543                 return ENOMEM;
544 
545         error = usbd_open_pipe_intr(sc->sc_iface, 0x83, USBD_SHORT_XFER_OK,
546             &sc->zyd_ep[ZYD_ENDPT_IIN], sc, sc->ibuf, isize, zyd_intr,
547             USBD_DEFAULT_INTERVAL);
548         if (error != 0) {
549                 device_printf(sc->sc_dev, "open rx intr pipe failed: %s\n",
550                     usbd_errstr(error));
551                 goto fail;
552         }
553 
554         /* interrupt out (not necessarily an interrupt pipe) */
555         error = usbd_open_pipe(sc->sc_iface, 0x04, USBD_EXCLUSIVE_USE,
556             &sc->zyd_ep[ZYD_ENDPT_IOUT]);
557         if (error != 0) {
558                 device_printf(sc->sc_dev, "open tx intr pipe failed: %s\n",
559                     usbd_errstr(error));
560                 goto fail;
561         }
562 
563         /* bulk in */
564         error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE,
565             &sc->zyd_ep[ZYD_ENDPT_BIN]);
566         if (error != 0) {
567                 device_printf(sc->sc_dev, "open rx pipe failed: %s\n",
568                     usbd_errstr(error));
569                 goto fail;
570         }
571 
572         /* bulk out */
573         error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE,
574             &sc->zyd_ep[ZYD_ENDPT_BOUT]);
575         if (error != 0) {
576                 device_printf(sc->sc_dev, "open tx pipe failed: %s\n",
577                     usbd_errstr(error));
578                 goto fail;
579         }
580 
581         return 0;
582 
583 fail:   zyd_close_pipes(sc);
584         return ENXIO;
585 }
586 
587 static void
588 zyd_close_pipes(struct zyd_softc *sc)
589 {
590         int i;
591 
592         for (i = 0; i < ZYD_ENDPT_CNT; i++) {
593                 if (sc->zyd_ep[i] != NULL) {
594                         usbd_abort_pipe(sc->zyd_ep[i]);
595                         usbd_close_pipe(sc->zyd_ep[i]);
596                         sc->zyd_ep[i] = NULL;
597                 }
598         }
599         if (sc->ibuf != NULL) {
600                 free(sc->ibuf, M_USBDEV);
601                 sc->ibuf = NULL;
602         }
603 }
604 
605 static int
606 zyd_alloc_tx_list(struct zyd_softc *sc)
607 {
608         int i, error;
609 
610         sc->tx_queued = 0;
611 
612         for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
613                 struct zyd_tx_data *data = &sc->tx_data[i];
614 
615                 data->sc = sc;  /* backpointer for callbacks */
616 
617                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
618                 if (data->xfer == NULL) {
619                         device_printf(sc->sc_dev,
620                             "could not allocate tx xfer\n");
621                         error = ENOMEM;
622                         goto fail;
623                 }
624                 data->buf = usbd_alloc_buffer(data->xfer, ZYD_MAX_TXBUFSZ);
625                 if (data->buf == NULL) {
626                         device_printf(sc->sc_dev,
627                             "could not allocate tx buffer\n");
628                         error = ENOMEM;
629                         goto fail;
630                 }
631 
632                 /* clear Tx descriptor */
633                 bzero(data->buf, sizeof(struct zyd_tx_desc));
634         }
635         return 0;
636 
637 fail:   zyd_free_tx_list(sc);
638         return error;
639 }
640 
641 static void
642 zyd_free_tx_list(struct zyd_softc *sc)
643 {
644         int i;
645 
646         for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
647                 struct zyd_tx_data *data = &sc->tx_data[i];
648 
649                 if (data->xfer != NULL) {
650                         usbd_free_xfer(data->xfer);
651                         data->xfer = NULL;
652                 }
653                 if (data->ni != NULL) {
654                         ieee80211_free_node(data->ni);
655                         data->ni = NULL;
656                 }
657         }
658 }
659 
660 static int
661 zyd_alloc_rx_list(struct zyd_softc *sc)
662 {
663         int i, error;
664 
665         for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
666                 struct zyd_rx_data *data = &sc->rx_data[i];
667 
668                 data->sc = sc;  /* backpointer for callbacks */
669 
670                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
671                 if (data->xfer == NULL) {
672                         device_printf(sc->sc_dev,
673                             "could not allocate rx xfer\n");
674                         error = ENOMEM;
675                         goto fail;
676                 }
677                 data->buf = usbd_alloc_buffer(data->xfer, ZYX_MAX_RXBUFSZ);
678                 if (data->buf == NULL) {
679                         device_printf(sc->sc_dev,
680                             "could not allocate rx buffer\n");
681                         error = ENOMEM;
682                         goto fail;
683                 }
684         }
685         return 0;
686 
687 fail:   zyd_free_rx_list(sc);
688         return error;
689 }
690 
691 static void
692 zyd_free_rx_list(struct zyd_softc *sc)
693 {
694         int i;
695 
696         for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
697                 struct zyd_rx_data *data = &sc->rx_data[i];
698 
699                 if (data->xfer != NULL) {
700                         usbd_free_xfer(data->xfer);
701                         data->xfer = NULL;
702                 }
703         }
704 }
705 
706 /* ARGUSED */
707 static struct ieee80211_node *
708 zyd_node_alloc(struct ieee80211vap *vap __unused,
709         const uint8_t mac[IEEE80211_ADDR_LEN] __unused)
710 {
711         struct zyd_node *zn;
712 
713         zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO);
714         return zn != NULL ? &zn->ni : NULL;
715 }
716 
717 static void
718 zyd_task(void *arg)
719 {
720         struct zyd_softc *sc = arg;
721         struct ifnet *ifp = sc->sc_ifp;
722         struct ieee80211com *ic = ifp->if_l2com;
723         struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
724         struct zyd_vap *zvp = ZYD_VAP(vap);
725 
726         switch (sc->sc_state) {
727         case IEEE80211_S_RUN:
728         {
729                 struct ieee80211_node *ni = vap->iv_bss;
730 
731                 zyd_set_chan(sc, ic->ic_curchan);
732 
733                 if (vap->iv_opmode != IEEE80211_M_MONITOR) {
734                         /* turn link LED on */
735                         zyd_set_led(sc, ZYD_LED1, 1);
736 
737                         /* make data LED blink upon Tx */
738                         zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 1);
739 
740                         IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
741                         zyd_set_bssid(sc, sc->sc_bssid);
742                 }
743                 break;
744         }
745         default:
746                 break;
747         }
748 
749         IEEE80211_LOCK(ic);
750         zvp->newstate(vap, sc->sc_state, sc->sc_arg);
751         if (vap->iv_newstate_cb != NULL)
752                 vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
753         IEEE80211_UNLOCK(ic);
754 }
755 
756 static int
757 zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
758 {
759         struct zyd_vap *zvp = ZYD_VAP(vap);
760         struct ieee80211com *ic = vap->iv_ic;
761         struct zyd_softc *sc = ic->ic_ifp->if_softc;
762 
763         usb_rem_task(sc->sc_udev, &sc->sc_scantask);
764         usb_rem_task(sc->sc_udev, &sc->sc_task);
765         callout_stop(&sc->sc_watchdog_ch);
766 
767         /* do it in a process context */
768         sc->sc_state = nstate;
769         sc->sc_arg = arg;
770 
771         if (nstate == IEEE80211_S_INIT) {
772                 zvp->newstate(vap, nstate, arg);
773                 return 0;
774         } else {
775                 usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
776                 return EINPROGRESS;
777         }
778 }
779 
780 static int
781 zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
782     void *odata, int olen, u_int flags)
783 {
784         usbd_xfer_handle xfer;
785         struct zyd_cmd cmd;
786         struct rq rq;
787         uint16_t xferflags;
788         usbd_status error;
789 
790         if (sc->sc_flags & ZYD_FLAG_DETACHING)
791                 return ENXIO;
792 
793         if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
794                 return ENOMEM;
795 
796         cmd.code = htole16(code);
797         bcopy(idata, cmd.data, ilen);
798 
799         xferflags = USBD_FORCE_SHORT_XFER;
800         if (!(flags & ZYD_CMD_FLAG_READ))
801                 xferflags |= USBD_SYNCHRONOUS;
802         else {
803                 rq.idata = idata;
804                 rq.odata = odata;
805                 rq.len = olen / sizeof(struct zyd_pair);
806                 STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq);
807         }
808 
809         usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0, &cmd,
810             sizeof(uint16_t) + ilen, xferflags, ZYD_INTR_TIMEOUT, NULL);
811         error = usbd_transfer(xfer);
812         if (error != USBD_IN_PROGRESS && error != 0) {
813                 device_printf(sc->sc_dev, "could not send command (error=%s)\n",
814                     usbd_errstr(error));
815                 (void)usbd_free_xfer(xfer);
816                 return EIO;
817         }
818         if (!(flags & ZYD_CMD_FLAG_READ)) {
819                 (void)usbd_free_xfer(xfer);
820                 return 0;       /* write: don't wait for reply */
821         }
822         /* wait at most one second for command reply */
823         error = tsleep(odata, PCATCH, "zydcmd", hz);
824         if (error == EWOULDBLOCK)
825                 device_printf(sc->sc_dev, "zyd_read sleep timeout\n");
826         STAILQ_REMOVE(&sc->sc_rqh, &rq, rq, rq);
827 
828         (void)usbd_free_xfer(xfer);
829         return error;
830 }
831 
832 static int
833 zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val)
834 {
835         struct zyd_pair tmp;
836         int error;
837 
838         reg = htole16(reg);
839         error = zyd_cmd(sc, ZYD_CMD_IORD, &reg, sizeof(reg), &tmp, sizeof(tmp),
840             ZYD_CMD_FLAG_READ);
841         if (error == 0)
842                 *val = le16toh(tmp.val);
843         return error;
844 }
845 
846 static int
847 zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val)
848 {
849         struct zyd_pair tmp[2];
850         uint16_t regs[2];
851         int error;
852 
853         regs[0] = htole16(ZYD_REG32_HI(reg));
854         regs[1] = htole16(ZYD_REG32_LO(reg));
855         error = zyd_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), tmp, sizeof(tmp),
856             ZYD_CMD_FLAG_READ);
857         if (error == 0)
858                 *val = le16toh(tmp[0].val) << 16 | le16toh(tmp[1].val);
859         return error;
860 }
861 
862 static int
863 zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
864 {
865         struct zyd_pair pair;
866 
867         pair.reg = htole16(reg);
868         pair.val = htole16(val);
869 
870         return zyd_cmd(sc, ZYD_CMD_IOWR, &pair, sizeof(pair), NULL, 0, 0);
871 }
872 
873 static int
874 zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
875 {
876         struct zyd_pair pair[2];
877 
878         pair[0].reg = htole16(ZYD_REG32_HI(reg));
879         pair[0].val = htole16(val >> 16);
880         pair[1].reg = htole16(ZYD_REG32_LO(reg));
881         pair[1].val = htole16(val & 0xffff);
882 
883         return zyd_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0);
884 }
885 
886 static int
887 zyd_rfwrite(struct zyd_softc *sc, uint32_t val)
888 {
889         struct zyd_rf *rf = &sc->sc_rf;
890         struct zyd_rfwrite req;
891         uint16_t cr203;
892         int i;
893 
894         (void)zyd_read16(sc, ZYD_CR203, &cr203);
895         cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA);
896 
897         req.code  = htole16(2);
898         req.width = htole16(rf->width);
899         for (i = 0; i < rf->width; i++) {
900                 req.bit[i] = htole16(cr203);
901                 if (val & (1 << (rf->width - 1 - i)))
902                         req.bit[i] |= htole16(ZYD_RF_DATA);
903         }
904         return zyd_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width, NULL, 0, 0);
905 }
906 
907 static void
908 zyd_lock_phy(struct zyd_softc *sc)
909 {
910         uint32_t tmp;
911 
912         (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
913         tmp &= ~ZYD_UNLOCK_PHY_REGS;
914         (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
915 }
916 
917 static void
918 zyd_unlock_phy(struct zyd_softc *sc)
919 {
920         uint32_t tmp;
921 
922         (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
923         tmp |= ZYD_UNLOCK_PHY_REGS;
924         (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
925 }
926 
927 /*
928  * RFMD RF methods.
929  */
930 static int
931 zyd_rfmd_init(struct zyd_rf *rf)
932 {
933 #define N(a)    (sizeof(a) / sizeof((a)[0]))
934         struct zyd_softc *sc = rf->rf_sc;
935         static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY;
936         static const uint32_t rfini[] = ZYD_RFMD_RF;
937         int i, error;
938 
939         /* init RF-dependent PHY registers */
940         for (i = 0; i < N(phyini); i++) {
941                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
942                 if (error != 0)
943