FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_zyd.c
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, ®, 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 |