Line data Source code
1 : /* $OpenBSD: if_zyd.c,v 1.118 2017/04/08 02:57:25 deraadt Exp $ */
2 :
3 : /*-
4 : * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
5 : * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
6 : *
7 : * Permission to use, copy, modify, and distribute this software for any
8 : * purpose with or without fee is hereby granted, provided that the above
9 : * copyright notice and this permission notice appear in all copies.
10 : *
11 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 : */
19 :
20 : /*
21 : * ZyDAS ZD1211/ZD1211B USB WLAN driver.
22 : */
23 :
24 : #include "bpfilter.h"
25 :
26 : #include <sys/param.h>
27 : #include <sys/sockio.h>
28 : #include <sys/mbuf.h>
29 : #include <sys/kernel.h>
30 : #include <sys/socket.h>
31 : #include <sys/systm.h>
32 : #include <sys/malloc.h>
33 : #include <sys/timeout.h>
34 : #include <sys/conf.h>
35 : #include <sys/device.h>
36 : #include <sys/endian.h>
37 :
38 : #if NBPFILTER > 0
39 : #include <net/bpf.h>
40 : #endif
41 : #include <net/if.h>
42 : #include <net/if_dl.h>
43 : #include <net/if_media.h>
44 :
45 : #include <netinet/in.h>
46 : #include <netinet/if_ether.h>
47 :
48 : #include <net80211/ieee80211_var.h>
49 : #include <net80211/ieee80211_amrr.h>
50 : #include <net80211/ieee80211_radiotap.h>
51 :
52 : #include <dev/usb/usb.h>
53 : #include <dev/usb/usbdi.h>
54 : #include <dev/usb/usbdi_util.h>
55 : #include <dev/usb/usbdevs.h>
56 :
57 : #include <dev/usb/if_zydreg.h>
58 :
59 : #ifdef ZYD_DEBUG
60 : #define DPRINTF(x) do { if (zyddebug > 0) printf x; } while (0)
61 : #define DPRINTFN(n, x) do { if (zyddebug > (n)) printf x; } while (0)
62 : int zyddebug = 0;
63 : #else
64 : #define DPRINTF(x)
65 : #define DPRINTFN(n, x)
66 : #endif
67 :
68 : static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
69 : static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
70 :
71 : /* various supported device vendors/products */
72 : #define ZYD_ZD1211_DEV(v, p) \
73 : { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211 }
74 : #define ZYD_ZD1211B_DEV(v, p) \
75 : { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B }
76 : static const struct zyd_type {
77 : struct usb_devno dev;
78 : uint8_t rev;
79 : #define ZYD_ZD1211 0
80 : #define ZYD_ZD1211B 1
81 : } zyd_devs[] = {
82 : ZYD_ZD1211_DEV(3COM2, 3CRUSB10075),
83 : ZYD_ZD1211_DEV(ABOCOM, WL54),
84 : ZYD_ZD1211_DEV(ASUS, WL159G),
85 : ZYD_ZD1211_DEV(CYBERTAN, TG54USB),
86 : ZYD_ZD1211_DEV(DRAYTEK, VIGOR550),
87 : ZYD_ZD1211_DEV(PLANEX2, GWUS54GD),
88 : ZYD_ZD1211_DEV(PLANEX2, GWUS54GZL),
89 : ZYD_ZD1211_DEV(PLANEX3, GWUS54GZ),
90 : ZYD_ZD1211_DEV(PLANEX3, GWUS54MINI),
91 : ZYD_ZD1211_DEV(SAGEM, XG760A),
92 : ZYD_ZD1211_DEV(SENAO, NUB8301),
93 : ZYD_ZD1211_DEV(SITECOMEU, WL113),
94 : ZYD_ZD1211_DEV(SWEEX, ZD1211),
95 : ZYD_ZD1211_DEV(TEKRAM, QUICKWLAN),
96 : ZYD_ZD1211_DEV(TEKRAM, ZD1211_1),
97 : ZYD_ZD1211_DEV(TEKRAM, ZD1211_2),
98 : ZYD_ZD1211_DEV(TWINMOS, G240),
99 : ZYD_ZD1211_DEV(UMEDIA, ALL0298V2),
100 : ZYD_ZD1211_DEV(UMEDIA, TEW429UB_A),
101 : ZYD_ZD1211_DEV(UMEDIA, TEW429UB),
102 : ZYD_ZD1211_DEV(UNKNOWN2, NW3100),
103 : ZYD_ZD1211_DEV(WISTRONNEWEB, UR055G),
104 : ZYD_ZD1211_DEV(ZCOM, ZD1211),
105 : ZYD_ZD1211_DEV(ZYDAS, ALL0298),
106 : ZYD_ZD1211_DEV(ZYDAS, ZD1211),
107 : ZYD_ZD1211_DEV(ZYXEL, AG225H),
108 : ZYD_ZD1211_DEV(ZYXEL, G200V2),
109 : ZYD_ZD1211_DEV(ZYXEL, G202),
110 : ZYD_ZD1211_DEV(ZYXEL, G220),
111 : ZYD_ZD1211_DEV(ZYXEL, G220F),
112 :
113 : ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG),
114 : ZYD_ZD1211B_DEV(ACCTON, WN4501H_LF_IR),
115 : ZYD_ZD1211B_DEV(ACCTON, WUS201),
116 : ZYD_ZD1211B_DEV(ACCTON, ZD1211B),
117 : ZYD_ZD1211B_DEV(ASUS, A9T_WIFI),
118 : ZYD_ZD1211B_DEV(BELKIN, F5D7050C),
119 : ZYD_ZD1211B_DEV(BELKIN, ZD1211B),
120 : ZYD_ZD1211B_DEV(BEWAN, BWIFI_USB54AR),
121 : ZYD_ZD1211B_DEV(CISCOLINKSYS, WUSBF54G),
122 : ZYD_ZD1211B_DEV(CYBERTAN, ZD1211B),
123 : ZYD_ZD1211B_DEV(FIBERLINE, WL430U),
124 : ZYD_ZD1211B_DEV(MELCO, KG54L),
125 : ZYD_ZD1211B_DEV(PHILIPS, SNU5600),
126 : ZYD_ZD1211B_DEV(PHILIPS, SNU5630NS05),
127 : ZYD_ZD1211B_DEV(PLANEX2, GW_US54GXS),
128 : ZYD_ZD1211B_DEV(PLANEX4, GWUS54ZGL),
129 : ZYD_ZD1211B_DEV(PLANEX4, ZD1211B),
130 : ZYD_ZD1211B_DEV(SAGEM, XG76NA),
131 : ZYD_ZD1211B_DEV(SITECOMEU, WL603),
132 : ZYD_ZD1211B_DEV(SITECOMEU, ZD1211B),
133 : ZYD_ZD1211B_DEV(UMEDIA, TEW429UBC1),
134 : ZYD_ZD1211B_DEV(UNKNOWN2, ZD1211B),
135 : ZYD_ZD1211B_DEV(UNKNOWN3, ZD1211B),
136 : ZYD_ZD1211B_DEV(SONY, IFU_WLM2),
137 : ZYD_ZD1211B_DEV(USR, USR5423),
138 : ZYD_ZD1211B_DEV(VTECH, ZD1211B),
139 : ZYD_ZD1211B_DEV(ZCOM, ZD1211B),
140 : ZYD_ZD1211B_DEV(ZYDAS, ZD1211B),
141 : ZYD_ZD1211B_DEV(ZYDAS, ZD1211B_2),
142 : ZYD_ZD1211B_DEV(ZYXEL, AG220),
143 : ZYD_ZD1211B_DEV(ZYXEL, AG225HV2),
144 : ZYD_ZD1211B_DEV(ZYXEL, G220V2),
145 : ZYD_ZD1211B_DEV(ZYXEL, M202)
146 : };
147 : #define zyd_lookup(v, p) \
148 : ((const struct zyd_type *)usb_lookup(zyd_devs, v, p))
149 :
150 : int zyd_match(struct device *, void *, void *);
151 : void zyd_attach(struct device *, struct device *, void *);
152 : int zyd_detach(struct device *, int);
153 :
154 : struct cfdriver zyd_cd = {
155 : NULL, "zyd", DV_IFNET
156 : };
157 :
158 : const struct cfattach zyd_ca = {
159 : sizeof(struct zyd_softc), zyd_match, zyd_attach, zyd_detach
160 : };
161 :
162 : void zyd_attachhook(struct device *);
163 : int zyd_complete_attach(struct zyd_softc *);
164 : int zyd_open_pipes(struct zyd_softc *);
165 : void zyd_close_pipes(struct zyd_softc *);
166 : int zyd_alloc_tx_list(struct zyd_softc *);
167 : void zyd_free_tx_list(struct zyd_softc *);
168 : int zyd_alloc_rx_list(struct zyd_softc *);
169 : void zyd_free_rx_list(struct zyd_softc *);
170 : struct ieee80211_node *zyd_node_alloc(struct ieee80211com *);
171 : int zyd_media_change(struct ifnet *);
172 : void zyd_next_scan(void *);
173 : void zyd_task(void *);
174 : int zyd_newstate(struct ieee80211com *, enum ieee80211_state, int);
175 : int zyd_cmd_read(struct zyd_softc *, const void *, size_t, int);
176 : int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
177 : int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
178 : int zyd_cmd_write(struct zyd_softc *, u_int16_t, const void *, int);
179 : int zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
180 : int zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
181 : int zyd_rfwrite(struct zyd_softc *, uint32_t);
182 : void zyd_lock_phy(struct zyd_softc *);
183 : void zyd_unlock_phy(struct zyd_softc *);
184 : int zyd_rfmd_init(struct zyd_rf *);
185 : int zyd_rfmd_switch_radio(struct zyd_rf *, int);
186 : int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t);
187 : int zyd_al2230_init(struct zyd_rf *);
188 : int zyd_al2230_switch_radio(struct zyd_rf *, int);
189 : int zyd_al2230_set_channel(struct zyd_rf *, uint8_t);
190 : int zyd_al2230_init_b(struct zyd_rf *);
191 : int zyd_al7230B_init(struct zyd_rf *);
192 : int zyd_al7230B_switch_radio(struct zyd_rf *, int);
193 : int zyd_al7230B_set_channel(struct zyd_rf *, uint8_t);
194 : int zyd_al2210_init(struct zyd_rf *);
195 : int zyd_al2210_switch_radio(struct zyd_rf *, int);
196 : int zyd_al2210_set_channel(struct zyd_rf *, uint8_t);
197 : int zyd_gct_init(struct zyd_rf *);
198 : int zyd_gct_switch_radio(struct zyd_rf *, int);
199 : int zyd_gct_set_channel(struct zyd_rf *, uint8_t);
200 : int zyd_maxim_init(struct zyd_rf *);
201 : int zyd_maxim_switch_radio(struct zyd_rf *, int);
202 : int zyd_maxim_set_channel(struct zyd_rf *, uint8_t);
203 : int zyd_maxim2_init(struct zyd_rf *);
204 : int zyd_maxim2_switch_radio(struct zyd_rf *, int);
205 : int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t);
206 : int zyd_rf_attach(struct zyd_softc *, uint8_t);
207 : const char *zyd_rf_name(uint8_t);
208 : int zyd_hw_init(struct zyd_softc *);
209 : int zyd_read_eeprom(struct zyd_softc *);
210 : void zyd_set_multi(struct zyd_softc *);
211 : void zyd_set_macaddr(struct zyd_softc *, const uint8_t *);
212 : void zyd_set_bssid(struct zyd_softc *, const uint8_t *);
213 : int zyd_switch_radio(struct zyd_softc *, int);
214 : void zyd_set_led(struct zyd_softc *, int, int);
215 : int zyd_set_rxfilter(struct zyd_softc *);
216 : void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *);
217 : int zyd_set_beacon_interval(struct zyd_softc *, int);
218 : uint8_t zyd_plcp_signal(int);
219 : void zyd_intr(struct usbd_xfer *, void *, usbd_status);
220 : void zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t);
221 : void zyd_rxeof(struct usbd_xfer *, void *, usbd_status);
222 : void zyd_txeof(struct usbd_xfer *, void *, usbd_status);
223 : int zyd_tx(struct zyd_softc *, struct mbuf *,
224 : struct ieee80211_node *);
225 : void zyd_start(struct ifnet *);
226 : void zyd_watchdog(struct ifnet *);
227 : int zyd_ioctl(struct ifnet *, u_long, caddr_t);
228 : int zyd_init(struct ifnet *);
229 : void zyd_stop(struct ifnet *, int);
230 : int zyd_loadfirmware(struct zyd_softc *, u_char *, size_t);
231 : void zyd_iter_func(void *, struct ieee80211_node *);
232 : void zyd_amrr_timeout(void *);
233 : void zyd_newassoc(struct ieee80211com *, struct ieee80211_node *,
234 : int);
235 :
236 : int
237 0 : zyd_match(struct device *parent, void *match, void *aux)
238 : {
239 0 : struct usb_attach_arg *uaa = aux;
240 :
241 0 : if (!uaa->iface)
242 0 : return UMATCH_NONE;
243 :
244 0 : return (zyd_lookup(uaa->vendor, uaa->product) != NULL) ?
245 : UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
246 0 : }
247 :
248 : void
249 0 : zyd_attachhook(struct device *self)
250 : {
251 0 : struct zyd_softc *sc = (struct zyd_softc *)self;
252 : const char *fwname;
253 0 : u_char *fw;
254 0 : size_t fwsize;
255 : int error;
256 :
257 0 : fwname = (sc->mac_rev == ZYD_ZD1211) ? "zd1211" : "zd1211b";
258 0 : if ((error = loadfirmware(fwname, &fw, &fwsize)) != 0) {
259 0 : printf("%s: error %d, could not read firmware file %s\n",
260 0 : sc->sc_dev.dv_xname, error, fwname);
261 0 : return;
262 : }
263 :
264 0 : error = zyd_loadfirmware(sc, fw, fwsize);
265 0 : free(fw, M_DEVBUF, fwsize);
266 0 : if (error != 0) {
267 0 : printf("%s: could not load firmware (error=%d)\n",
268 0 : sc->sc_dev.dv_xname, error);
269 0 : return;
270 : }
271 :
272 : /* complete the attach process */
273 0 : if (zyd_complete_attach(sc) == 0)
274 0 : sc->attached = 1;
275 0 : }
276 :
277 : void
278 0 : zyd_attach(struct device *parent, struct device *self, void *aux)
279 : {
280 0 : struct zyd_softc *sc = (struct zyd_softc *)self;
281 0 : struct usb_attach_arg *uaa = aux;
282 : usb_device_descriptor_t* ddesc;
283 :
284 0 : sc->sc_udev = uaa->device;
285 :
286 0 : sc->mac_rev = zyd_lookup(uaa->vendor, uaa->product)->rev;
287 :
288 0 : ddesc = usbd_get_device_descriptor(sc->sc_udev);
289 0 : if (UGETW(ddesc->bcdDevice) < 0x4330) {
290 0 : printf("%s: device version mismatch: 0x%x "
291 0 : "(only >= 43.30 supported)\n", sc->sc_dev.dv_xname,
292 : UGETW(ddesc->bcdDevice));
293 0 : return;
294 : }
295 :
296 0 : config_mountroot(self, zyd_attachhook);
297 0 : }
298 :
299 : int
300 0 : zyd_complete_attach(struct zyd_softc *sc)
301 : {
302 0 : struct ieee80211com *ic = &sc->sc_ic;
303 0 : struct ifnet *ifp = &ic->ic_if;
304 : usbd_status error;
305 : int i;
306 :
307 0 : usb_init_task(&sc->sc_task, zyd_task, sc, USB_TASK_TYPE_GENERIC);
308 0 : timeout_set(&sc->scan_to, zyd_next_scan, sc);
309 :
310 0 : sc->amrr.amrr_min_success_threshold = 1;
311 0 : sc->amrr.amrr_max_success_threshold = 10;
312 0 : timeout_set(&sc->amrr_to, zyd_amrr_timeout, sc);
313 :
314 0 : error = usbd_set_config_no(sc->sc_udev, ZYD_CONFIG_NO, 1);
315 0 : if (error != 0) {
316 0 : printf("%s: setting config no failed\n",
317 0 : sc->sc_dev.dv_xname);
318 0 : goto fail;
319 : }
320 :
321 0 : error = usbd_device2interface_handle(sc->sc_udev, ZYD_IFACE_INDEX,
322 0 : &sc->sc_iface);
323 0 : if (error != 0) {
324 0 : printf("%s: getting interface handle failed\n",
325 0 : sc->sc_dev.dv_xname);
326 0 : goto fail;
327 : }
328 :
329 0 : if ((error = zyd_open_pipes(sc)) != 0) {
330 0 : printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
331 0 : goto fail;
332 : }
333 :
334 0 : if ((error = zyd_read_eeprom(sc)) != 0) {
335 0 : printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
336 0 : goto fail;
337 : }
338 :
339 0 : if ((error = zyd_rf_attach(sc, sc->rf_rev)) != 0) {
340 0 : printf("%s: could not attach RF\n", sc->sc_dev.dv_xname);
341 0 : goto fail;
342 : }
343 :
344 0 : if ((error = zyd_hw_init(sc)) != 0) {
345 0 : printf("%s: hardware initialization failed\n",
346 : sc->sc_dev.dv_xname);
347 0 : goto fail;
348 : }
349 :
350 0 : printf("%s: HMAC ZD1211%s, FW %02x.%02x, RF %s, PA %x, address %s\n",
351 0 : sc->sc_dev.dv_xname, (sc->mac_rev == ZYD_ZD1211) ? "": "B",
352 0 : sc->fw_rev >> 8, sc->fw_rev & 0xff, zyd_rf_name(sc->rf_rev),
353 0 : sc->pa_rev, ether_sprintf(ic->ic_myaddr));
354 :
355 0 : ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
356 0 : ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
357 0 : ic->ic_state = IEEE80211_S_INIT;
358 :
359 : /* set device capabilities */
360 0 : ic->ic_caps =
361 : IEEE80211_C_MONITOR | /* monitor mode supported */
362 : IEEE80211_C_TXPMGT | /* tx power management */
363 : IEEE80211_C_SHPREAMBLE | /* short preamble supported */
364 : IEEE80211_C_WEP | /* s/w WEP */
365 : IEEE80211_C_RSN; /* WPA/RSN */
366 :
367 : /* set supported .11b and .11g rates */
368 0 : ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
369 0 : ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
370 :
371 : /* set supported .11b and .11g channels (1 through 14) */
372 0 : for (i = 1; i <= 14; i++) {
373 0 : ic->ic_channels[i].ic_freq =
374 0 : ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
375 0 : ic->ic_channels[i].ic_flags =
376 : IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
377 : IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
378 : }
379 :
380 0 : ifp->if_softc = sc;
381 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
382 0 : ifp->if_ioctl = zyd_ioctl;
383 0 : ifp->if_start = zyd_start;
384 0 : ifp->if_watchdog = zyd_watchdog;
385 0 : memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
386 :
387 0 : if_attach(ifp);
388 0 : ieee80211_ifattach(ifp);
389 0 : ic->ic_node_alloc = zyd_node_alloc;
390 0 : ic->ic_newassoc = zyd_newassoc;
391 :
392 : /* override state transition machine */
393 0 : sc->sc_newstate = ic->ic_newstate;
394 0 : ic->ic_newstate = zyd_newstate;
395 0 : ieee80211_media_init(ifp, zyd_media_change, ieee80211_media_status);
396 :
397 : #if NBPFILTER > 0
398 0 : bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
399 : sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
400 :
401 0 : sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
402 0 : sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
403 0 : sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT);
404 :
405 0 : sc->sc_txtap_len = sizeof sc->sc_txtapu;
406 0 : sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
407 0 : sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT);
408 : #endif
409 :
410 0 : fail: return error;
411 : }
412 :
413 : int
414 0 : zyd_detach(struct device *self, int flags)
415 : {
416 0 : struct zyd_softc *sc = (struct zyd_softc *)self;
417 0 : struct ifnet *ifp = &sc->sc_ic.ic_if;
418 : int s;
419 :
420 0 : s = splusb();
421 :
422 0 : usb_rem_task(sc->sc_udev, &sc->sc_task);
423 0 : if (timeout_initialized(&sc->scan_to))
424 0 : timeout_del(&sc->scan_to);
425 0 : if (timeout_initialized(&sc->amrr_to))
426 0 : timeout_del(&sc->amrr_to);
427 :
428 0 : zyd_close_pipes(sc);
429 :
430 0 : if (!sc->attached) {
431 0 : splx(s);
432 0 : return 0;
433 : }
434 :
435 0 : if (ifp->if_softc != NULL) {
436 0 : ieee80211_ifdetach(ifp);
437 0 : if_detach(ifp);
438 0 : }
439 :
440 0 : zyd_free_rx_list(sc);
441 0 : zyd_free_tx_list(sc);
442 :
443 0 : sc->attached = 0;
444 :
445 0 : splx(s);
446 :
447 0 : return 0;
448 0 : }
449 :
450 : int
451 0 : zyd_open_pipes(struct zyd_softc *sc)
452 : {
453 : usb_endpoint_descriptor_t *edesc;
454 : int isize;
455 : usbd_status error;
456 :
457 : /* interrupt in */
458 0 : edesc = usbd_get_endpoint_descriptor(sc->sc_iface, 0x83);
459 0 : if (edesc == NULL)
460 0 : return EINVAL;
461 :
462 0 : isize = UGETW(edesc->wMaxPacketSize);
463 0 : if (isize == 0) /* should not happen */
464 0 : return EINVAL;
465 :
466 0 : sc->ibuf = malloc(isize, M_USBDEV, M_NOWAIT);
467 0 : if (sc->ibuf == NULL)
468 0 : return ENOMEM;
469 0 : sc->ibuflen = isize;
470 0 : error = usbd_open_pipe_intr(sc->sc_iface, 0x83, USBD_SHORT_XFER_OK,
471 0 : &sc->zyd_ep[ZYD_ENDPT_IIN], sc, sc->ibuf, isize, zyd_intr,
472 : USBD_DEFAULT_INTERVAL);
473 0 : if (error != 0) {
474 0 : printf("%s: open rx intr pipe failed: %s\n",
475 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
476 0 : goto fail;
477 : }
478 :
479 : /* interrupt out (not necessarily an interrupt pipe) */
480 0 : error = usbd_open_pipe(sc->sc_iface, 0x04, USBD_EXCLUSIVE_USE,
481 0 : &sc->zyd_ep[ZYD_ENDPT_IOUT]);
482 0 : if (error != 0) {
483 0 : printf("%s: open tx intr pipe failed: %s\n",
484 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
485 0 : goto fail;
486 : }
487 :
488 : /* bulk in */
489 0 : error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE,
490 0 : &sc->zyd_ep[ZYD_ENDPT_BIN]);
491 0 : if (error != 0) {
492 0 : printf("%s: open rx pipe failed: %s\n",
493 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
494 0 : goto fail;
495 : }
496 :
497 : /* bulk out */
498 0 : error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE,
499 0 : &sc->zyd_ep[ZYD_ENDPT_BOUT]);
500 0 : if (error != 0) {
501 0 : printf("%s: open tx pipe failed: %s\n",
502 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
503 0 : goto fail;
504 : }
505 :
506 0 : return 0;
507 :
508 0 : fail: zyd_close_pipes(sc);
509 0 : return error;
510 0 : }
511 :
512 : void
513 0 : zyd_close_pipes(struct zyd_softc *sc)
514 : {
515 : int i;
516 :
517 0 : for (i = 0; i < ZYD_ENDPT_CNT; i++) {
518 0 : if (sc->zyd_ep[i] != NULL) {
519 0 : usbd_abort_pipe(sc->zyd_ep[i]);
520 0 : usbd_close_pipe(sc->zyd_ep[i]);
521 0 : sc->zyd_ep[i] = NULL;
522 0 : }
523 : }
524 0 : if (sc->ibuf != NULL) {
525 0 : free(sc->ibuf, M_USBDEV, sc->ibuflen);
526 0 : sc->ibuf = NULL;
527 0 : }
528 0 : }
529 :
530 : int
531 0 : zyd_alloc_tx_list(struct zyd_softc *sc)
532 : {
533 : int i, error;
534 :
535 0 : sc->tx_queued = 0;
536 :
537 0 : for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
538 0 : struct zyd_tx_data *data = &sc->tx_data[i];
539 :
540 0 : data->sc = sc; /* backpointer for callbacks */
541 :
542 0 : data->xfer = usbd_alloc_xfer(sc->sc_udev);
543 0 : if (data->xfer == NULL) {
544 0 : printf("%s: could not allocate tx xfer\n",
545 0 : sc->sc_dev.dv_xname);
546 : error = ENOMEM;
547 0 : goto fail;
548 : }
549 0 : data->buf = usbd_alloc_buffer(data->xfer, ZYD_MAX_TXBUFSZ);
550 0 : if (data->buf == NULL) {
551 0 : printf("%s: could not allocate tx buffer\n",
552 0 : sc->sc_dev.dv_xname);
553 : error = ENOMEM;
554 0 : goto fail;
555 : }
556 :
557 : /* clear Tx descriptor */
558 0 : bzero(data->buf, sizeof (struct zyd_tx_desc));
559 0 : }
560 0 : return 0;
561 :
562 0 : fail: zyd_free_tx_list(sc);
563 0 : return error;
564 0 : }
565 :
566 : void
567 0 : zyd_free_tx_list(struct zyd_softc *sc)
568 : {
569 0 : struct ieee80211com *ic = &sc->sc_ic;
570 : int i;
571 :
572 0 : for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
573 0 : struct zyd_tx_data *data = &sc->tx_data[i];
574 :
575 0 : if (data->xfer != NULL) {
576 0 : usbd_free_xfer(data->xfer);
577 0 : data->xfer = NULL;
578 0 : }
579 0 : if (data->ni != NULL) {
580 0 : ieee80211_release_node(ic, data->ni);
581 0 : data->ni = NULL;
582 0 : }
583 : }
584 0 : }
585 :
586 : int
587 0 : zyd_alloc_rx_list(struct zyd_softc *sc)
588 : {
589 : int i, error;
590 :
591 0 : for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
592 0 : struct zyd_rx_data *data = &sc->rx_data[i];
593 :
594 0 : data->sc = sc; /* backpointer for callbacks */
595 :
596 0 : data->xfer = usbd_alloc_xfer(sc->sc_udev);
597 0 : if (data->xfer == NULL) {
598 0 : printf("%s: could not allocate rx xfer\n",
599 0 : sc->sc_dev.dv_xname);
600 : error = ENOMEM;
601 0 : goto fail;
602 : }
603 0 : data->buf = usbd_alloc_buffer(data->xfer, ZYX_MAX_RXBUFSZ);
604 0 : if (data->buf == NULL) {
605 0 : printf("%s: could not allocate rx buffer\n",
606 0 : sc->sc_dev.dv_xname);
607 : error = ENOMEM;
608 0 : goto fail;
609 : }
610 0 : }
611 0 : return 0;
612 :
613 0 : fail: zyd_free_rx_list(sc);
614 0 : return error;
615 0 : }
616 :
617 : void
618 0 : zyd_free_rx_list(struct zyd_softc *sc)
619 : {
620 : int i;
621 :
622 0 : for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
623 0 : struct zyd_rx_data *data = &sc->rx_data[i];
624 :
625 0 : if (data->xfer != NULL) {
626 0 : usbd_free_xfer(data->xfer);
627 0 : data->xfer = NULL;
628 0 : }
629 : }
630 0 : }
631 :
632 : struct ieee80211_node *
633 0 : zyd_node_alloc(struct ieee80211com *ic)
634 : {
635 0 : return malloc(sizeof (struct zyd_node), M_DEVBUF, M_NOWAIT | M_ZERO);
636 : }
637 :
638 : int
639 0 : zyd_media_change(struct ifnet *ifp)
640 : {
641 : int error;
642 :
643 0 : error = ieee80211_media_change(ifp);
644 0 : if (error != ENETRESET)
645 0 : return error;
646 :
647 0 : if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
648 0 : zyd_init(ifp);
649 :
650 0 : return 0;
651 0 : }
652 :
653 : /*
654 : * This function is called periodically (every 200ms) during scanning to
655 : * switch from one channel to another.
656 : */
657 : void
658 0 : zyd_next_scan(void *arg)
659 : {
660 0 : struct zyd_softc *sc = arg;
661 0 : struct ieee80211com *ic = &sc->sc_ic;
662 0 : struct ifnet *ifp = &ic->ic_if;
663 :
664 0 : if (ic->ic_state == IEEE80211_S_SCAN)
665 0 : ieee80211_next_scan(ifp);
666 0 : }
667 :
668 : void
669 0 : zyd_task(void *arg)
670 : {
671 0 : struct zyd_softc *sc = arg;
672 0 : struct ieee80211com *ic = &sc->sc_ic;
673 : enum ieee80211_state ostate;
674 :
675 0 : ostate = ic->ic_state;
676 :
677 0 : switch (sc->sc_state) {
678 : case IEEE80211_S_INIT:
679 0 : if (ostate == IEEE80211_S_RUN) {
680 : /* turn link LED off */
681 0 : zyd_set_led(sc, ZYD_LED1, 0);
682 :
683 : /* stop data LED from blinking */
684 0 : zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 0);
685 0 : }
686 : break;
687 :
688 : case IEEE80211_S_SCAN:
689 0 : zyd_set_chan(sc, ic->ic_bss->ni_chan);
690 0 : timeout_add_msec(&sc->scan_to, 200);
691 0 : break;
692 :
693 : case IEEE80211_S_AUTH:
694 : case IEEE80211_S_ASSOC:
695 0 : zyd_set_chan(sc, ic->ic_bss->ni_chan);
696 0 : break;
697 :
698 : case IEEE80211_S_RUN:
699 : {
700 0 : struct ieee80211_node *ni = ic->ic_bss;
701 :
702 0 : zyd_set_chan(sc, ni->ni_chan);
703 :
704 0 : if (ic->ic_opmode != IEEE80211_M_MONITOR) {
705 : /* turn link LED on */
706 0 : zyd_set_led(sc, ZYD_LED1, 1);
707 :
708 : /* make data LED blink upon Tx */
709 0 : zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 1);
710 :
711 0 : zyd_set_bssid(sc, ni->ni_bssid);
712 0 : }
713 :
714 0 : if (ic->ic_opmode == IEEE80211_M_STA) {
715 : /* fake a join to init the tx rate */
716 0 : zyd_newassoc(ic, ni, 1);
717 0 : }
718 :
719 : /* start automatic rate control timer */
720 0 : if (ic->ic_fixed_rate == -1)
721 0 : timeout_add_sec(&sc->amrr_to, 1);
722 :
723 : break;
724 : }
725 : }
726 :
727 0 : sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
728 0 : }
729 :
730 : int
731 0 : zyd_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
732 : {
733 0 : struct zyd_softc *sc = ic->ic_softc;
734 :
735 0 : usb_rem_task(sc->sc_udev, &sc->sc_task);
736 0 : timeout_del(&sc->scan_to);
737 0 : timeout_del(&sc->amrr_to);
738 :
739 : /* do it in a process context */
740 0 : sc->sc_state = nstate;
741 0 : sc->sc_arg = arg;
742 0 : usb_add_task(sc->sc_udev, &sc->sc_task);
743 :
744 0 : return 0;
745 : }
746 :
747 : /*
748 : * Issue a read command for the specificed register (of size regsize)
749 : * and await a reply of olen bytes in sc->odata.
750 : */
751 : int
752 0 : zyd_cmd_read(struct zyd_softc *sc, const void *reg, size_t regsize, int olen)
753 : {
754 : struct usbd_xfer *xfer;
755 0 : struct zyd_cmd cmd;
756 : usbd_status error;
757 : int s;
758 :
759 0 : if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
760 0 : return ENOMEM;
761 :
762 0 : bzero(&cmd, sizeof(cmd));
763 0 : cmd.code = htole16(ZYD_CMD_IORD);
764 0 : bcopy(reg, cmd.data, regsize);
765 :
766 0 : bzero(sc->odata, sizeof(sc->odata));
767 0 : sc->olen = olen;
768 :
769 0 : usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0,
770 0 : &cmd, sizeof(cmd.code) + regsize,
771 : USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS,
772 : ZYD_INTR_TIMEOUT, NULL);
773 0 : s = splusb();
774 0 : sc->odone = 0;
775 0 : error = usbd_transfer(xfer);
776 0 : splx(s);
777 0 : if (error) {
778 0 : printf("%s: could not send command: %s\n",
779 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
780 0 : usbd_free_xfer(xfer);
781 0 : return EIO;
782 : }
783 :
784 0 : if (!sc->odone) {
785 : /* wait for ZYD_NOTIF_IORD interrupt */
786 0 : if (tsleep(sc, PWAIT, "zydcmd", ZYD_INTR_TIMEOUT) != 0)
787 0 : printf("%s: read command failed\n",
788 0 : sc->sc_dev.dv_xname);
789 : }
790 0 : usbd_free_xfer(xfer);
791 :
792 0 : return error;
793 0 : }
794 :
795 : int
796 0 : zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val)
797 : {
798 : struct zyd_io *odata;
799 : int error;
800 :
801 0 : reg = htole16(reg);
802 0 : error = zyd_cmd_read(sc, ®, sizeof(reg), sizeof(*odata));
803 0 : if (error == 0) {
804 0 : odata = (struct zyd_io *)sc->odata;
805 0 : *val = letoh16(odata[0].val);
806 0 : }
807 0 : return error;
808 : }
809 :
810 : int
811 0 : zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val)
812 : {
813 : struct zyd_io *odata;
814 0 : uint16_t regs[2];
815 : int error;
816 :
817 0 : regs[0] = htole16(ZYD_REG32_HI(reg));
818 0 : regs[1] = htole16(ZYD_REG32_LO(reg));
819 0 : error = zyd_cmd_read(sc, regs, sizeof(regs), sizeof(*odata) * 2);
820 0 : if (error == 0) {
821 0 : odata = (struct zyd_io *)sc->odata;
822 0 : *val = letoh16(odata[0].val) << 16 | letoh16(odata[1].val);
823 0 : }
824 0 : return error;
825 0 : }
826 :
827 : int
828 0 : zyd_cmd_write(struct zyd_softc *sc, u_int16_t code, const void *data, int len)
829 : {
830 : struct usbd_xfer *xfer;
831 0 : struct zyd_cmd cmd;
832 : usbd_status error;
833 :
834 0 : if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
835 0 : return ENOMEM;
836 :
837 0 : bzero(&cmd, sizeof(cmd));
838 0 : cmd.code = htole16(code);
839 0 : bcopy(data, cmd.data, len);
840 :
841 0 : usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0,
842 0 : &cmd, sizeof(cmd.code) + len,
843 : USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS,
844 : ZYD_INTR_TIMEOUT, NULL);
845 0 : error = usbd_transfer(xfer);
846 0 : if (error)
847 0 : printf("%s: could not send command: %s\n",
848 0 : sc->sc_dev.dv_xname, usbd_errstr(error));
849 :
850 0 : usbd_free_xfer(xfer);
851 0 : return error;
852 0 : }
853 :
854 : int
855 0 : zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
856 : {
857 0 : struct zyd_io io;
858 :
859 0 : io.reg = htole16(reg);
860 0 : io.val = htole16(val);
861 0 : return zyd_cmd_write(sc, ZYD_CMD_IOWR, &io, sizeof(io));
862 0 : }
863 :
864 : int
865 0 : zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
866 : {
867 0 : struct zyd_io io[2];
868 :
869 0 : io[0].reg = htole16(ZYD_REG32_HI(reg));
870 0 : io[0].val = htole16(val >> 16);
871 0 : io[1].reg = htole16(ZYD_REG32_LO(reg));
872 0 : io[1].val = htole16(val & 0xffff);
873 :
874 0 : return zyd_cmd_write(sc, ZYD_CMD_IOWR, io, sizeof(io));
875 0 : }
876 :
877 : int
878 0 : zyd_rfwrite(struct zyd_softc *sc, uint32_t val)
879 : {
880 0 : struct zyd_rf *rf = &sc->sc_rf;
881 0 : struct zyd_rfwrite req;
882 0 : uint16_t cr203;
883 : int i;
884 :
885 0 : (void)zyd_read16(sc, ZYD_CR203, &cr203);
886 0 : cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA);
887 :
888 0 : req.code = htole16(2);
889 0 : req.width = htole16(rf->width);
890 0 : for (i = 0; i < rf->width; i++) {
891 0 : req.bit[i] = htole16(cr203);
892 0 : if (val & (1 << (rf->width - 1 - i)))
893 0 : req.bit[i] |= htole16(ZYD_RF_DATA);
894 : }
895 0 : return zyd_cmd_write(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width);
896 0 : }
897 :
898 : void
899 0 : zyd_lock_phy(struct zyd_softc *sc)
900 : {
901 0 : uint32_t tmp;
902 :
903 0 : (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
904 0 : tmp &= ~ZYD_UNLOCK_PHY_REGS;
905 0 : (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
906 0 : }
907 :
908 : void
909 0 : zyd_unlock_phy(struct zyd_softc *sc)
910 : {
911 0 : uint32_t tmp;
912 :
913 0 : (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
914 0 : tmp |= ZYD_UNLOCK_PHY_REGS;
915 0 : (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
916 0 : }
917 :
918 : /*
919 : * RFMD RF methods.
920 : */
921 : int
922 0 : zyd_rfmd_init(struct zyd_rf *rf)
923 : {
924 0 : struct zyd_softc *sc = rf->rf_sc;
925 : static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY;
926 : static const uint32_t rfini[] = ZYD_RFMD_RF;
927 : int i, error;
928 :
929 : /* init RF-dependent PHY registers */
930 0 : for (i = 0; i < nitems(phyini); i++) {
931 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
932 0 : if (error != 0)
933 0 : return error;
934 : }
935 :
936 : /* init RFMD radio */
937 0 : for (i = 0; i < nitems(rfini); i++) {
938 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
939 0 : return error;
940 : }
941 0 : return 0;
942 0 : }
943 :
944 : int
945 0 : zyd_rfmd_switch_radio(struct zyd_rf *rf, int on)
946 : {
947 0 : struct zyd_softc *sc = rf->rf_sc;
948 :
949 0 : (void)zyd_write16(sc, ZYD_CR10, on ? 0x89 : 0x15);
950 0 : (void)zyd_write16(sc, ZYD_CR11, on ? 0x00 : 0x81);
951 :
952 0 : return 0;
953 : }
954 :
955 : int
956 0 : zyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan)
957 : {
958 0 : struct zyd_softc *sc = rf->rf_sc;
959 : static const struct {
960 : uint32_t r1, r2;
961 : } rfprog[] = ZYD_RFMD_CHANTABLE;
962 :
963 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
964 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
965 :
966 0 : return 0;
967 : }
968 :
969 : /*
970 : * AL2230 RF methods.
971 : */
972 : int
973 0 : zyd_al2230_init(struct zyd_rf *rf)
974 : {
975 0 : struct zyd_softc *sc = rf->rf_sc;
976 : static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY;
977 : static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT;
978 : static const uint32_t rfini[] = ZYD_AL2230_RF;
979 : int i, error;
980 :
981 : /* init RF-dependent PHY registers */
982 0 : for (i = 0; i < nitems(phyini); i++) {
983 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
984 0 : if (error != 0)
985 0 : return error;
986 : }
987 0 : if (sc->rf_rev == ZYD_RF_AL2230S) {
988 0 : for (i = 0; i < nitems(phy2230s); i++) {
989 0 : error = zyd_write16(sc, phy2230s[i].reg,
990 0 : phy2230s[i].val);
991 0 : if (error != 0)
992 0 : return error;
993 : }
994 : }
995 : /* init AL2230 radio */
996 0 : for (i = 0; i < nitems(rfini); i++) {
997 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
998 0 : return error;
999 : }
1000 0 : return 0;
1001 0 : }
1002 :
1003 : int
1004 0 : zyd_al2230_init_b(struct zyd_rf *rf)
1005 : {
1006 0 : struct zyd_softc *sc = rf->rf_sc;
1007 : static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B;
1008 : static const uint32_t rfini[] = ZYD_AL2230_RF_B;
1009 : int i, error;
1010 :
1011 : /* init RF-dependent PHY registers */
1012 0 : for (i = 0; i < nitems(phyini); i++) {
1013 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1014 0 : if (error != 0)
1015 0 : return error;
1016 : }
1017 :
1018 : /* init AL2230 radio */
1019 0 : for (i = 0; i < nitems(rfini); i++) {
1020 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1021 0 : return error;
1022 : }
1023 0 : return 0;
1024 0 : }
1025 :
1026 : int
1027 0 : zyd_al2230_switch_radio(struct zyd_rf *rf, int on)
1028 : {
1029 0 : struct zyd_softc *sc = rf->rf_sc;
1030 0 : int on251 = (sc->mac_rev == ZYD_ZD1211) ? 0x3f : 0x7f;
1031 :
1032 0 : (void)zyd_write16(sc, ZYD_CR11, on ? 0x00 : 0x04);
1033 0 : (void)zyd_write16(sc, ZYD_CR251, on ? on251 : 0x2f);
1034 :
1035 0 : return 0;
1036 : }
1037 :
1038 : int
1039 0 : zyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan)
1040 : {
1041 0 : struct zyd_softc *sc = rf->rf_sc;
1042 : static const struct {
1043 : uint32_t r1, r2, r3;
1044 : } rfprog[] = ZYD_AL2230_CHANTABLE;
1045 :
1046 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1047 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1048 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r3);
1049 :
1050 0 : (void)zyd_write16(sc, ZYD_CR138, 0x28);
1051 0 : (void)zyd_write16(sc, ZYD_CR203, 0x06);
1052 :
1053 0 : return 0;
1054 : }
1055 :
1056 : /*
1057 : * AL7230B RF methods.
1058 : */
1059 : int
1060 0 : zyd_al7230B_init(struct zyd_rf *rf)
1061 : {
1062 0 : struct zyd_softc *sc = rf->rf_sc;
1063 : static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1;
1064 : static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2;
1065 : static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3;
1066 : static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1;
1067 : static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2;
1068 : int i, error;
1069 :
1070 : /* for AL7230B, PHY and RF need to be initialized in "phases" */
1071 :
1072 : /* init RF-dependent PHY registers, part one */
1073 0 : for (i = 0; i < nitems(phyini_1); i++) {
1074 0 : error = zyd_write16(sc, phyini_1[i].reg, phyini_1[i].val);
1075 0 : if (error != 0)
1076 0 : return error;
1077 : }
1078 : /* init AL7230B radio, part one */
1079 0 : for (i = 0; i < nitems(rfini_1); i++) {
1080 0 : if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0)
1081 0 : return error;
1082 : }
1083 : /* init RF-dependent PHY registers, part two */
1084 0 : for (i = 0; i < nitems(phyini_2); i++) {
1085 0 : error = zyd_write16(sc, phyini_2[i].reg, phyini_2[i].val);
1086 0 : if (error != 0)
1087 0 : return error;
1088 : }
1089 : /* init AL7230B radio, part two */
1090 0 : for (i = 0; i < nitems(rfini_2); i++) {
1091 0 : if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0)
1092 0 : return error;
1093 : }
1094 : /* init RF-dependent PHY registers, part three */
1095 0 : for (i = 0; i < nitems(phyini_3); i++) {
1096 0 : error = zyd_write16(sc, phyini_3[i].reg, phyini_3[i].val);
1097 0 : if (error != 0)
1098 0 : return error;
1099 : }
1100 :
1101 0 : return 0;
1102 0 : }
1103 :
1104 : int
1105 0 : zyd_al7230B_switch_radio(struct zyd_rf *rf, int on)
1106 : {
1107 0 : struct zyd_softc *sc = rf->rf_sc;
1108 :
1109 0 : (void)zyd_write16(sc, ZYD_CR11, on ? 0x00 : 0x04);
1110 0 : (void)zyd_write16(sc, ZYD_CR251, on ? 0x3f : 0x2f);
1111 :
1112 0 : return 0;
1113 : }
1114 :
1115 : int
1116 0 : zyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan)
1117 : {
1118 0 : struct zyd_softc *sc = rf->rf_sc;
1119 : static const struct {
1120 : uint32_t r1, r2;
1121 : } rfprog[] = ZYD_AL7230B_CHANTABLE;
1122 : static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL;
1123 : int i, error;
1124 :
1125 0 : (void)zyd_write16(sc, ZYD_CR240, 0x57);
1126 0 : (void)zyd_write16(sc, ZYD_CR251, 0x2f);
1127 :
1128 0 : for (i = 0; i < nitems(rfsc); i++) {
1129 0 : if ((error = zyd_rfwrite(sc, rfsc[i])) != 0)
1130 0 : return error;
1131 : }
1132 :
1133 0 : (void)zyd_write16(sc, ZYD_CR128, 0x14);
1134 0 : (void)zyd_write16(sc, ZYD_CR129, 0x12);
1135 0 : (void)zyd_write16(sc, ZYD_CR130, 0x10);
1136 0 : (void)zyd_write16(sc, ZYD_CR38, 0x38);
1137 0 : (void)zyd_write16(sc, ZYD_CR136, 0xdf);
1138 :
1139 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1140 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1141 0 : (void)zyd_rfwrite(sc, 0x3c9000);
1142 :
1143 0 : (void)zyd_write16(sc, ZYD_CR251, 0x3f);
1144 0 : (void)zyd_write16(sc, ZYD_CR203, 0x06);
1145 0 : (void)zyd_write16(sc, ZYD_CR240, 0x08);
1146 :
1147 0 : return 0;
1148 0 : }
1149 :
1150 : /*
1151 : * AL2210 RF methods.
1152 : */
1153 : int
1154 0 : zyd_al2210_init(struct zyd_rf *rf)
1155 : {
1156 0 : struct zyd_softc *sc = rf->rf_sc;
1157 : static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY;
1158 : static const uint32_t rfini[] = ZYD_AL2210_RF;
1159 0 : uint32_t tmp;
1160 : int i, error;
1161 :
1162 0 : (void)zyd_write32(sc, ZYD_CR18, 2);
1163 :
1164 : /* init RF-dependent PHY registers */
1165 0 : for (i = 0; i < nitems(phyini); i++) {
1166 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1167 0 : if (error != 0)
1168 0 : return error;
1169 : }
1170 : /* init AL2210 radio */
1171 0 : for (i = 0; i < nitems(rfini); i++) {
1172 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1173 0 : return error;
1174 : }
1175 0 : (void)zyd_write16(sc, ZYD_CR47, 0x1e);
1176 0 : (void)zyd_read32(sc, ZYD_CR_RADIO_PD, &tmp);
1177 0 : (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1);
1178 0 : (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp | 1);
1179 0 : (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x05);
1180 0 : (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x00);
1181 0 : (void)zyd_write16(sc, ZYD_CR47, 0x1e);
1182 0 : (void)zyd_write32(sc, ZYD_CR18, 3);
1183 :
1184 0 : return 0;
1185 0 : }
1186 :
1187 : int
1188 0 : zyd_al2210_switch_radio(struct zyd_rf *rf, int on)
1189 : {
1190 : /* vendor driver does nothing for this RF chip */
1191 :
1192 0 : return 0;
1193 : }
1194 :
1195 : int
1196 0 : zyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan)
1197 : {
1198 0 : struct zyd_softc *sc = rf->rf_sc;
1199 : static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE;
1200 0 : uint32_t tmp;
1201 :
1202 0 : (void)zyd_write32(sc, ZYD_CR18, 2);
1203 0 : (void)zyd_write16(sc, ZYD_CR47, 0x1e);
1204 0 : (void)zyd_read32(sc, ZYD_CR_RADIO_PD, &tmp);
1205 0 : (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1);
1206 0 : (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp | 1);
1207 0 : (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x05);
1208 :
1209 0 : (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x00);
1210 0 : (void)zyd_write16(sc, ZYD_CR47, 0x1e);
1211 :
1212 : /* actually set the channel */
1213 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1]);
1214 :
1215 0 : (void)zyd_write32(sc, ZYD_CR18, 3);
1216 :
1217 0 : return 0;
1218 0 : }
1219 :
1220 : /*
1221 : * GCT RF methods.
1222 : */
1223 : int
1224 0 : zyd_gct_init(struct zyd_rf *rf)
1225 : {
1226 0 : struct zyd_softc *sc = rf->rf_sc;
1227 : static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY;
1228 : static const uint32_t rfini[] = ZYD_GCT_RF;
1229 : int i, error;
1230 :
1231 : /* init RF-dependent PHY registers */
1232 0 : for (i = 0; i < nitems(phyini); i++) {
1233 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1234 0 : if (error != 0)
1235 0 : return error;
1236 : }
1237 : /* init cgt radio */
1238 0 : for (i = 0; i < nitems(rfini); i++) {
1239 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1240 0 : return error;
1241 : }
1242 0 : return 0;
1243 0 : }
1244 :
1245 : int
1246 0 : zyd_gct_switch_radio(struct zyd_rf *rf, int on)
1247 : {
1248 : /* vendor driver does nothing for this RF chip */
1249 :
1250 0 : return 0;
1251 : }
1252 :
1253 : int
1254 0 : zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan)
1255 : {
1256 0 : struct zyd_softc *sc = rf->rf_sc;
1257 : static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE;
1258 :
1259 0 : (void)zyd_rfwrite(sc, 0x1c0000);
1260 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1]);
1261 0 : (void)zyd_rfwrite(sc, 0x1c0008);
1262 :
1263 0 : return 0;
1264 : }
1265 :
1266 : /*
1267 : * Maxim RF methods.
1268 : */
1269 : int
1270 0 : zyd_maxim_init(struct zyd_rf *rf)
1271 : {
1272 0 : struct zyd_softc *sc = rf->rf_sc;
1273 : static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY;
1274 : static const uint32_t rfini[] = ZYD_MAXIM_RF;
1275 0 : uint16_t tmp;
1276 : int i, error;
1277 :
1278 : /* init RF-dependent PHY registers */
1279 0 : for (i = 0; i < nitems(phyini); i++) {
1280 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1281 0 : if (error != 0)
1282 0 : return error;
1283 : }
1284 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1285 0 : (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
1286 :
1287 : /* init maxim radio */
1288 0 : for (i = 0; i < nitems(rfini); i++) {
1289 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1290 0 : return error;
1291 : }
1292 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1293 0 : (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
1294 :
1295 0 : return 0;
1296 0 : }
1297 :
1298 : int
1299 0 : zyd_maxim_switch_radio(struct zyd_rf *rf, int on)
1300 : {
1301 : /* vendor driver does nothing for this RF chip */
1302 :
1303 0 : return 0;
1304 : }
1305 :
1306 : int
1307 0 : zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan)
1308 : {
1309 0 : struct zyd_softc *sc = rf->rf_sc;
1310 : static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY;
1311 : static const uint32_t rfini[] = ZYD_MAXIM_RF;
1312 : static const struct {
1313 : uint32_t r1, r2;
1314 : } rfprog[] = ZYD_MAXIM_CHANTABLE;
1315 0 : uint16_t tmp;
1316 : int i, error;
1317 :
1318 : /*
1319 : * Do the same as we do when initializing it, except for the channel
1320 : * values coming from the two channel tables.
1321 : */
1322 :
1323 : /* init RF-dependent PHY registers */
1324 0 : for (i = 0; i < nitems(phyini); i++) {
1325 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1326 0 : if (error != 0)
1327 0 : return error;
1328 : }
1329 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1330 0 : (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
1331 :
1332 : /* first two values taken from the chantables */
1333 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1334 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1335 :
1336 : /* init maxim radio - skipping the two first values */
1337 0 : for (i = 2; i < nitems(rfini); i++) {
1338 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1339 0 : return error;
1340 : }
1341 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1342 0 : (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
1343 :
1344 0 : return 0;
1345 0 : }
1346 :
1347 : /*
1348 : * Maxim2 RF methods.
1349 : */
1350 : int
1351 0 : zyd_maxim2_init(struct zyd_rf *rf)
1352 : {
1353 0 : struct zyd_softc *sc = rf->rf_sc;
1354 : static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY;
1355 : static const uint32_t rfini[] = ZYD_MAXIM2_RF;
1356 0 : uint16_t tmp;
1357 : int i, error;
1358 :
1359 : /* init RF-dependent PHY registers */
1360 0 : for (i = 0; i < nitems(phyini); i++) {
1361 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1362 0 : if (error != 0)
1363 0 : return error;
1364 : }
1365 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1366 0 : (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
1367 :
1368 : /* init maxim2 radio */
1369 0 : for (i = 0; i < nitems(rfini); i++) {
1370 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1371 0 : return error;
1372 : }
1373 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1374 0 : (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
1375 :
1376 0 : return 0;
1377 0 : }
1378 :
1379 : int
1380 0 : zyd_maxim2_switch_radio(struct zyd_rf *rf, int on)
1381 : {
1382 : /* vendor driver does nothing for this RF chip */
1383 :
1384 0 : return 0;
1385 : }
1386 :
1387 : int
1388 0 : zyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan)
1389 : {
1390 0 : struct zyd_softc *sc = rf->rf_sc;
1391 : static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY;
1392 : static const uint32_t rfini[] = ZYD_MAXIM2_RF;
1393 : static const struct {
1394 : uint32_t r1, r2;
1395 : } rfprog[] = ZYD_MAXIM2_CHANTABLE;
1396 0 : uint16_t tmp;
1397 : int i, error;
1398 :
1399 : /*
1400 : * Do the same as we do when initializing it, except for the channel
1401 : * values coming from the two channel tables.
1402 : */
1403 :
1404 : /* init RF-dependent PHY registers */
1405 0 : for (i = 0; i < nitems(phyini); i++) {
1406 0 : error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
1407 0 : if (error != 0)
1408 0 : return error;
1409 : }
1410 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1411 0 : (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
1412 :
1413 : /* first two values taken from the chantables */
1414 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
1415 0 : (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
1416 :
1417 : /* init maxim2 radio - skipping the two first values */
1418 0 : for (i = 2; i < nitems(rfini); i++) {
1419 0 : if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
1420 0 : return error;
1421 : }
1422 0 : (void)zyd_read16(sc, ZYD_CR203, &tmp);
1423 0 : (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
1424 :
1425 0 : return 0;
1426 0 : }
1427 :
1428 : int
1429 0 : zyd_rf_attach(struct zyd_softc *sc, uint8_t type)
1430 : {
1431 0 : struct zyd_rf *rf = &sc->sc_rf;
1432 :
1433 0 : rf->rf_sc = sc;
1434 :
1435 0 : switch (type) {
1436 : case ZYD_RF_RFMD:
1437 0 : rf->init = zyd_rfmd_init;
1438 0 : rf->switch_radio = zyd_rfmd_switch_radio;
1439 0 : rf->set_channel = zyd_rfmd_set_channel;
1440 0 : rf->width = 24; /* 24-bit RF values */
1441 0 : break;
1442 : case ZYD_RF_AL2230:
1443 : case ZYD_RF_AL2230S:
1444 0 : if (sc->mac_rev == ZYD_ZD1211B)
1445 0 : rf->init = zyd_al2230_init_b;
1446 : else
1447 0 : rf->init = zyd_al2230_init;
1448 0 : rf->switch_radio = zyd_al2230_switch_radio;
1449 0 : rf->set_channel = zyd_al2230_set_channel;
1450 0 : rf->width = 24; /* 24-bit RF values */
1451 0 : break;
1452 : case ZYD_RF_AL7230B:
1453 0 : rf->init = zyd_al7230B_init;
1454 0 : rf->switch_radio = zyd_al7230B_switch_radio;
1455 0 : rf->set_channel = zyd_al7230B_set_channel;
1456 0 : rf->width = 24; /* 24-bit RF values */
1457 0 : break;
1458 : case ZYD_RF_AL2210:
1459 0 : rf->init = zyd_al2210_init;
1460 0 : rf->switch_radio = zyd_al2210_switch_radio;
1461 0 : rf->set_channel = zyd_al2210_set_channel;
1462 0 : rf->width = 24; /* 24-bit RF values */
1463 0 : break;
1464 : case ZYD_RF_GCT:
1465 0 : rf->init = zyd_gct_init;
1466 0 : rf->switch_radio = zyd_gct_switch_radio;
1467 0 : rf->set_channel = zyd_gct_set_channel;
1468 0 : rf->width = 21; /* 21-bit RF values */
1469 0 : break;
1470 : case ZYD_RF_MAXIM_NEW:
1471 0 : rf->init = zyd_maxim_init;
1472 0 : rf->switch_radio = zyd_maxim_switch_radio;
1473 0 : rf->set_channel = zyd_maxim_set_channel;
1474 0 : rf->width = 18; /* 18-bit RF values */
1475 0 : break;
1476 : case ZYD_RF_MAXIM_NEW2:
1477 0 : rf->init = zyd_maxim2_init;
1478 0 : rf->switch_radio = zyd_maxim2_switch_radio;
1479 0 : rf->set_channel = zyd_maxim2_set_channel;
1480 0 : rf->width = 18; /* 18-bit RF values */
1481 0 : break;
1482 : default:
1483 0 : printf("%s: sorry, radio \"%s\" is not supported yet\n",
1484 0 : sc->sc_dev.dv_xname, zyd_rf_name(type));
1485 0 : return EINVAL;
1486 : }
1487 0 : return 0;
1488 0 : }
1489 :
1490 : const char *
1491 0 : zyd_rf_name(uint8_t type)
1492 : {
1493 : static const char * const zyd_rfs[] = {
1494 : "unknown", "unknown", "UW2451", "UCHIP", "AL2230",
1495 : "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT",
1496 : "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2",
1497 : "PHILIPS"
1498 : };
1499 0 : return zyd_rfs[(type > 15) ? 0 : type];
1500 : }
1501 :
1502 : int
1503 0 : zyd_hw_init(struct zyd_softc *sc)
1504 : {
1505 0 : struct zyd_rf *rf = &sc->sc_rf;
1506 : const struct zyd_phy_pair *phyp;
1507 0 : uint32_t tmp;
1508 : int error;
1509 :
1510 : /* specify that the plug and play is finished */
1511 0 : (void)zyd_write32(sc, ZYD_MAC_AFTER_PNP, 1);
1512 :
1513 0 : (void)zyd_read16(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->fwbase);
1514 : DPRINTF(("firmware base address=0x%04x\n", sc->fwbase));
1515 :
1516 : /* retrieve firmware revision number */
1517 0 : (void)zyd_read16(sc, sc->fwbase + ZYD_FW_FIRMWARE_REV, &sc->fw_rev);
1518 :
1519 0 : (void)zyd_write32(sc, ZYD_CR_GPI_EN, 0);
1520 0 : (void)zyd_write32(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f);
1521 :
1522 : /* disable interrupts */
1523 0 : (void)zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
1524 :
1525 : /* PHY init */
1526 0 : zyd_lock_phy(sc);
1527 0 : phyp = (sc->mac_rev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy;
1528 0 : for (; phyp->reg != 0; phyp++) {
1529 0 : if ((error = zyd_write16(sc, phyp->reg, phyp->val)) != 0)
1530 : goto fail;
1531 : }
1532 0 : if (sc->fix_cr157) {
1533 0 : if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
1534 0 : (void)zyd_write32(sc, ZYD_CR157, tmp >> 8);
1535 : }
1536 0 : zyd_unlock_phy(sc);
1537 :
1538 : /* HMAC init */
1539 0 : zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000020);
1540 0 : zyd_write32(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808);
1541 :
1542 0 : if (sc->mac_rev == ZYD_ZD1211) {
1543 0 : zyd_write32(sc, ZYD_MAC_RETRY, 0x00000002);
1544 0 : } else {
1545 0 : zyd_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202);
1546 0 : zyd_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f);
1547 0 : zyd_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f);
1548 0 : zyd_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f);
1549 0 : zyd_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f);
1550 0 : zyd_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028);
1551 0 : zyd_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003c);
1552 0 : zyd_write32(sc, ZYD_MACB_TXOP, 0x01800824);
1553 : }
1554 :
1555 0 : zyd_write32(sc, ZYD_MAC_SNIFFER, 0x00000000);
1556 0 : zyd_write32(sc, ZYD_MAC_RXFILTER, 0x00000000);
1557 0 : zyd_write32(sc, ZYD_MAC_GHTBL, 0x00000000);
1558 0 : zyd_write32(sc, ZYD_MAC_GHTBH, 0x80000000);
1559 0 : zyd_write32(sc, ZYD_MAC_MISC, 0x000000a4);
1560 0 : zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f);
1561 0 : zyd_write32(sc, ZYD_MAC_BCNCFG, 0x00f00401);
1562 0 : zyd_write32(sc, ZYD_MAC_PHY_DELAY2, 0x00000000);
1563 0 : zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000080);
1564 0 : zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000);
1565 0 : zyd_write32(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100);
1566 0 : zyd_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0547c032);
1567 0 : zyd_write32(sc, ZYD_CR_RX_PE_DELAY, 0x00000070);
1568 0 : zyd_write32(sc, ZYD_CR_PS_CTRL, 0x10000000);
1569 0 : zyd_write32(sc, ZYD_MAC_RTSCTSRATE, 0x02030203);
1570 0 : zyd_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640);
1571 0 : zyd_write32(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114);
1572 :
1573 : /* RF chip init */
1574 0 : zyd_lock_phy(sc);
1575 0 : error = (*rf->init)(rf);
1576 0 : zyd_unlock_phy(sc);
1577 0 : if (error != 0) {
1578 0 : printf("%s: radio initialization failed\n",
1579 0 : sc->sc_dev.dv_xname);
1580 0 : goto fail;
1581 : }
1582 :
1583 : /* init beacon interval to 100ms */
1584 0 : if ((error = zyd_set_beacon_interval(sc, 100)) != 0)
1585 0 : goto fail;
1586 :
1587 0 : fail: return error;
1588 0 : }
1589 :
1590 : int
1591 0 : zyd_read_eeprom(struct zyd_softc *sc)
1592 : {
1593 0 : struct ieee80211com *ic = &sc->sc_ic;
1594 0 : uint32_t tmp;
1595 0 : uint16_t val;
1596 : int i;
1597 :
1598 : /* read MAC address */
1599 0 : (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P1, &tmp);
1600 0 : ic->ic_myaddr[0] = tmp & 0xff;
1601 0 : ic->ic_myaddr[1] = tmp >> 8;
1602 0 : ic->ic_myaddr[2] = tmp >> 16;
1603 0 : ic->ic_myaddr[3] = tmp >> 24;
1604 0 : (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P2, &tmp);
1605 0 : ic->ic_myaddr[4] = tmp & 0xff;
1606 0 : ic->ic_myaddr[5] = tmp >> 8;
1607 :
1608 0 : (void)zyd_read32(sc, ZYD_EEPROM_POD, &tmp);
1609 0 : sc->rf_rev = tmp & 0x0f;
1610 0 : sc->fix_cr47 = (tmp >> 8 ) & 0x01;
1611 0 : sc->fix_cr157 = (tmp >> 13) & 0x01;
1612 0 : sc->pa_rev = (tmp >> 16) & 0x0f;
1613 :
1614 : /* read regulatory domain (currently unused) */
1615 0 : (void)zyd_read32(sc, ZYD_EEPROM_SUBID, &tmp);
1616 0 : sc->regdomain = tmp >> 16;
1617 : DPRINTF(("regulatory domain %x\n", sc->regdomain));
1618 :
1619 : /* read Tx power calibration tables */
1620 0 : for (i = 0; i < 7; i++) {
1621 0 : (void)zyd_read16(sc, ZYD_EEPROM_PWR_CAL + i, &val);
1622 0 : sc->pwr_cal[i * 2] = val >> 8;
1623 0 : sc->pwr_cal[i * 2 + 1] = val & 0xff;
1624 :
1625 0 : (void)zyd_read16(sc, ZYD_EEPROM_PWR_INT + i, &val);
1626 0 : sc->pwr_int[i * 2] = val >> 8;
1627 0 : sc->pwr_int[i * 2 + 1] = val & 0xff;
1628 :
1629 0 : (void)zyd_read16(sc, ZYD_EEPROM_36M_CAL + i, &val);
1630 0 : sc->ofdm36_cal[i * 2] = val >> 8;
1631 0 : sc->ofdm36_cal[i * 2 + 1] = val & 0xff;
1632 :
1633 0 : (void)zyd_read16(sc, ZYD_EEPROM_48M_CAL + i, &val);
1634 0 : sc->ofdm48_cal[i * 2] = val >> 8;
1635 0 : sc->ofdm48_cal[i * 2 + 1] = val & 0xff;
1636 :
1637 0 : (void)zyd_read16(sc, ZYD_EEPROM_54M_CAL + i, &val);
1638 0 : sc->ofdm54_cal[i * 2] = val >> 8;
1639 0 : sc->ofdm54_cal[i * 2 + 1] = val & 0xff;
1640 : }
1641 0 : return 0;
1642 0 : }
1643 :
1644 : void
1645 0 : zyd_set_multi(struct zyd_softc *sc)
1646 : {
1647 0 : struct arpcom *ac = &sc->sc_ic.ic_ac;
1648 0 : struct ifnet *ifp = &ac->ac_if;
1649 : struct ether_multi *enm;
1650 : struct ether_multistep step;
1651 : uint32_t lo, hi;
1652 : uint8_t bit;
1653 :
1654 0 : if (ac->ac_multirangecnt > 0)
1655 0 : ifp->if_flags |= IFF_ALLMULTI;
1656 :
1657 0 : if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
1658 : lo = hi = 0xffffffff;
1659 0 : goto done;
1660 : }
1661 : lo = hi = 0;
1662 0 : ETHER_FIRST_MULTI(step, ac, enm);
1663 0 : while (enm != NULL) {
1664 0 : bit = enm->enm_addrlo[5] >> 2;
1665 0 : if (bit < 32)
1666 0 : lo |= 1 << bit;
1667 : else
1668 0 : hi |= 1 << (bit - 32);
1669 0 : ETHER_NEXT_MULTI(step, enm);
1670 : }
1671 :
1672 : done:
1673 0 : hi |= 1U << 31; /* make sure the broadcast bit is set */
1674 0 : zyd_write32(sc, ZYD_MAC_GHTBL, lo);
1675 0 : zyd_write32(sc, ZYD_MAC_GHTBH, hi);
1676 0 : }
1677 :
1678 : void
1679 0 : zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr)
1680 : {
1681 : uint32_t tmp;
1682 :
1683 0 : tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
1684 0 : (void)zyd_write32(sc, ZYD_MAC_MACADRL, tmp);
1685 :
1686 0 : tmp = addr[5] << 8 | addr[4];
1687 0 : (void)zyd_write32(sc, ZYD_MAC_MACADRH, tmp);
1688 0 : }
1689 :
1690 : void
1691 0 : zyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr)
1692 : {
1693 : uint32_t tmp;
1694 :
1695 0 : tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
1696 0 : (void)zyd_write32(sc, ZYD_MAC_BSSADRL, tmp);
1697 :
1698 0 : tmp = addr[5] << 8 | addr[4];
1699 0 : (void)zyd_write32(sc, ZYD_MAC_BSSADRH, tmp);
1700 0 : }
1701 :
1702 : int
1703 0 : zyd_switch_radio(struct zyd_softc *sc, int on)
1704 : {
1705 0 : struct zyd_rf *rf = &sc->sc_rf;
1706 : int error;
1707 :
1708 0 : zyd_lock_phy(sc);
1709 0 : error = (*rf->switch_radio)(rf, on);
1710 0 : zyd_unlock_phy(sc);
1711 :
1712 0 : return error;
1713 : }
1714 :
1715 : void
1716 0 : zyd_set_led(struct zyd_softc *sc, int which, int on)
1717 : {
1718 0 : uint32_t tmp;
1719 :
1720 0 : (void)zyd_read32(sc, ZYD_MAC_TX_PE_CONTROL, &tmp);
1721 0 : tmp &= ~which;
1722 0 : if (on)
1723 0 : tmp |= which;
1724 0 : (void)zyd_write32(sc, ZYD_MAC_TX_PE_CONTROL, tmp);
1725 0 : }
1726 :
1727 : int
1728 0 : zyd_set_rxfilter(struct zyd_softc *sc)
1729 : {
1730 : uint32_t rxfilter;
1731 :
1732 0 : switch (sc->sc_ic.ic_opmode) {
1733 : case IEEE80211_M_STA:
1734 : rxfilter = ZYD_FILTER_BSS;
1735 0 : break;
1736 : #ifndef IEEE80211_STA_ONLY
1737 : case IEEE80211_M_IBSS:
1738 : case IEEE80211_M_HOSTAP:
1739 : rxfilter = ZYD_FILTER_HOSTAP;
1740 0 : break;
1741 : #endif
1742 : case IEEE80211_M_MONITOR:
1743 : rxfilter = ZYD_FILTER_MONITOR;
1744 0 : break;
1745 : default:
1746 : /* should not get there */
1747 0 : return EINVAL;
1748 : }
1749 0 : return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter);
1750 0 : }
1751 :
1752 : void
1753 0 : zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
1754 : {
1755 0 : struct ieee80211com *ic = &sc->sc_ic;
1756 0 : struct zyd_rf *rf = &sc->sc_rf;
1757 0 : uint32_t tmp;
1758 : u_int chan;
1759 :
1760 0 : chan = ieee80211_chan2ieee(ic, c);
1761 0 : if (chan == 0 || chan == IEEE80211_CHAN_ANY)
1762 0 : return;
1763 :
1764 0 : zyd_lock_phy(sc);
1765 :
1766 0 : (*rf->set_channel)(rf, chan);
1767 :
1768 : /* update Tx power */
1769 0 : (void)zyd_write16(sc, ZYD_CR31, sc->pwr_int[chan - 1]);
1770 :
1771 0 : if (sc->mac_rev == ZYD_ZD1211B) {
1772 0 : (void)zyd_write16(sc, ZYD_CR67, sc->ofdm36_cal[chan - 1]);
1773 0 : (void)zyd_write16(sc, ZYD_CR66, sc->ofdm48_cal[chan - 1]);
1774 0 : (void)zyd_write16(sc, ZYD_CR65, sc->ofdm54_cal[chan - 1]);
1775 :
1776 0 : (void)zyd_write16(sc, ZYD_CR68, sc->pwr_cal[chan - 1]);
1777 :
1778 0 : (void)zyd_write16(sc, ZYD_CR69, 0x28);
1779 0 : (void)zyd_write16(sc, ZYD_CR69, 0x2a);
1780 0 : }
1781 :
1782 0 : if (sc->fix_cr47) {
1783 : /* set CCK baseband gain from EEPROM */
1784 0 : if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
1785 0 : (void)zyd_write16(sc, ZYD_CR47, tmp & 0xff);
1786 : }
1787 :
1788 0 : (void)zyd_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0);
1789 :
1790 0 : zyd_unlock_phy(sc);
1791 0 : }
1792 :
1793 : int
1794 0 : zyd_set_beacon_interval(struct zyd_softc *sc, int bintval)
1795 : {
1796 : /* XXX this is probably broken.. */
1797 0 : (void)zyd_write32(sc, ZYD_CR_ATIM_WND_PERIOD, bintval - 2);
1798 0 : (void)zyd_write32(sc, ZYD_CR_PRE_TBTT, bintval - 1);
1799 0 : (void)zyd_write32(sc, ZYD_CR_BCN_INTERVAL, bintval);
1800 :
1801 0 : return 0;
1802 : }
1803 :
1804 : uint8_t
1805 0 : zyd_plcp_signal(int rate)
1806 : {
1807 0 : switch (rate) {
1808 : /* CCK rates (returned values are device-dependent) */
1809 0 : case 2: return 0x0;
1810 0 : case 4: return 0x1;
1811 0 : case 11: return 0x2;
1812 0 : case 22: return 0x3;
1813 :
1814 : /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1815 0 : case 12: return 0xb;
1816 0 : case 18: return 0xf;
1817 0 : case 24: return 0xa;
1818 0 : case 36: return 0xe;
1819 0 : case 48: return 0x9;
1820 0 : case 72: return 0xd;
1821 0 : case 96: return 0x8;
1822 0 : case 108: return 0xc;
1823 :
1824 : /* unsupported rates (should not get there) */
1825 0 : default: return 0xff;
1826 : }
1827 0 : }
1828 :
1829 : void
1830 0 : zyd_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1831 : {
1832 0 : struct zyd_softc *sc = (struct zyd_softc *)priv;
1833 : const struct zyd_cmd *cmd;
1834 0 : uint32_t len;
1835 :
1836 0 : if (status != USBD_NORMAL_COMPLETION) {
1837 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1838 0 : return;
1839 :
1840 0 : if (status == USBD_STALLED) {
1841 0 : usbd_clear_endpoint_stall_async(
1842 0 : sc->zyd_ep[ZYD_ENDPT_IIN]);
1843 0 : }
1844 0 : return;
1845 : }
1846 :
1847 0 : cmd = (const struct zyd_cmd *)sc->ibuf;
1848 :
1849 0 : if (letoh16(cmd->code) == ZYD_NOTIF_RETRYSTATUS) {
1850 : struct zyd_notif_retry *retry =
1851 0 : (struct zyd_notif_retry *)cmd->data;
1852 0 : struct ieee80211com *ic = &sc->sc_ic;
1853 0 : struct ifnet *ifp = &ic->ic_if;
1854 : struct ieee80211_node *ni;
1855 :
1856 : DPRINTF(("retry intr: rate=0x%x addr=%s count=%d (0x%x)\n",
1857 : letoh16(retry->rate), ether_sprintf(retry->macaddr),
1858 : letoh16(retry->count) & 0xff, letoh16(retry->count)));
1859 :
1860 : /*
1861 : * Find the node to which the packet was sent and update its
1862 : * retry statistics. In BSS mode, this node is the AP we're
1863 : * associated to so no lookup is actually needed.
1864 : */
1865 0 : if (ic->ic_opmode != IEEE80211_M_STA) {
1866 0 : ni = ieee80211_find_node(ic, retry->macaddr);
1867 0 : if (ni == NULL)
1868 0 : return; /* just ignore */
1869 : } else
1870 0 : ni = ic->ic_bss;
1871 :
1872 0 : ((struct zyd_node *)ni)->amn.amn_retrycnt++;
1873 :
1874 0 : if (letoh16(retry->count) & 0x100)
1875 0 : ifp->if_oerrors++; /* too many retries */
1876 :
1877 0 : } else if (letoh16(cmd->code) == ZYD_NOTIF_IORD) {
1878 0 : if (letoh16(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT)
1879 0 : return; /* HMAC interrupt */
1880 :
1881 0 : if (!sc->odone) {
1882 : /* copy answer into sc->odata buffer */
1883 0 : usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1884 0 : bcopy(cmd->data, sc->odata, sc->olen);
1885 0 : sc->odone = 1;
1886 0 : wakeup(sc); /* wakeup zyd_cmd_read() */
1887 0 : }
1888 :
1889 : } else {
1890 0 : printf("%s: unknown notification %x\n", sc->sc_dev.dv_xname,
1891 : letoh16(cmd->code));
1892 : }
1893 0 : }
1894 :
1895 : void
1896 0 : zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len)
1897 : {
1898 0 : struct ieee80211com *ic = &sc->sc_ic;
1899 0 : struct ifnet *ifp = &ic->ic_if;
1900 : struct ieee80211_node *ni;
1901 : struct ieee80211_frame *wh;
1902 0 : struct ieee80211_rxinfo rxi;
1903 : const struct zyd_plcphdr *plcp;
1904 : const struct zyd_rx_stat *stat;
1905 : struct mbuf *m;
1906 : int s;
1907 :
1908 0 : if (len < ZYD_MIN_FRAGSZ) {
1909 : DPRINTFN(2, ("frame too short (length=%d)\n", len));
1910 0 : ifp->if_ierrors++;
1911 0 : return;
1912 : }
1913 :
1914 0 : plcp = (const struct zyd_plcphdr *)buf;
1915 0 : stat = (const struct zyd_rx_stat *)(buf + len - sizeof (*stat));
1916 :
1917 0 : if (stat->flags & ZYD_RX_ERROR) {
1918 : DPRINTF(("%s: RX status indicated error (%x)\n",
1919 : sc->sc_dev.dv_xname, stat->flags));
1920 0 : ifp->if_ierrors++;
1921 0 : return;
1922 : }
1923 :
1924 : /* compute actual frame length */
1925 0 : len -= (sizeof (*plcp) + sizeof (*stat) + IEEE80211_CRC_LEN);
1926 :
1927 0 : if (len > MCLBYTES) {
1928 : DPRINTFN(2, ("frame too large (length=%d)\n", len));
1929 0 : ifp->if_ierrors++;
1930 0 : return;
1931 : }
1932 :
1933 : /* allocate a mbuf to store the frame */
1934 0 : MGETHDR(m, M_DONTWAIT, MT_DATA);
1935 0 : if (m == NULL) {
1936 0 : ifp->if_ierrors++;
1937 0 : return;
1938 : }
1939 0 : if (len > MHLEN) {
1940 0 : MCLGET(m, M_DONTWAIT);
1941 0 : if (!(m->m_flags & M_EXT)) {
1942 0 : ifp->if_ierrors++;
1943 0 : m_freem(m);
1944 0 : return;
1945 : }
1946 : }
1947 0 : bcopy(plcp + 1, mtod(m, caddr_t), len);
1948 0 : m->m_pkthdr.len = m->m_len = len;
1949 :
1950 : #if NBPFILTER > 0
1951 0 : if (sc->sc_drvbpf != NULL) {
1952 0 : struct mbuf mb;
1953 0 : struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap;
1954 : static const uint8_t rates[] = {
1955 : /* reverse function of zyd_plcp_signal() */
1956 : 2, 4, 11, 22, 0, 0, 0, 0,
1957 : 96, 48, 24, 12, 108, 72, 36, 18
1958 : };
1959 :
1960 0 : tap->wr_flags = 0;
1961 0 : tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
1962 0 : tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
1963 0 : tap->wr_rssi = stat->rssi;
1964 0 : tap->wr_rate = rates[plcp->signal & 0xf];
1965 :
1966 0 : mb.m_data = (caddr_t)tap;
1967 0 : mb.m_len = sc->sc_rxtap_len;
1968 0 : mb.m_next = m;
1969 0 : mb.m_nextpkt = NULL;
1970 0 : mb.m_type = 0;
1971 0 : mb.m_flags = 0;
1972 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
1973 0 : }
1974 : #endif
1975 :
1976 0 : s = splnet();
1977 0 : wh = mtod(m, struct ieee80211_frame *);
1978 0 : ni = ieee80211_find_rxnode(ic, wh);
1979 0 : rxi.rxi_flags = 0;
1980 0 : rxi.rxi_rssi = stat->rssi;
1981 0 : rxi.rxi_tstamp = 0; /* unused */
1982 0 : ieee80211_input(ifp, m, ni, &rxi);
1983 :
1984 : /* node is no longer needed */
1985 0 : ieee80211_release_node(ic, ni);
1986 :
1987 0 : splx(s);
1988 0 : }
1989 :
1990 : void
1991 0 : zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1992 : {
1993 0 : struct zyd_rx_data *data = priv;
1994 0 : struct zyd_softc *sc = data->sc;
1995 0 : struct ieee80211com *ic = &sc->sc_ic;
1996 0 : struct ifnet *ifp = &ic->ic_if;
1997 : const struct zyd_rx_desc *desc;
1998 0 : int len;
1999 :
2000 0 : if (status != USBD_NORMAL_COMPLETION) {
2001 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2002 0 : return;
2003 :
2004 0 : if (status == USBD_STALLED)
2005 0 : usbd_clear_endpoint_stall(sc->zyd_ep[ZYD_ENDPT_BIN]);
2006 :
2007 : goto skip;
2008 : }
2009 0 : usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
2010 :
2011 0 : if (len < ZYD_MIN_RXBUFSZ) {
2012 : DPRINTFN(2, ("xfer too short (length=%d)\n", len));
2013 0 : ifp->if_ierrors++;
2014 0 : goto skip;
2015 : }
2016 :
2017 0 : desc = (const struct zyd_rx_desc *)
2018 0 : (data->buf + len - sizeof (struct zyd_rx_desc));
2019 :
2020 0 : if (UGETW(desc->tag) == ZYD_TAG_MULTIFRAME) {
2021 : const uint8_t *p = data->buf, *end = p + len;
2022 : int i;
2023 :
2024 : DPRINTFN(3, ("received multi-frame transfer\n"));
2025 :
2026 0 : for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) {
2027 0 : const uint16_t len = UGETW(desc->len[i]);
2028 :
2029 0 : if (len == 0 || p + len >= end)
2030 0 : break;
2031 :
2032 0 : zyd_rx_data(sc, p, len);
2033 : /* next frame is aligned on a 32-bit boundary */
2034 0 : p += (len + 3) & ~3;
2035 0 : }
2036 0 : } else {
2037 : DPRINTFN(3, ("received single-frame transfer\n"));
2038 :
2039 0 : zyd_rx_data(sc, data->buf, len);
2040 : }
2041 :
2042 : skip: /* setup a new transfer */
2043 0 : usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data, NULL,
2044 : ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK,
2045 : USBD_NO_TIMEOUT, zyd_rxeof);
2046 0 : (void)usbd_transfer(xfer);
2047 0 : }
2048 :
2049 : void
2050 0 : zyd_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2051 : {
2052 0 : struct zyd_tx_data *data = priv;
2053 0 : struct zyd_softc *sc = data->sc;
2054 0 : struct ieee80211com *ic = &sc->sc_ic;
2055 0 : struct ifnet *ifp = &ic->ic_if;
2056 : int s;
2057 :
2058 0 : if (status != USBD_NORMAL_COMPLETION) {
2059 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2060 0 : return;
2061 :
2062 0 : printf("%s: could not transmit buffer: %s\n",
2063 0 : sc->sc_dev.dv_xname, usbd_errstr(status));
2064 :
2065 0 : if (status == USBD_STALLED) {
2066 0 : usbd_clear_endpoint_stall_async(
2067 0 : sc->zyd_ep[ZYD_ENDPT_BOUT]);
2068 0 : }
2069 0 : ifp->if_oerrors++;
2070 0 : return;
2071 : }
2072 :
2073 0 : s = splnet();
2074 :
2075 : /* update rate control statistics */
2076 0 : ((struct zyd_node *)data->ni)->amn.amn_txcnt++;
2077 :
2078 0 : ieee80211_release_node(ic, data->ni);
2079 0 : data->ni = NULL;
2080 :
2081 0 : sc->tx_queued--;
2082 :
2083 0 : sc->tx_timer = 0;
2084 0 : ifq_clr_oactive(&ifp->if_snd);
2085 0 : zyd_start(ifp);
2086 :
2087 0 : splx(s);
2088 0 : }
2089 :
2090 : int
2091 0 : zyd_tx(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2092 : {
2093 0 : struct ieee80211com *ic = &sc->sc_ic;
2094 0 : struct ifnet *ifp = &ic->ic_if;
2095 : struct zyd_tx_desc *desc;
2096 : struct zyd_tx_data *data;
2097 : struct ieee80211_frame *wh;
2098 : struct ieee80211_key *k;
2099 : int xferlen, totlen, rate;
2100 : uint16_t pktlen;
2101 : usbd_status error;
2102 :
2103 0 : wh = mtod(m, struct ieee80211_frame *);
2104 :
2105 0 : if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
2106 0 : k = ieee80211_get_txkey(ic, wh, ni);
2107 0 : if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
2108 0 : return ENOBUFS;
2109 0 : wh = mtod(m, struct ieee80211_frame *);
2110 0 : }
2111 :
2112 : /* pickup a rate */
2113 0 : if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
2114 0 : ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2115 : IEEE80211_FC0_TYPE_MGT)) {
2116 : /* mgmt/multicast frames are sent at the lowest avail. rate */
2117 0 : rate = ni->ni_rates.rs_rates[0];
2118 0 : } else if (ic->ic_fixed_rate != -1) {
2119 0 : rate = ic->ic_sup_rates[ic->ic_curmode].
2120 0 : rs_rates[ic->ic_fixed_rate];
2121 0 : } else
2122 0 : rate = ni->ni_rates.rs_rates[ni->ni_txrate];
2123 0 : rate &= IEEE80211_RATE_VAL;
2124 0 : if (rate == 0) /* XXX should not happen */
2125 : rate = 2;
2126 :
2127 0 : data = &sc->tx_data[0];
2128 0 : desc = (struct zyd_tx_desc *)data->buf;
2129 :
2130 0 : data->ni = ni;
2131 :
2132 0 : xferlen = sizeof (struct zyd_tx_desc) + m->m_pkthdr.len;
2133 0 : totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
2134 :
2135 : /* fill Tx descriptor */
2136 0 : desc->len = htole16(totlen);
2137 :
2138 0 : desc->flags = ZYD_TX_FLAG_BACKOFF;
2139 0 : if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2140 : /* multicast frames are not sent at OFDM rates in 802.11b/g */
2141 0 : if (totlen > ic->ic_rtsthreshold) {
2142 0 : desc->flags |= ZYD_TX_FLAG_RTS;
2143 0 : } else if (ZYD_RATE_IS_OFDM(rate) &&
2144 0 : (ic->ic_flags & IEEE80211_F_USEPROT)) {
2145 0 : if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
2146 0 : desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF;
2147 0 : else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
2148 0 : desc->flags |= ZYD_TX_FLAG_RTS;
2149 : }
2150 : } else
2151 0 : desc->flags |= ZYD_TX_FLAG_MULTICAST;
2152 :
2153 0 : if ((wh->i_fc[0] &
2154 0 : (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
2155 : (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL))
2156 0 : desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL);
2157 :
2158 0 : desc->phy = zyd_plcp_signal(rate);
2159 0 : if (ZYD_RATE_IS_OFDM(rate)) {
2160 0 : desc->phy |= ZYD_TX_PHY_OFDM;
2161 0 : if (ic->ic_curmode == IEEE80211_MODE_11A)
2162 0 : desc->phy |= ZYD_TX_PHY_5GHZ;
2163 0 : } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
2164 0 : desc->phy |= ZYD_TX_PHY_SHPREAMBLE;
2165 :
2166 : /* actual transmit length (XXX why +10?) */
2167 : pktlen = sizeof (struct zyd_tx_desc) + 10;
2168 0 : if (sc->mac_rev == ZYD_ZD1211)
2169 0 : pktlen += totlen;
2170 0 : desc->pktlen = htole16(pktlen);
2171 :
2172 0 : desc->plcp_length = htole16((16 * totlen + rate - 1) / rate);
2173 0 : desc->plcp_service = 0;
2174 0 : if (rate == 22) {
2175 0 : const int remainder = (16 * totlen) % 22;
2176 0 : if (remainder != 0 && remainder < 7)
2177 0 : desc->plcp_service |= ZYD_PLCP_LENGEXT;
2178 0 : }
2179 :
2180 : #if NBPFILTER > 0
2181 0 : if (sc->sc_drvbpf != NULL) {
2182 0 : struct mbuf mb;
2183 0 : struct zyd_tx_radiotap_header *tap = &sc->sc_txtap;
2184 :
2185 0 : tap->wt_flags = 0;
2186 0 : tap->wt_rate = rate;
2187 0 : tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
2188 0 : tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
2189 :
2190 0 : mb.m_data = (caddr_t)tap;
2191 0 : mb.m_len = sc->sc_txtap_len;
2192 0 : mb.m_next = m;
2193 0 : mb.m_nextpkt = NULL;
2194 0 : mb.m_type = 0;
2195 0 : mb.m_flags = 0;
2196 0 : bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
2197 0 : }
2198 : #endif
2199 :
2200 0 : m_copydata(m, 0, m->m_pkthdr.len,
2201 0 : data->buf + sizeof (struct zyd_tx_desc));
2202 :
2203 : DPRINTFN(10, ("%s: sending data frame len=%u rate=%u xferlen=%u\n",
2204 : sc->sc_dev.dv_xname, m->m_pkthdr.len, rate, xferlen));
2205 :
2206 0 : m_freem(m); /* mbuf no longer needed */
2207 :
2208 0 : usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BOUT], data,
2209 0 : data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
2210 : ZYD_TX_TIMEOUT, zyd_txeof);
2211 0 : error = usbd_transfer(data->xfer);
2212 0 : if (error != USBD_IN_PROGRESS && error != 0) {
2213 0 : ifp->if_oerrors++;
2214 0 : return EIO;
2215 : }
2216 0 : sc->tx_queued++;
2217 :
2218 0 : return 0;
2219 0 : }
2220 :
2221 : void
2222 0 : zyd_start(struct ifnet *ifp)
2223 : {
2224 0 : struct zyd_softc *sc = ifp->if_softc;
2225 0 : struct ieee80211com *ic = &sc->sc_ic;
2226 0 : struct ieee80211_node *ni;
2227 : struct mbuf *m;
2228 :
2229 0 : if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
2230 0 : return;
2231 :
2232 0 : for (;;) {
2233 0 : if (sc->tx_queued >= ZYD_TX_LIST_CNT) {
2234 0 : ifq_set_oactive(&ifp->if_snd);
2235 0 : break;
2236 : }
2237 : /* send pending management frames first */
2238 0 : m = mq_dequeue(&ic->ic_mgtq);
2239 0 : if (m != NULL) {
2240 0 : ni = m->m_pkthdr.ph_cookie;
2241 0 : goto sendit;
2242 : }
2243 0 : if (ic->ic_state != IEEE80211_S_RUN)
2244 : break;
2245 :
2246 : /* encapsulate and send data frames */
2247 0 : IFQ_DEQUEUE(&ifp->if_snd, m);
2248 0 : if (m == NULL)
2249 : break;
2250 : #if NBPFILTER > 0
2251 0 : if (ifp->if_bpf != NULL)
2252 0 : bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
2253 : #endif
2254 0 : if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
2255 0 : continue;
2256 : sendit:
2257 : #if NBPFILTER > 0
2258 0 : if (ic->ic_rawbpf != NULL)
2259 0 : bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
2260 : #endif
2261 0 : if (zyd_tx(sc, m, ni) != 0) {
2262 0 : ieee80211_release_node(ic, ni);
2263 0 : ifp->if_oerrors++;
2264 0 : continue;
2265 : }
2266 :
2267 0 : sc->tx_timer = 5;
2268 0 : ifp->if_timer = 1;
2269 : }
2270 0 : }
2271 :
2272 : void
2273 0 : zyd_watchdog(struct ifnet *ifp)
2274 : {
2275 0 : struct zyd_softc *sc = ifp->if_softc;
2276 :
2277 0 : ifp->if_timer = 0;
2278 :
2279 0 : if (sc->tx_timer > 0) {
2280 0 : if (--sc->tx_timer == 0) {
2281 0 : printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2282 : /* zyd_init(ifp); XXX needs a process context ? */
2283 0 : ifp->if_oerrors++;
2284 0 : return;
2285 : }
2286 0 : ifp->if_timer = 1;
2287 0 : }
2288 :
2289 0 : ieee80211_watchdog(ifp);
2290 0 : }
2291 :
2292 : int
2293 0 : zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2294 : {
2295 0 : struct zyd_softc *sc = ifp->if_softc;
2296 0 : struct ieee80211com *ic = &sc->sc_ic;
2297 : struct ifreq *ifr;
2298 : int s, error = 0;
2299 :
2300 0 : s = splnet();
2301 :
2302 0 : switch (cmd) {
2303 : case SIOCSIFADDR:
2304 0 : ifp->if_flags |= IFF_UP;
2305 : /* FALLTHROUGH */
2306 : case SIOCSIFFLAGS:
2307 0 : if (ifp->if_flags & IFF_UP) {
2308 : /*
2309 : * If only the PROMISC or ALLMULTI flag changes, then
2310 : * don't do a full re-init of the chip, just update
2311 : * the Rx filter.
2312 : */
2313 0 : if ((ifp->if_flags & IFF_RUNNING) &&
2314 0 : ((ifp->if_flags ^ sc->sc_if_flags) &
2315 0 : (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
2316 0 : zyd_set_multi(sc);
2317 0 : } else {
2318 0 : if (!(ifp->if_flags & IFF_RUNNING))
2319 0 : zyd_init(ifp);
2320 : }
2321 : } else {
2322 0 : if (ifp->if_flags & IFF_RUNNING)
2323 0 : zyd_stop(ifp, 1);
2324 : }
2325 0 : sc->sc_if_flags = ifp->if_flags;
2326 0 : break;
2327 :
2328 : case SIOCADDMULTI:
2329 : case SIOCDELMULTI:
2330 0 : ifr = (struct ifreq *)data;
2331 0 : error = (cmd == SIOCADDMULTI) ?
2332 0 : ether_addmulti(ifr, &ic->ic_ac) :
2333 0 : ether_delmulti(ifr, &ic->ic_ac);
2334 0 : if (error == ENETRESET) {
2335 0 : if (ifp->if_flags & IFF_RUNNING)
2336 0 : zyd_set_multi(sc);
2337 : error = 0;
2338 0 : }
2339 : break;
2340 :
2341 : case SIOCS80211CHANNEL:
2342 : /*
2343 : * This allows for fast channel switching in monitor mode
2344 : * (used by kismet). In IBSS mode, we must explicitly reset
2345 : * the interface to generate a new beacon frame.
2346 : */
2347 0 : error = ieee80211_ioctl(ifp, cmd, data);
2348 0 : if (error == ENETRESET &&
2349 0 : ic->ic_opmode == IEEE80211_M_MONITOR) {
2350 0 : zyd_set_chan(sc, ic->ic_ibss_chan);
2351 : error = 0;
2352 0 : }
2353 : break;
2354 :
2355 : default:
2356 0 : error = ieee80211_ioctl(ifp, cmd, data);
2357 0 : }
2358 :
2359 0 : if (error == ENETRESET) {
2360 0 : if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) ==
2361 : (IFF_RUNNING | IFF_UP))
2362 0 : zyd_init(ifp);
2363 : error = 0;
2364 0 : }
2365 :
2366 0 : splx(s);
2367 :
2368 0 : return error;
2369 : }
2370 :
2371 : int
2372 0 : zyd_init(struct ifnet *ifp)
2373 : {
2374 0 : struct zyd_softc *sc = ifp->if_softc;
2375 0 : struct ieee80211com *ic = &sc->sc_ic;
2376 : int i, error;
2377 :
2378 0 : zyd_stop(ifp, 0);
2379 :
2380 0 : IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
2381 : DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2382 0 : zyd_set_macaddr(sc, ic->ic_myaddr);
2383 :
2384 : /* we'll do software WEP decryption for now */
2385 : DPRINTF(("setting encryption type\n"));
2386 0 : error = zyd_write32(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER);
2387 0 : if (error != 0)
2388 0 : return error;
2389 :
2390 : /* promiscuous mode */
2391 0 : (void)zyd_write32(sc, ZYD_MAC_SNIFFER,
2392 0 : (ic->ic_opmode == IEEE80211_M_MONITOR) ? 1 : 0);
2393 :
2394 0 : (void)zyd_set_rxfilter(sc);
2395 :
2396 : /* switch radio transmitter ON */
2397 0 : (void)zyd_switch_radio(sc, 1);
2398 :
2399 : /* set basic rates */
2400 0 : if (ic->ic_curmode == IEEE80211_MODE_11B)
2401 0 : (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x0003);
2402 0 : else if (ic->ic_curmode == IEEE80211_MODE_11A)
2403 0 : (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x1500);
2404 : else /* assumes 802.11b/g */
2405 0 : (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x000f);
2406 :
2407 : /* set mandatory rates */
2408 0 : if (ic->ic_curmode == IEEE80211_MODE_11B)
2409 0 : (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x000f);
2410 0 : else if (ic->ic_curmode == IEEE80211_MODE_11A)
2411 0 : (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x1500);
2412 : else /* assumes 802.11b/g */
2413 0 : (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x150f);
2414 :
2415 : /* set default BSS channel */
2416 0 : ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2417 0 : zyd_set_chan(sc, ic->ic_bss->ni_chan);
2418 :
2419 : /* enable interrupts */
2420 0 : (void)zyd_write32(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
2421 :
2422 : /*
2423 : * Allocate Tx and Rx xfer queues.
2424 : */
2425 0 : if ((error = zyd_alloc_tx_list(sc)) != 0) {
2426 0 : printf("%s: could not allocate Tx list\n",
2427 0 : sc->sc_dev.dv_xname);
2428 0 : goto fail;
2429 : }
2430 0 : if ((error = zyd_alloc_rx_list(sc)) != 0) {
2431 0 : printf("%s: could not allocate Rx list\n",
2432 0 : sc->sc_dev.dv_xname);
2433 0 : goto fail;
2434 : }
2435 :
2436 : /*
2437 : * Start up the receive pipe.
2438 : */
2439 0 : for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
2440 0 : struct zyd_rx_data *data = &sc->rx_data[i];
2441 :
2442 0 : usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data,
2443 : NULL, ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK,
2444 : USBD_NO_TIMEOUT, zyd_rxeof);
2445 0 : error = usbd_transfer(data->xfer);
2446 0 : if (error != USBD_IN_PROGRESS && error != 0) {
2447 0 : printf("%s: could not queue Rx transfer\n",
2448 0 : sc->sc_dev.dv_xname);
2449 0 : goto fail;
2450 : }
2451 0 : }
2452 :
2453 0 : ifq_clr_oactive(&ifp->if_snd);
2454 0 : ifp->if_flags |= IFF_RUNNING;
2455 :
2456 0 : if (ic->ic_opmode == IEEE80211_M_MONITOR)
2457 0 : ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2458 : else
2459 0 : ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2460 :
2461 0 : return 0;
2462 :
2463 0 : fail: zyd_stop(ifp, 1);
2464 0 : return error;
2465 0 : }
2466 :
2467 : void
2468 0 : zyd_stop(struct ifnet *ifp, int disable)
2469 : {
2470 0 : struct zyd_softc *sc = ifp->if_softc;
2471 0 : struct ieee80211com *ic = &sc->sc_ic;
2472 :
2473 0 : sc->tx_timer = 0;
2474 0 : ifp->if_timer = 0;
2475 0 : ifp->if_flags &= ~IFF_RUNNING;
2476 0 : ifq_clr_oactive(&ifp->if_snd);
2477 :
2478 0 : ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */
2479 :
2480 : /* switch radio transmitter OFF */
2481 0 : (void)zyd_switch_radio(sc, 0);
2482 :
2483 : /* disable Rx */
2484 0 : (void)zyd_write32(sc, ZYD_MAC_RXFILTER, 0);
2485 :
2486 : /* disable interrupts */
2487 0 : (void)zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
2488 :
2489 0 : usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BIN]);
2490 0 : usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BOUT]);
2491 :
2492 0 : zyd_free_rx_list(sc);
2493 0 : zyd_free_tx_list(sc);
2494 0 : }
2495 :
2496 : int
2497 0 : zyd_loadfirmware(struct zyd_softc *sc, u_char *fw, size_t size)
2498 : {
2499 0 : usb_device_request_t req;
2500 : uint16_t addr;
2501 0 : uint8_t stat;
2502 :
2503 : DPRINTF(("firmware size=%zd\n", size));
2504 :
2505 0 : req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
2506 0 : req.bRequest = ZYD_DOWNLOADREQ;
2507 0 : USETW(req.wIndex, 0);
2508 :
2509 : addr = ZYD_FIRMWARE_START_ADDR;
2510 0 : while (size > 0) {
2511 0 : const int mlen = min(size, 4096);
2512 :
2513 : DPRINTF(("loading firmware block: len=%d, addr=0x%x\n", mlen,
2514 : addr));
2515 :
2516 0 : USETW(req.wValue, addr);
2517 0 : USETW(req.wLength, mlen);
2518 0 : if (usbd_do_request(sc->sc_udev, &req, fw) != 0)
2519 0 : return EIO;
2520 :
2521 0 : addr += mlen / 2;
2522 0 : fw += mlen;
2523 0 : size -= mlen;
2524 0 : }
2525 :
2526 : /* check whether the upload succeeded */
2527 0 : req.bmRequestType = UT_READ_VENDOR_DEVICE;
2528 0 : req.bRequest = ZYD_DOWNLOADSTS;
2529 0 : USETW(req.wValue, 0);
2530 0 : USETW(req.wIndex, 0);
2531 0 : USETW(req.wLength, sizeof stat);
2532 0 : if (usbd_do_request(sc->sc_udev, &req, &stat) != 0)
2533 0 : return EIO;
2534 :
2535 0 : return (stat & 0x80) ? EIO : 0;
2536 0 : }
2537 :
2538 : void
2539 0 : zyd_iter_func(void *arg, struct ieee80211_node *ni)
2540 : {
2541 0 : struct zyd_softc *sc = arg;
2542 0 : struct zyd_node *zn = (struct zyd_node *)ni;
2543 :
2544 0 : ieee80211_amrr_choose(&sc->amrr, ni, &zn->amn);
2545 0 : }
2546 :
2547 : void
2548 0 : zyd_amrr_timeout(void *arg)
2549 : {
2550 0 : struct zyd_softc *sc = arg;
2551 0 : struct ieee80211com *ic = &sc->sc_ic;
2552 : int s;
2553 :
2554 0 : s = splnet();
2555 0 : if (ic->ic_opmode == IEEE80211_M_STA)
2556 0 : zyd_iter_func(sc, ic->ic_bss);
2557 : else
2558 0 : ieee80211_iterate_nodes(ic, zyd_iter_func, sc);
2559 0 : splx(s);
2560 :
2561 0 : timeout_add_sec(&sc->amrr_to, 1);
2562 0 : }
2563 :
2564 : void
2565 0 : zyd_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
2566 : {
2567 0 : struct zyd_softc *sc = ic->ic_softc;
2568 : int i;
2569 :
2570 0 : ieee80211_amrr_node_init(&sc->amrr, &((struct zyd_node *)ni)->amn);
2571 :
2572 : /* set rate to some reasonable initial value */
2573 0 : for (i = ni->ni_rates.rs_nrates - 1;
2574 0 : i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
2575 0 : i--);
2576 0 : ni->ni_txrate = i;
2577 0 : }
|