Annotation of sys/dev/usb/if_uath.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_uath.c,v 1.27 2007/07/18 18:10:31 damien Exp $ */
2:
3: /*-
4: * Copyright (c) 2006
5: * Damien Bergamini <damien.bergamini@free.fr>
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: * Driver for Atheros AR5005UG/AR5005UX chipsets.
22: * http://www.atheros.com/pt/bulletins/AR5005UGBulletin.pdf
23: * http://www.atheros.com/pt/bulletins/AR5005UXBulletin.pdf
24: *
25: * IMPORTANT NOTICE:
26: * This driver was written without any documentation or support from Atheros
27: * Communications. It is based on a black-box analysis of the Windows binary
28: * driver. It handles both pre and post-firmware devices.
29: */
30:
31: #include "bpfilter.h"
32:
33: #include <sys/param.h>
34: #include <sys/sockio.h>
35: #include <sys/sysctl.h>
36: #include <sys/mbuf.h>
37: #include <sys/kernel.h>
38: #include <sys/socket.h>
39: #include <sys/systm.h>
40: #include <sys/malloc.h>
41: #include <sys/timeout.h>
42: #include <sys/conf.h>
43: #include <sys/device.h>
44:
45: #include <machine/bus.h>
46: #include <machine/endian.h>
47: #include <machine/intr.h>
48:
49: #if NBPFILTER > 0
50: #include <net/bpf.h>
51: #endif
52: #include <net/if.h>
53: #include <net/if_arp.h>
54: #include <net/if_dl.h>
55: #include <net/if_media.h>
56: #include <net/if_types.h>
57:
58: #include <netinet/in.h>
59: #include <netinet/in_systm.h>
60: #include <netinet/in_var.h>
61: #include <netinet/if_ether.h>
62: #include <netinet/ip.h>
63:
64: #include <net80211/ieee80211_var.h>
65: #include <net80211/ieee80211_radiotap.h>
66:
67: #include <dev/rndvar.h>
68: #include <crypto/arc4.h>
69:
70: #include <dev/usb/usb.h>
71: #include <dev/usb/usbdi.h>
72: #include <dev/usb/usbdivar.h> /* needs_reattach() */
73: #include <dev/usb/usbdi_util.h>
74: #include <dev/usb/usbdevs.h>
75:
76: #include <dev/usb/if_uathreg.h>
77: #include <dev/usb/if_uathvar.h>
78:
79: #ifdef USB_DEBUG
80: #define UATH_DEBUG
81: #endif
82:
83: #ifdef UATH_DEBUG
84: #define DPRINTF(x) do { if (uath_debug) printf x; } while (0)
85: #define DPRINTFN(n, x) do { if (uath_debug >= (n)) printf x; } while (0)
86: int uath_debug = 1;
87: #else
88: #define DPRINTF(x)
89: #define DPRINTFN(n, x)
90: #endif
91:
92: /*-
93: * Various supported device vendors/products.
94: * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g
95: */
96: #define UATH_DEV(v, p, f) \
97: { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) }, \
98: { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p##_NF }, \
99: (f) | UATH_FLAG_PRE_FIRMWARE }
100: #define UATH_DEV_UG(v, p) UATH_DEV(v, p, 0)
101: #define UATH_DEV_UX(v, p) UATH_DEV(v, p, UATH_FLAG_ABG)
102: static const struct uath_type {
103: struct usb_devno dev;
104: unsigned int flags;
105: #define UATH_FLAG_PRE_FIRMWARE (1 << 0)
106: #define UATH_FLAG_ABG (1 << 1)
107: } uath_devs[] = {
108: UATH_DEV_UG(ATHEROS, AR5523),
109: UATH_DEV_UG(ATHEROS2, AR5523_1),
110: UATH_DEV_UG(ATHEROS2, AR5523_2),
111: UATH_DEV_UX(ATHEROS2, AR5523_3),
112: UATH_DEV_UG(CONCEPTRONIC, AR5523_1),
113: UATH_DEV_UX(CONCEPTRONIC, AR5523_2),
114: UATH_DEV_UX(DLINK, DWLAG122),
115: UATH_DEV_UX(DLINK, DWLAG132),
116: UATH_DEV_UG(DLINK, DWLG132),
117: UATH_DEV_UG(GIGASET, AR5523),
118: UATH_DEV_UG(GIGASET, SMCWUSBTG),
119: UATH_DEV_UG(GLOBALSUN, AR5523_1),
120: UATH_DEV_UX(GLOBALSUN, AR5523_2),
121: UATH_DEV_UX(NETGEAR, WG111U),
122: UATH_DEV_UG(NETGEAR3, WG111T),
123: UATH_DEV_UG(NETGEAR3, WPN111),
124: UATH_DEV_UG(UMEDIA, AR5523_1),
125: UATH_DEV_UX(UMEDIA, AR5523_2),
126: UATH_DEV_UG(UMEDIA, TEW444UBEU),
127: UATH_DEV_UG(WISTRONNEWEB, AR5523_1),
128: UATH_DEV_UX(WISTRONNEWEB, AR5523_2),
129: UATH_DEV_UG(ZCOM, AR5523)
130: };
131: #define uath_lookup(v, p) \
132: ((const struct uath_type *)usb_lookup(uath_devs, v, p))
133:
134: void uath_attachhook(void *);
135: int uath_open_pipes(struct uath_softc *);
136: void uath_close_pipes(struct uath_softc *);
137: int uath_alloc_tx_data_list(struct uath_softc *);
138: void uath_free_tx_data_list(struct uath_softc *);
139: int uath_alloc_rx_data_list(struct uath_softc *);
140: void uath_free_rx_data_list(struct uath_softc *);
141: void uath_free_rx_data(caddr_t, u_int, void *);
142: int uath_alloc_tx_cmd_list(struct uath_softc *);
143: void uath_free_tx_cmd_list(struct uath_softc *);
144: int uath_alloc_rx_cmd_list(struct uath_softc *);
145: void uath_free_rx_cmd_list(struct uath_softc *);
146: int uath_media_change(struct ifnet *);
147: void uath_stat(void *);
148: void uath_next_scan(void *);
149: void uath_task(void *);
150: int uath_newstate(struct ieee80211com *, enum ieee80211_state, int);
151: #ifdef UATH_DEBUG
152: void uath_dump_cmd(const uint8_t *, int, char);
153: #endif
154: int uath_cmd(struct uath_softc *, uint32_t, const void *, int, void *,
155: int);
156: int uath_cmd_write(struct uath_softc *, uint32_t, const void *, int, int);
157: int uath_cmd_read(struct uath_softc *, uint32_t, const void *, int, void *,
158: int);
159: int uath_write_reg(struct uath_softc *, uint32_t, uint32_t);
160: int uath_write_multi(struct uath_softc *, uint32_t, const void *, int);
161: int uath_read_reg(struct uath_softc *, uint32_t, uint32_t *);
162: int uath_read_eeprom(struct uath_softc *, uint32_t, void *);
163: void uath_cmd_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
164: void uath_data_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
165: void uath_data_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
166: int uath_tx_null(struct uath_softc *);
167: int uath_tx_data(struct uath_softc *, struct mbuf *,
168: struct ieee80211_node *);
169: void uath_start(struct ifnet *);
170: void uath_watchdog(struct ifnet *);
171: int uath_ioctl(struct ifnet *, u_long, caddr_t);
172: int uath_query_eeprom(struct uath_softc *);
173: int uath_reset(struct uath_softc *);
174: int uath_reset_tx_queues(struct uath_softc *);
175: int uath_wme_init(struct uath_softc *);
176: int uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
177: int uath_set_key(struct uath_softc *, const struct ieee80211_key *, int);
178: int uath_set_keys(struct uath_softc *);
179: int uath_set_rates(struct uath_softc *, const struct ieee80211_rateset *);
180: int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
181: int uath_set_led(struct uath_softc *, int, int);
182: int uath_switch_channel(struct uath_softc *, struct ieee80211_channel *);
183: int uath_init(struct ifnet *);
184: void uath_stop(struct ifnet *, int);
185: int uath_loadfirmware(struct uath_softc *, const u_char *, int);
186: int uath_activate(struct device *, enum devact);
187:
188: int uath_match(struct device *, void *, void *);
189: void uath_attach(struct device *, struct device *, void *);
190: int uath_detach(struct device *, int);
191: int uath_activate(struct device *, enum devact);
192:
193: struct cfdriver uath_cd = {
194: NULL, "uath", DV_DULL
195: };
196:
197: const struct cfattach uath_ca = {
198: sizeof(struct uath_softc),
199: uath_match,
200: uath_attach,
201: uath_detach,
202: uath_activate,
203: };
204:
205: int
206: uath_match(struct device *parent, void *match, void *aux)
207: {
208: struct usb_attach_arg *uaa = aux;
209:
210: if (uaa->iface != NULL)
211: return UMATCH_NONE;
212:
213: return (uath_lookup(uaa->vendor, uaa->product) != NULL) ?
214: UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
215: }
216:
217: void
218: uath_attachhook(void *xsc)
219: {
220: struct uath_softc *sc = xsc;
221: u_char *fw;
222: size_t size;
223: int error;
224:
225: if ((error = loadfirmware("uath-ar5523", &fw, &size)) != 0) {
226: printf("%s: could not read firmware (error=%d)\n",
227: sc->sc_dev.dv_xname, error);
228: return;
229: }
230:
231: error = uath_loadfirmware(sc, fw, size);
232: free(fw, M_DEVBUF);
233:
234: if (error == 0) {
235: usb_port_status_t status;
236:
237: /*
238: * Hack alert: the device doesn't always gracefully detach
239: * from the bus after a firmware upload. We need to force
240: * a port reset and a re-exploration on the parent hub.
241: */
242: usbd_reset_port(sc->sc_uhub, sc->sc_port, &status);
243: usb_needs_reattach(sc->sc_udev);
244: } else {
245: printf("%s: could not load firmware (error=%s)\n",
246: sc->sc_dev.dv_xname, usbd_errstr(error));
247: }
248: }
249:
250: void
251: uath_attach(struct device *parent, struct device *self, void *aux)
252: {
253: struct uath_softc *sc = (struct uath_softc *)self;
254: struct usb_attach_arg *uaa = aux;
255: struct ieee80211com *ic = &sc->sc_ic;
256: struct ifnet *ifp = &ic->ic_if;
257: usbd_status error;
258: char *devinfop;
259: int i;
260:
261: sc->sc_udev = uaa->device;
262: sc->sc_uhub = uaa->device->myhub;
263: sc->sc_port = uaa->port;
264:
265: devinfop = usbd_devinfo_alloc(uaa->device, 0);
266: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
267: usbd_devinfo_free(devinfop);
268:
269: sc->sc_flags = uath_lookup(uaa->vendor, uaa->product)->flags;
270:
271: if (usbd_set_config_no(sc->sc_udev, UATH_CONFIG_NO, 0) != 0) {
272: printf("%s: could not set configuration no\n",
273: sc->sc_dev.dv_xname);
274: return;
275: }
276:
277: /* get the first interface handle */
278: error = usbd_device2interface_handle(sc->sc_udev, UATH_IFACE_INDEX,
279: &sc->sc_iface);
280: if (error != 0) {
281: printf("%s: could not get interface handle\n",
282: sc->sc_dev.dv_xname);
283: return;
284: }
285:
286: /*
287: * We must open the pipes early because they're used to upload the
288: * firmware (pre-firmware devices) or to send firmware commands.
289: */
290: if (uath_open_pipes(sc) != 0) {
291: printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
292: return;
293: }
294:
295: if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE) {
296: if (rootvp == NULL)
297: mountroothook_establish(uath_attachhook, sc);
298: else
299: uath_attachhook(sc);
300: return;
301: }
302:
303: /*
304: * Only post-firmware devices here.
305: */
306: usb_init_task(&sc->sc_task, uath_task, sc);
307: timeout_set(&sc->scan_to, uath_next_scan, sc);
308: timeout_set(&sc->stat_to, uath_stat, sc);
309:
310: /*
311: * Allocate xfers for firmware commands.
312: */
313: if (uath_alloc_tx_cmd_list(sc) != 0) {
314: printf("%s: could not allocate Tx command list\n",
315: sc->sc_dev.dv_xname);
316: goto fail1;
317: }
318: if (uath_alloc_rx_cmd_list(sc) != 0) {
319: printf("%s: could not allocate Rx command list\n",
320: sc->sc_dev.dv_xname);
321: goto fail2;
322: }
323:
324: /*
325: * Queue Rx command xfers.
326: */
327: for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++) {
328: struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
329:
330: usbd_setup_xfer(cmd->xfer, sc->cmd_rx_pipe, cmd, cmd->buf,
331: UATH_MAX_RXCMDSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
332: USBD_NO_TIMEOUT, uath_cmd_rxeof);
333: error = usbd_transfer(cmd->xfer);
334: if (error != USBD_IN_PROGRESS && error != 0) {
335: printf("%s: could not queue Rx command xfer\n",
336: sc->sc_dev.dv_xname);
337: goto fail3;
338: }
339: }
340:
341: /*
342: * We're now ready to send/receive firmware commands.
343: */
344: if (uath_reset(sc) != 0) {
345: printf("%s: could not initialize adapter\n",
346: sc->sc_dev.dv_xname);
347: goto fail3;
348: }
349: if (uath_query_eeprom(sc) != 0) {
350: printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
351: goto fail3;
352: }
353:
354: printf("%s: MAC/BBP AR5523, RF AR%c112, address %s\n",
355: sc->sc_dev.dv_xname, (sc->sc_flags & UATH_FLAG_ABG) ? '5': '2',
356: ether_sprintf(ic->ic_myaddr));
357:
358: /*
359: * Allocate xfers for Tx/Rx data pipes.
360: */
361: if (uath_alloc_tx_data_list(sc) != 0) {
362: printf("%s: could not allocate Tx data list\n",
363: sc->sc_dev.dv_xname);
364: goto fail3;
365: }
366: if (uath_alloc_rx_data_list(sc) != 0) {
367: printf("%s: could not allocate Rx data list\n",
368: sc->sc_dev.dv_xname);
369: goto fail4;
370: }
371:
372: ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
373: ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
374: ic->ic_state = IEEE80211_S_INIT;
375:
376: /* set device capabilities */
377: ic->ic_caps =
378: IEEE80211_C_TXPMGT | /* tx power management */
379: IEEE80211_C_SHPREAMBLE | /* short preamble supported */
380: IEEE80211_C_SHSLOT | /* short slot time supported */
381: IEEE80211_C_WEP; /* h/w WEP */
382:
383: /* set supported .11b and .11g rates */
384: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
385: ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
386:
387: /* set supported .11b and .11g channels (1 through 14) */
388: for (i = 1; i <= 14; i++) {
389: ic->ic_channels[i].ic_freq =
390: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
391: ic->ic_channels[i].ic_flags =
392: IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
393: IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
394: }
395:
396: ifp->if_softc = sc;
397: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
398: ifp->if_init = uath_init;
399: ifp->if_ioctl = uath_ioctl;
400: ifp->if_start = uath_start;
401: ifp->if_watchdog = uath_watchdog;
402: IFQ_SET_READY(&ifp->if_snd);
403: memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
404:
405: if_attach(ifp);
406: ieee80211_ifattach(ifp);
407:
408: /* override state transition machine */
409: sc->sc_newstate = ic->ic_newstate;
410: ic->ic_newstate = uath_newstate;
411: ieee80211_media_init(ifp, uath_media_change, ieee80211_media_status);
412:
413: #if NBPFILTER > 0
414: bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
415: sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
416:
417: sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
418: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
419: sc->sc_rxtap.wr_ihdr.it_present = htole32(UATH_RX_RADIOTAP_PRESENT);
420:
421: sc->sc_txtap_len = sizeof sc->sc_txtapu;
422: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
423: sc->sc_txtap.wt_ihdr.it_present = htole32(UATH_TX_RADIOTAP_PRESENT);
424: #endif
425:
426: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
427: &sc->sc_dev);
428:
429: return;
430:
431: fail4: uath_free_tx_data_list(sc);
432: fail3: uath_free_rx_cmd_list(sc);
433: fail2: uath_free_tx_cmd_list(sc);
434: fail1: uath_close_pipes(sc);
435: }
436:
437: int
438: uath_detach(struct device *self, int flags)
439: {
440: struct uath_softc *sc = (struct uath_softc *)self;
441: struct ifnet *ifp = &sc->sc_ic.ic_if;
442: int s;
443:
444: s = splnet();
445:
446: if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE) {
447: uath_close_pipes(sc);
448: splx(s);
449: return 0;
450: }
451:
452: /* post-firmware device */
453:
454: usb_rem_task(sc->sc_udev, &sc->sc_task);
455: timeout_del(&sc->scan_to);
456: timeout_del(&sc->stat_to);
457:
458: ieee80211_ifdetach(ifp); /* free all nodes */
459: if_detach(ifp);
460:
461: sc->sc_dying = 1;
462: DPRINTF(("reclaiming %d references\n", sc->sc_refcnt));
463: while (sc->sc_refcnt > 0)
464: (void)tsleep(UATH_COND_NOREF(sc), 0, "uathdet", 0);
465: DPRINTF(("all references reclaimed\n"));
466:
467: /* abort and free xfers */
468: uath_free_tx_data_list(sc);
469: uath_free_rx_data_list(sc);
470: uath_free_tx_cmd_list(sc);
471: uath_free_rx_cmd_list(sc);
472:
473: /* close Tx/Rx pipes */
474: uath_close_pipes(sc);
475:
476: splx(s);
477:
478: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
479: &sc->sc_dev);
480:
481: return 0;
482: }
483:
484: int
485: uath_open_pipes(struct uath_softc *sc)
486: {
487: int error;
488:
489: /*
490: * XXX pipes numbers are hardcoded because we don't have any way
491: * to distinguish the data pipes from the firmware command pipes
492: * (both are bulk pipes) using the endpoints descriptors.
493: */
494: error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE,
495: &sc->cmd_tx_pipe);
496: if (error != 0) {
497: printf("%s: could not open Tx command pipe: %s\n",
498: sc->sc_dev.dv_xname, usbd_errstr(error));
499: goto fail;
500: }
501:
502: error = usbd_open_pipe(sc->sc_iface, 0x02, USBD_EXCLUSIVE_USE,
503: &sc->data_tx_pipe);
504: if (error != 0) {
505: printf("%s: could not open Tx data pipe: %s\n",
506: sc->sc_dev.dv_xname, usbd_errstr(error));
507: goto fail;
508: }
509:
510: error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE,
511: &sc->cmd_rx_pipe);
512: if (error != 0) {
513: printf("%s: could not open Rx command pipe: %s\n",
514: sc->sc_dev.dv_xname, usbd_errstr(error));
515: goto fail;
516: }
517:
518: error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE,
519: &sc->data_rx_pipe);
520: if (error != 0) {
521: printf("%s: could not open Rx data pipe: %s\n",
522: sc->sc_dev.dv_xname, usbd_errstr(error));
523: goto fail;
524: }
525:
526: return 0;
527:
528: fail: uath_close_pipes(sc);
529: return error;
530: }
531:
532: void
533: uath_close_pipes(struct uath_softc *sc)
534: {
535: /* assumes no transfers are pending on the pipes */
536:
537: if (sc->data_tx_pipe != NULL)
538: usbd_close_pipe(sc->data_tx_pipe);
539:
540: if (sc->data_rx_pipe != NULL)
541: usbd_close_pipe(sc->data_rx_pipe);
542:
543: if (sc->cmd_tx_pipe != NULL)
544: usbd_close_pipe(sc->cmd_tx_pipe);
545:
546: if (sc->cmd_rx_pipe != NULL)
547: usbd_close_pipe(sc->cmd_rx_pipe);
548: }
549:
550: int
551: uath_alloc_tx_data_list(struct uath_softc *sc)
552: {
553: int i, error;
554:
555: for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
556: struct uath_tx_data *data = &sc->tx_data[i];
557:
558: data->sc = sc; /* backpointer for callbacks */
559:
560: data->xfer = usbd_alloc_xfer(sc->sc_udev);
561: if (data->xfer == NULL) {
562: printf("%s: could not allocate xfer\n",
563: sc->sc_dev.dv_xname);
564: error = ENOMEM;
565: goto fail;
566: }
567: data->buf = usbd_alloc_buffer(data->xfer, UATH_MAX_TXBUFSZ);
568: if (data->buf == NULL) {
569: printf("%s: could not allocate xfer buffer\n",
570: sc->sc_dev.dv_xname);
571: error = ENOMEM;
572: goto fail;
573: }
574: }
575: return 0;
576:
577: fail: uath_free_tx_data_list(sc);
578: return error;
579: }
580:
581: void
582: uath_free_tx_data_list(struct uath_softc *sc)
583: {
584: int i;
585:
586: /* make sure no transfers are pending */
587: usbd_abort_pipe(sc->data_tx_pipe);
588:
589: for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++)
590: if (sc->tx_data[i].xfer != NULL)
591: usbd_free_xfer(sc->tx_data[i].xfer);
592: }
593:
594: int
595: uath_alloc_rx_data_list(struct uath_softc *sc)
596: {
597: int i, error;
598:
599: SLIST_INIT(&sc->rx_freelist);
600: for (i = 0; i < UATH_RX_DATA_POOL_COUNT; i++) {
601: struct uath_rx_data *data = &sc->rx_data[i];
602:
603: data->sc = sc; /* backpointer for callbacks */
604:
605: data->xfer = usbd_alloc_xfer(sc->sc_udev);
606: if (data->xfer == NULL) {
607: printf("%s: could not allocate xfer\n",
608: sc->sc_dev.dv_xname);
609: error = ENOMEM;
610: goto fail;
611: }
612: data->buf = usbd_alloc_buffer(data->xfer, sc->rxbufsz);
613: if (data->buf == NULL) {
614: printf("%s: could not allocate xfer buffer\n",
615: sc->sc_dev.dv_xname);
616: error = ENOMEM;
617: goto fail;
618: }
619: SLIST_INSERT_HEAD(&sc->rx_freelist, data, next);
620: }
621: return 0;
622:
623: fail: uath_free_rx_data_list(sc);
624: return error;
625: }
626:
627: void
628: uath_free_rx_data_list(struct uath_softc *sc)
629: {
630: int i;
631:
632: /* make sure no transfers are pending */
633: usbd_abort_pipe(sc->data_rx_pipe);
634:
635: for (i = 0; i < UATH_RX_DATA_POOL_COUNT; i++)
636: if (sc->rx_data[i].xfer != NULL)
637: usbd_free_xfer(sc->rx_data[i].xfer);
638: }
639:
640: void
641: uath_free_rx_data(caddr_t buf, u_int size, void *arg)
642: {
643: struct uath_rx_data *data = arg;
644: struct uath_softc *sc = data->sc;
645:
646: /* put the buffer back in the free list */
647: SLIST_INSERT_HEAD(&sc->rx_freelist, data, next);
648:
649: /* release reference to softc */
650: if (--sc->sc_refcnt == 0 && sc->sc_dying)
651: wakeup(UATH_COND_NOREF(sc));
652: }
653:
654: int
655: uath_alloc_tx_cmd_list(struct uath_softc *sc)
656: {
657: int i, error;
658:
659: for (i = 0; i < UATH_TX_CMD_LIST_COUNT; i++) {
660: struct uath_tx_cmd *cmd = &sc->tx_cmd[i];
661:
662: cmd->sc = sc; /* backpointer for callbacks */
663:
664: cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
665: if (cmd->xfer == NULL) {
666: printf("%s: could not allocate xfer\n",
667: sc->sc_dev.dv_xname);
668: error = ENOMEM;
669: goto fail;
670: }
671: cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_TXCMDSZ);
672: if (cmd->buf == NULL) {
673: printf("%s: could not allocate xfer buffer\n",
674: sc->sc_dev.dv_xname);
675: error = ENOMEM;
676: goto fail;
677: }
678: }
679: return 0;
680:
681: fail: uath_free_tx_cmd_list(sc);
682: return error;
683: }
684:
685: void
686: uath_free_tx_cmd_list(struct uath_softc *sc)
687: {
688: int i;
689:
690: /* make sure no transfers are pending */
691: usbd_abort_pipe(sc->cmd_tx_pipe);
692:
693: for (i = 0; i < UATH_TX_CMD_LIST_COUNT; i++)
694: if (sc->tx_cmd[i].xfer != NULL)
695: usbd_free_xfer(sc->tx_cmd[i].xfer);
696: }
697:
698: int
699: uath_alloc_rx_cmd_list(struct uath_softc *sc)
700: {
701: int i, error;
702:
703: for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++) {
704: struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
705:
706: cmd->sc = sc; /* backpointer for callbacks */
707:
708: cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
709: if (cmd->xfer == NULL) {
710: printf("%s: could not allocate xfer\n",
711: sc->sc_dev.dv_xname);
712: error = ENOMEM;
713: goto fail;
714: }
715: cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_RXCMDSZ);
716: if (cmd->buf == NULL) {
717: printf("%s: could not allocate xfer buffer\n",
718: sc->sc_dev.dv_xname);
719: error = ENOMEM;
720: goto fail;
721: }
722: }
723: return 0;
724:
725: fail: uath_free_rx_cmd_list(sc);
726: return error;
727: }
728:
729: void
730: uath_free_rx_cmd_list(struct uath_softc *sc)
731: {
732: int i;
733:
734: /* make sure no transfers are pending */
735: usbd_abort_pipe(sc->cmd_rx_pipe);
736:
737: for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++)
738: if (sc->rx_cmd[i].xfer != NULL)
739: usbd_free_xfer(sc->rx_cmd[i].xfer);
740: }
741:
742: int
743: uath_media_change(struct ifnet *ifp)
744: {
745: int error;
746:
747: error = ieee80211_media_change(ifp);
748: if (error != ENETRESET)
749: return error;
750:
751: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
752: uath_init(ifp);
753:
754: return 0;
755: }
756:
757: /*
758: * This function is called periodically (every second) when associated to
759: * query device statistics.
760: */
761: void
762: uath_stat(void *arg)
763: {
764: struct uath_softc *sc = arg;
765: int error;
766:
767: /*
768: * Send request for statistics asynchronously. The timer will be
769: * restarted when we'll get the stats notification.
770: */
771: error = uath_cmd_write(sc, UATH_CMD_STATS, NULL, 0,
772: UATH_CMD_FLAG_ASYNC);
773: if (error != 0) {
774: printf("%s: could not query statistics (error=%d)\n",
775: sc->sc_dev.dv_xname, error);
776: }
777: }
778:
779: /*
780: * This function is called periodically (every 250ms) during scanning to
781: * switch from one channel to another.
782: */
783: void
784: uath_next_scan(void *arg)
785: {
786: struct uath_softc *sc = arg;
787: struct ieee80211com *ic = &sc->sc_ic;
788: struct ifnet *ifp = &ic->ic_if;
789:
790: if (ic->ic_state == IEEE80211_S_SCAN)
791: ieee80211_next_scan(ifp);
792: }
793:
794: void
795: uath_task(void *arg)
796: {
797: struct uath_softc *sc = arg;
798: struct ieee80211com *ic = &sc->sc_ic;
799: enum ieee80211_state ostate;
800:
801: ostate = ic->ic_state;
802:
803: switch (sc->sc_state) {
804: case IEEE80211_S_INIT:
805: if (ostate == IEEE80211_S_RUN) {
806: /* turn link and activity LEDs off */
807: (void)uath_set_led(sc, UATH_LED_LINK, 0);
808: (void)uath_set_led(sc, UATH_LED_ACTIVITY, 0);
809: }
810: break;
811:
812: case IEEE80211_S_SCAN:
813: if (uath_switch_channel(sc, ic->ic_bss->ni_chan) != 0) {
814: printf("%s: could not switch channel\n",
815: sc->sc_dev.dv_xname);
816: break;
817: }
818: timeout_add(&sc->scan_to, hz / 4);
819: break;
820:
821: case IEEE80211_S_AUTH:
822: {
823: struct ieee80211_node *ni = ic->ic_bss;
824: struct uath_cmd_bssid bssid;
825: struct uath_cmd_0b cmd0b;
826: struct uath_cmd_0c cmd0c;
827:
828: if (uath_switch_channel(sc, ni->ni_chan) != 0) {
829: printf("%s: could not switch channel\n",
830: sc->sc_dev.dv_xname);
831: break;
832: }
833:
834: (void)uath_cmd_write(sc, UATH_CMD_24, NULL, 0, 0);
835:
836: bzero(&bssid, sizeof bssid);
837: bssid.len = htobe32(IEEE80211_ADDR_LEN);
838: IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid);
839: (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID, &bssid,
840: sizeof bssid, 0);
841:
842: bzero(&cmd0b, sizeof cmd0b);
843: cmd0b.code = htobe32(2);
844: cmd0b.size = htobe32(sizeof (cmd0b.data));
845: (void)uath_cmd_write(sc, UATH_CMD_0B, &cmd0b, sizeof cmd0b, 0);
846:
847: bzero(&cmd0c, sizeof cmd0c);
848: cmd0c.magic1 = htobe32(2);
849: cmd0c.magic2 = htobe32(7);
850: cmd0c.magic3 = htobe32(1);
851: (void)uath_cmd_write(sc, UATH_CMD_0C, &cmd0c, sizeof cmd0c, 0);
852:
853: if (uath_set_rates(sc, &ni->ni_rates) != 0) {
854: printf("%s: could not set negotiated rate set\n",
855: sc->sc_dev.dv_xname);
856: break;
857: }
858: break;
859: }
860:
861: case IEEE80211_S_ASSOC:
862: break;
863:
864: case IEEE80211_S_RUN:
865: {
866: struct ieee80211_node *ni = ic->ic_bss;
867: struct uath_cmd_bssid bssid;
868: struct uath_cmd_xled xled;
869: uint32_t val;
870:
871: if (ic->ic_opmode == IEEE80211_M_MONITOR) {
872: /* make both LEDs blink while monitoring */
873: bzero(&xled, sizeof xled);
874: xled.which = htobe32(0);
875: xled.rate = htobe32(1);
876: xled.mode = htobe32(2);
877: (void)uath_cmd_write(sc, UATH_CMD_SET_XLED, &xled,
878: sizeof xled, 0);
879: break;
880: }
881:
882: /*
883: * Tx rate is controlled by firmware, report the maximum
884: * negotiated rate in ifconfig output.
885: */
886: ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
887:
888: val = htobe32(1);
889: (void)uath_cmd_write(sc, UATH_CMD_2E, &val, sizeof val, 0);
890:
891: bzero(&bssid, sizeof bssid);
892: bssid.flags1 = htobe32(0xc004);
893: bssid.flags2 = htobe32(0x003b);
894: bssid.len = htobe32(IEEE80211_ADDR_LEN);
895: IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid);
896: (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID, &bssid,
897: sizeof bssid, 0);
898:
899: /* turn link LED on */
900: (void)uath_set_led(sc, UATH_LED_LINK, 1);
901:
902: /* make activity LED blink */
903: bzero(&xled, sizeof xled);
904: xled.which = htobe32(1);
905: xled.rate = htobe32(1);
906: xled.mode = htobe32(2);
907: (void)uath_cmd_write(sc, UATH_CMD_SET_XLED, &xled, sizeof xled,
908: 0);
909:
910: /* set state to associated */
911: val = htobe32(1);
912: (void)uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val,
913: 0);
914:
915: /* start statistics timer */
916: timeout_add(&sc->stat_to, hz);
917: break;
918: }
919: }
920: sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
921: }
922:
923: int
924: uath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
925: {
926: struct uath_softc *sc = ic->ic_softc;
927:
928: usb_rem_task(sc->sc_udev, &sc->sc_task);
929: timeout_del(&sc->scan_to);
930: timeout_del(&sc->stat_to);
931:
932: /* do it in a process context */
933: sc->sc_state = nstate;
934: sc->sc_arg = arg;
935: usb_add_task(sc->sc_udev, &sc->sc_task);
936: return 0;
937: }
938:
939: #ifdef UATH_DEBUG
940: void
941: uath_dump_cmd(const uint8_t *buf, int len, char prefix)
942: {
943: int i;
944:
945: for (i = 0; i < len; i++) {
946: if ((i % 16) == 0)
947: printf("\n%c ", prefix);
948: else if ((i % 4) == 0)
949: printf(" ");
950: printf("%02x", buf[i]);
951: }
952: printf("\n");
953: }
954: #endif
955:
956: /*
957: * Low-level function to send read or write commands to the firmware.
958: */
959: int
960: uath_cmd(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
961: void *odata, int flags)
962: {
963: struct uath_cmd_hdr *hdr;
964: struct uath_tx_cmd *cmd;
965: uint16_t xferflags;
966: int s, xferlen, error;
967:
968: /* grab a xfer */
969: cmd = &sc->tx_cmd[sc->cmd_idx];
970:
971: /* always bulk-out a multiple of 4 bytes */
972: xferlen = (sizeof (struct uath_cmd_hdr) + ilen + 3) & ~3;
973:
974: hdr = (struct uath_cmd_hdr *)cmd->buf;
975: bzero(hdr, sizeof (struct uath_cmd_hdr));
976: hdr->len = htobe32(xferlen);
977: hdr->code = htobe32(code);
978: hdr->priv = sc->cmd_idx; /* don't care about endianness */
979: hdr->magic = htobe32((flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
980: bcopy(idata, (uint8_t *)(hdr + 1), ilen);
981:
982: #ifdef UATH_DEBUG
983: if (uath_debug >= 5) {
984: printf("sending command code=0x%02x flags=0x%x index=%u",
985: code, flags, sc->cmd_idx);
986: uath_dump_cmd(cmd->buf, xferlen, '+');
987: }
988: #endif
989: xferflags = USBD_FORCE_SHORT_XFER | USBD_NO_COPY;
990: if (!(flags & UATH_CMD_FLAG_READ)) {
991: if (!(flags & UATH_CMD_FLAG_ASYNC))
992: xferflags |= USBD_SYNCHRONOUS;
993: } else
994: s = splusb();
995:
996: cmd->odata = odata;
997:
998: usbd_setup_xfer(cmd->xfer, sc->cmd_tx_pipe, cmd, cmd->buf, xferlen,
999: xferflags, UATH_CMD_TIMEOUT, NULL);
1000: error = usbd_transfer(cmd->xfer);
1001: if (error != USBD_IN_PROGRESS && error != 0) {
1002: if (flags & UATH_CMD_FLAG_READ)
1003: splx(s);
1004: printf("%s: could not send command 0x%x (error=%s)\n",
1005: sc->sc_dev.dv_xname, code, usbd_errstr(error));
1006: return error;
1007: }
1008: sc->cmd_idx = (sc->cmd_idx + 1) % UATH_TX_CMD_LIST_COUNT;
1009:
1010: if (!(flags & UATH_CMD_FLAG_READ))
1011: return 0; /* write: don't wait for reply */
1012:
1013: /* wait at most two seconds for command reply */
1014: error = tsleep(cmd, PCATCH, "uathcmd", 2 * hz);
1015: cmd->odata = NULL; /* in case answer is received too late */
1016: splx(s);
1017: if (error != 0) {
1018: printf("%s: timeout waiting for command reply\n",
1019: sc->sc_dev.dv_xname);
1020: }
1021: return error;
1022: }
1023:
1024: int
1025: uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
1026: int flags)
1027: {
1028: flags &= ~UATH_CMD_FLAG_READ;
1029: return uath_cmd(sc, code, data, len, NULL, flags);
1030: }
1031:
1032: int
1033: uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
1034: int ilen, void *odata, int flags)
1035: {
1036: flags |= UATH_CMD_FLAG_READ;
1037: return uath_cmd(sc, code, idata, ilen, odata, flags);
1038: }
1039:
1040: int
1041: uath_write_reg(struct uath_softc *sc, uint32_t reg, uint32_t val)
1042: {
1043: struct uath_write_mac write;
1044: int error;
1045:
1046: write.reg = htobe32(reg);
1047: write.len = htobe32(0); /* 0 = single write */
1048: *(uint32_t *)write.data = htobe32(val);
1049:
1050: error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC, &write,
1051: 3 * sizeof (uint32_t), 0);
1052: if (error != 0) {
1053: printf("%s: could not write register 0x%02x\n",
1054: sc->sc_dev.dv_xname, reg);
1055: }
1056: return error;
1057: }
1058:
1059: int
1060: uath_write_multi(struct uath_softc *sc, uint32_t reg, const void *data,
1061: int len)
1062: {
1063: struct uath_write_mac write;
1064: int error;
1065:
1066: write.reg = htobe32(reg);
1067: write.len = htobe32(len);
1068: bcopy(data, write.data, len);
1069:
1070: /* properly handle the case where len is zero (reset) */
1071: error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC, &write,
1072: (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
1073: if (error != 0) {
1074: printf("%s: could not write %d bytes to register 0x%02x\n",
1075: sc->sc_dev.dv_xname, len, reg);
1076: }
1077: return error;
1078: }
1079:
1080: int
1081: uath_read_reg(struct uath_softc *sc, uint32_t reg, uint32_t *val)
1082: {
1083: struct uath_read_mac read;
1084: int error;
1085:
1086: reg = htobe32(reg);
1087: error = uath_cmd_read(sc, UATH_CMD_READ_MAC, ®, sizeof reg, &read,
1088: 0);
1089: if (error != 0) {
1090: printf("%s: could not read register 0x%02x\n",
1091: sc->sc_dev.dv_xname, betoh32(reg));
1092: return error;
1093: }
1094: *val = betoh32(*(uint32_t *)read.data);
1095: return error;
1096: }
1097:
1098: int
1099: uath_read_eeprom(struct uath_softc *sc, uint32_t reg, void *odata)
1100: {
1101: struct uath_read_mac read;
1102: int len, error;
1103:
1104: reg = htobe32(reg);
1105: error = uath_cmd_read(sc, UATH_CMD_READ_EEPROM, ®, sizeof reg,
1106: &read, 0);
1107: if (error != 0) {
1108: printf("%s: could not read EEPROM offset 0x%02x\n",
1109: sc->sc_dev.dv_xname, betoh32(reg));
1110: return error;
1111: }
1112: len = betoh32(read.len);
1113: bcopy(read.data, odata, (len == 0) ? sizeof (uint32_t) : len);
1114: return error;
1115: }
1116:
1117: void
1118: uath_cmd_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
1119: usbd_status status)
1120: {
1121: struct uath_rx_cmd *cmd = priv;
1122: struct uath_softc *sc = cmd->sc;
1123: struct uath_cmd_hdr *hdr;
1124:
1125: if (status != USBD_NORMAL_COMPLETION) {
1126: if (status == USBD_STALLED)
1127: usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
1128: return;
1129: }
1130:
1131: hdr = (struct uath_cmd_hdr *)cmd->buf;
1132:
1133: #ifdef UATH_DEBUG
1134: if (uath_debug >= 5) {
1135: printf("received command code=0x%x index=%u len=%u",
1136: betoh32(hdr->code), hdr->priv, betoh32(hdr->len));
1137: uath_dump_cmd(cmd->buf, betoh32(hdr->len), '-');
1138: }
1139: #endif
1140:
1141: switch (betoh32(hdr->code) & 0xff) {
1142: /* reply to a read command */
1143: default:
1144: {
1145: struct uath_tx_cmd *txcmd = &sc->tx_cmd[hdr->priv];
1146:
1147: if (txcmd->odata != NULL) {
1148: /* copy answer into caller's supplied buffer */
1149: bcopy((uint8_t *)(hdr + 1), txcmd->odata,
1150: betoh32(hdr->len) - sizeof (struct uath_cmd_hdr));
1151: }
1152: wakeup(txcmd); /* wake up caller */
1153: break;
1154: }
1155: /* spontaneous firmware notifications */
1156: case UATH_NOTIF_READY:
1157: DPRINTF(("received device ready notification\n"));
1158: wakeup(UATH_COND_INIT(sc));
1159: break;
1160:
1161: case UATH_NOTIF_TX:
1162: /* this notification is sent when UATH_TX_NOTIFY is set */
1163: DPRINTF(("received Tx notification\n"));
1164: break;
1165:
1166: case UATH_NOTIF_STATS:
1167: DPRINTFN(2, ("received device statistics\n"));
1168: timeout_add(&sc->stat_to, hz);
1169: break;
1170: }
1171:
1172: /* setup a new transfer */
1173: usbd_setup_xfer(xfer, sc->cmd_rx_pipe, cmd, cmd->buf, UATH_MAX_RXCMDSZ,
1174: USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1175: uath_cmd_rxeof);
1176: (void)usbd_transfer(xfer);
1177: }
1178:
1179: void
1180: uath_data_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
1181: usbd_status status)
1182: {
1183: struct uath_rx_data *data = priv;
1184: struct uath_softc *sc = data->sc;
1185: struct ieee80211com *ic = &sc->sc_ic;
1186: struct ifnet *ifp = &ic->ic_if;
1187: struct ieee80211_frame *wh;
1188: struct ieee80211_node *ni;
1189: struct uath_rx_data *ndata;
1190: struct uath_rx_desc *desc;
1191: struct mbuf *m;
1192: uint32_t hdr;
1193: int s, len;
1194:
1195: if (status != USBD_NORMAL_COMPLETION) {
1196: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1197: return;
1198:
1199: if (status == USBD_STALLED)
1200: usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
1201:
1202: ifp->if_ierrors++;
1203: return;
1204: }
1205: usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1206:
1207: if (len < UATH_MIN_RXBUFSZ) {
1208: DPRINTF(("wrong xfer size (len=%d)\n", len));
1209: ifp->if_ierrors++;
1210: goto skip;
1211: }
1212:
1213: hdr = betoh32(*(uint32_t *)data->buf);
1214:
1215: /* Rx descriptor is located at the end, 32-bit aligned */
1216: desc = (struct uath_rx_desc *)
1217: (data->buf + len - sizeof (struct uath_rx_desc));
1218:
1219: if (betoh32(desc->len) > sc->rxbufsz) {
1220: DPRINTF(("bad descriptor (len=%d)\n", betoh32(desc->len)));
1221: ifp->if_ierrors++;
1222: goto skip;
1223: }
1224:
1225: /* there's probably a "bad CRC" flag somewhere in the descriptor.. */
1226:
1227: MGETHDR(m, M_DONTWAIT, MT_DATA);
1228: if (m == NULL) {
1229: ifp->if_ierrors++;
1230: goto skip;
1231: }
1232:
1233: /* grab a new Rx buffer */
1234: ndata = SLIST_FIRST(&sc->rx_freelist);
1235: if (ndata == NULL) {
1236: printf("%s: could not allocate Rx buffer\n",
1237: sc->sc_dev.dv_xname);
1238: m_freem(m);
1239: ifp->if_ierrors++;
1240: goto skip;
1241: }
1242: SLIST_REMOVE_HEAD(&sc->rx_freelist, next);
1243:
1244: MEXTADD(m, data->buf, sc->rxbufsz, 0, uath_free_rx_data, data);
1245:
1246: /* finalize mbuf */
1247: m->m_pkthdr.rcvif = ifp;
1248: m->m_data = data->buf + sizeof (uint32_t);
1249: m->m_pkthdr.len = m->m_len = betoh32(desc->len) -
1250: sizeof (struct uath_rx_desc) - IEEE80211_CRC_LEN;
1251:
1252: data = ndata;
1253:
1254: wh = mtod(m, struct ieee80211_frame *);
1255: if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
1256: ic->ic_opmode != IEEE80211_M_MONITOR) {
1257: /*
1258: * Hardware decrypts the frame itself but leaves the WEP bit
1259: * set in the 802.11 header and doesn't remove the IV and CRC
1260: * fields.
1261: */
1262: wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1263: ovbcopy(wh, (caddr_t)wh + IEEE80211_WEP_IVLEN +
1264: IEEE80211_WEP_KIDLEN, sizeof (struct ieee80211_frame));
1265: m_adj(m, IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN);
1266: m_adj(m, -IEEE80211_WEP_CRCLEN);
1267: wh = mtod(m, struct ieee80211_frame *);
1268: }
1269:
1270: #if NBPFILTER > 0
1271: /* there are a lot more fields in the Rx descriptor */
1272: if (sc->sc_drvbpf != NULL) {
1273: struct mbuf mb;
1274: struct uath_rx_radiotap_header *tap = &sc->sc_rxtap;
1275:
1276: tap->wr_flags = 0;
1277: tap->wr_chan_freq = htole16(betoh32(desc->freq));
1278: tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
1279: tap->wr_dbm_antsignal = (int8_t)betoh32(desc->rssi);
1280:
1281: mb.m_data = (caddr_t)tap;
1282: mb.m_len = sc->sc_rxtap_len;
1283: mb.m_next = m;
1284: mb.m_nextpkt = NULL;
1285: mb.m_type = 0;
1286: mb.m_flags = 0;
1287: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
1288: }
1289: #endif
1290:
1291: s = splnet();
1292: sc->sc_refcnt++;
1293: ni = ieee80211_find_rxnode(ic, wh);
1294: ieee80211_input(ifp, m, ni, (int)betoh32(desc->rssi), 0);
1295:
1296: /* node is no longer needed */
1297: ieee80211_release_node(ic, ni);
1298: splx(s);
1299:
1300: skip: /* setup a new transfer */
1301: usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
1302: sc->rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1303: uath_data_rxeof);
1304: (void)usbd_transfer(data->xfer);
1305: }
1306:
1307: int
1308: uath_tx_null(struct uath_softc *sc)
1309: {
1310: struct uath_tx_data *data;
1311: struct uath_tx_desc *desc;
1312:
1313: data = &sc->tx_data[sc->data_idx];
1314:
1315: data->ni = NULL;
1316:
1317: *(uint32_t *)data->buf = UATH_MAKECTL(1, sizeof (struct uath_tx_desc));
1318: desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1319:
1320: bzero(desc, sizeof (struct uath_tx_desc));
1321: desc->len = htobe32(sizeof (struct uath_tx_desc));
1322: desc->type = htobe32(UATH_TX_NULL);
1323:
1324: usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf,
1325: sizeof (uint32_t) + sizeof (struct uath_tx_desc), USBD_NO_COPY |
1326: USBD_FORCE_SHORT_XFER, UATH_DATA_TIMEOUT, NULL);
1327: if (usbd_sync_transfer(data->xfer) != 0)
1328: return EIO;
1329:
1330: sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
1331:
1332: return uath_cmd_write(sc, UATH_CMD_0F, NULL, 0, UATH_CMD_FLAG_ASYNC);
1333: }
1334:
1335: void
1336: uath_data_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
1337: usbd_status status)
1338: {
1339: struct uath_tx_data *data = priv;
1340: struct uath_softc *sc = data->sc;
1341: struct ieee80211com *ic = &sc->sc_ic;
1342: struct ifnet *ifp = &ic->ic_if;
1343: int s;
1344:
1345: if (status != USBD_NORMAL_COMPLETION) {
1346: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1347: return;
1348:
1349: printf("%s: could not transmit buffer: %s\n",
1350: sc->sc_dev.dv_xname, usbd_errstr(status));
1351:
1352: if (status == USBD_STALLED)
1353: usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
1354:
1355: ifp->if_oerrors++;
1356: return;
1357: }
1358:
1359: s = splnet();
1360:
1361: ieee80211_release_node(ic, data->ni);
1362: data->ni = NULL;
1363:
1364: sc->tx_queued--;
1365: ifp->if_opackets++;
1366:
1367: sc->sc_tx_timer = 0;
1368: ifp->if_flags &= ~IFF_OACTIVE;
1369: uath_start(ifp);
1370:
1371: splx(s);
1372: }
1373:
1374: int
1375: uath_tx_data(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
1376: {
1377: struct ieee80211com *ic = &sc->sc_ic;
1378: struct uath_tx_data *data;
1379: struct uath_tx_desc *desc;
1380: const struct ieee80211_frame *wh;
1381: int paylen, totlen, xferlen, error;
1382:
1383: data = &sc->tx_data[sc->data_idx];
1384: desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1385:
1386: data->ni = ni;
1387:
1388: #if NBPFILTER > 0
1389: if (sc->sc_drvbpf != NULL) {
1390: struct mbuf mb;
1391: struct uath_tx_radiotap_header *tap = &sc->sc_txtap;
1392:
1393: tap->wt_flags = 0;
1394: tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
1395: tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
1396:
1397: mb.m_data = (caddr_t)tap;
1398: mb.m_len = sc->sc_txtap_len;
1399: mb.m_next = m0;
1400: mb.m_nextpkt = NULL;
1401: mb.m_type = 0;
1402: mb.m_flags = 0;
1403: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
1404: }
1405: #endif
1406:
1407: paylen = m0->m_pkthdr.len;
1408: xferlen = sizeof (uint32_t) + sizeof (struct uath_tx_desc) + paylen;
1409:
1410: wh = mtod(m0, struct ieee80211_frame *);
1411: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1412: uint8_t *frm = (uint8_t *)(desc + 1);
1413: uint32_t iv;
1414:
1415: /* h/w WEP: it's up to the host to fill the IV field */
1416: bcopy(wh, frm, sizeof (struct ieee80211_frame));
1417: frm += sizeof (struct ieee80211_frame);
1418:
1419: /* insert IV: code copied from net80211 */
1420: iv = (ic->ic_iv != 0) ? ic->ic_iv : arc4random();
1421: if (iv >= 0x03ff00 && (iv & 0xf8ff00) == 0x00ff00)
1422: iv += 0x000100;
1423: ic->ic_iv = iv + 1;
1424:
1425: *frm++ = iv & 0xff;
1426: *frm++ = (iv >> 8) & 0xff;
1427: *frm++ = (iv >> 16) & 0xff;
1428: *frm++ = ic->ic_wep_txkey << 6;
1429:
1430: m_copydata(m0, sizeof (struct ieee80211_frame),
1431: m0->m_pkthdr.len - sizeof (struct ieee80211_frame), frm);
1432:
1433: paylen += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
1434: xferlen += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
1435: totlen = xferlen + IEEE80211_WEP_CRCLEN;
1436: } else {
1437: m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1));
1438: totlen = xferlen;
1439: }
1440:
1441: /* fill Tx descriptor */
1442: *(uint32_t *)data->buf = UATH_MAKECTL(1, xferlen - sizeof (uint32_t));
1443:
1444: desc->len = htobe32(totlen);
1445: desc->priv = sc->data_idx; /* don't care about endianness */
1446: desc->paylen = htobe32(paylen);
1447: desc->type = htobe32(UATH_TX_DATA);
1448: desc->flags = htobe32(0);
1449: if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1450: desc->dest = htobe32(UATH_ID_BROADCAST);
1451: desc->magic = htobe32(3);
1452: } else {
1453: desc->dest = htobe32(UATH_ID_BSS);
1454: desc->magic = htobe32(1);
1455: }
1456:
1457: m_freem(m0); /* mbuf is no longer needed */
1458:
1459: #ifdef UATH_DEBUG
1460: if (uath_debug >= 6) {
1461: printf("sending frame index=%u len=%d xferlen=%d",
1462: sc->data_idx, paylen, xferlen);
1463: uath_dump_cmd(data->buf, xferlen, '+');
1464: }
1465: #endif
1466: usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
1467: USBD_FORCE_SHORT_XFER | USBD_NO_COPY, UATH_DATA_TIMEOUT,
1468: uath_data_txeof);
1469: error = usbd_transfer(data->xfer);
1470: if (error != USBD_IN_PROGRESS && error != 0) {
1471: ic->ic_if.if_oerrors++;
1472: return error;
1473: }
1474: sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
1475: sc->tx_queued++;
1476:
1477: return 0;
1478: }
1479:
1480: void
1481: uath_start(struct ifnet *ifp)
1482: {
1483: struct uath_softc *sc = ifp->if_softc;
1484: struct ieee80211com *ic = &sc->sc_ic;
1485: struct ieee80211_node *ni;
1486: struct mbuf *m0;
1487:
1488: /*
1489: * net80211 may still try to send management frames even if the
1490: * IFF_RUNNING flag is not set...
1491: */
1492: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1493: return;
1494:
1495: for (;;) {
1496: IF_POLL(&ic->ic_mgtq, m0);
1497: if (m0 != NULL) {
1498: if (sc->tx_queued >= UATH_TX_DATA_LIST_COUNT) {
1499: ifp->if_flags |= IFF_OACTIVE;
1500: break;
1501: }
1502: IF_DEQUEUE(&ic->ic_mgtq, m0);
1503:
1504: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
1505: m0->m_pkthdr.rcvif = NULL;
1506: #if NBPFILTER > 0
1507: if (ic->ic_rawbpf != NULL)
1508: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
1509: #endif
1510: if (uath_tx_data(sc, m0, ni) != 0)
1511: break;
1512: } else {
1513: if (ic->ic_state != IEEE80211_S_RUN)
1514: break;
1515: IFQ_POLL(&ifp->if_snd, m0);
1516: if (m0 == NULL)
1517: break;
1518: if (sc->tx_queued >= UATH_TX_DATA_LIST_COUNT) {
1519: ifp->if_flags |= IFF_OACTIVE;
1520: break;
1521: }
1522: IFQ_DEQUEUE(&ifp->if_snd, m0);
1523: #if NBPFILTER > 0
1524: if (ifp->if_bpf != NULL)
1525: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
1526: #endif
1527: m0 = ieee80211_encap(ifp, m0, &ni);
1528: if (m0 == NULL)
1529: continue;
1530: #if NBPFILTER > 0
1531: if (ic->ic_rawbpf != NULL)
1532: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
1533: #endif
1534: if (uath_tx_data(sc, m0, ni) != 0) {
1535: if (ni != NULL)
1536: ieee80211_release_node(ic, ni);
1537: ifp->if_oerrors++;
1538: break;
1539: }
1540: }
1541:
1542: sc->sc_tx_timer = 5;
1543: ifp->if_timer = 1;
1544: }
1545: }
1546:
1547: void
1548: uath_watchdog(struct ifnet *ifp)
1549: {
1550: struct uath_softc *sc = ifp->if_softc;
1551:
1552: ifp->if_timer = 0;
1553:
1554: if (sc->sc_tx_timer > 0) {
1555: if (--sc->sc_tx_timer == 0) {
1556: printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1557: /*uath_init(ifp); XXX needs a process context! */
1558: ifp->if_oerrors++;
1559: return;
1560: }
1561: ifp->if_timer = 1;
1562: }
1563:
1564: ieee80211_watchdog(ifp);
1565: }
1566:
1567: int
1568: uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1569: {
1570: struct uath_softc *sc = ifp->if_softc;
1571: struct ieee80211com *ic = &sc->sc_ic;
1572: struct ifaddr *ifa;
1573: struct ifreq *ifr;
1574: int s, error = 0;
1575:
1576: s = splnet();
1577:
1578: switch (cmd) {
1579: case SIOCSIFADDR:
1580: ifa = (struct ifaddr *)data;
1581: ifp->if_flags |= IFF_UP;
1582: #ifdef INET
1583: if (ifa->ifa_addr->sa_family == AF_INET)
1584: arp_ifinit(&ic->ic_ac, ifa);
1585: #endif
1586: /* FALLTHROUGH */
1587: case SIOCSIFFLAGS:
1588: if (ifp->if_flags & IFF_UP) {
1589: if (!(ifp->if_flags & IFF_RUNNING))
1590: uath_init(ifp);
1591: } else {
1592: if (ifp->if_flags & IFF_RUNNING)
1593: uath_stop(ifp, 1);
1594: }
1595: break;
1596:
1597: case SIOCADDMULTI:
1598: case SIOCDELMULTI:
1599: ifr = (struct ifreq *)data;
1600: error = (cmd == SIOCADDMULTI) ?
1601: ether_addmulti(ifr, &ic->ic_ac) :
1602: ether_delmulti(ifr, &ic->ic_ac);
1603: if (error == ENETRESET)
1604: error = 0;
1605: break;
1606:
1607: default:
1608: error = ieee80211_ioctl(ifp, cmd, data);
1609: }
1610:
1611: if (error == ENETRESET) {
1612: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1613: (IFF_UP | IFF_RUNNING))
1614: uath_init(ifp);
1615: error = 0;
1616: }
1617:
1618: splx(s);
1619:
1620: return error;
1621: }
1622:
1623: int
1624: uath_query_eeprom(struct uath_softc *sc)
1625: {
1626: uint32_t tmp;
1627: int error;
1628:
1629: /* retrieve MAC address */
1630: error = uath_read_eeprom(sc, UATH_EEPROM_MACADDR, sc->sc_ic.ic_myaddr);
1631: if (error != 0) {
1632: printf("%s: could not read MAC address\n",
1633: sc->sc_dev.dv_xname);
1634: return error;
1635: }
1636:
1637: /* retrieve the maximum frame size that the hardware can receive */
1638: error = uath_read_eeprom(sc, UATH_EEPROM_RXBUFSZ, &tmp);
1639: if (error != 0) {
1640: printf("%s: could not read maximum Rx buffer size\n",
1641: sc->sc_dev.dv_xname);
1642: return error;
1643: }
1644: sc->rxbufsz = betoh32(tmp) & 0xfff;
1645: DPRINTF(("maximum Rx buffer size %d\n", sc->rxbufsz));
1646: return 0;
1647: }
1648:
1649: int
1650: uath_reset(struct uath_softc *sc)
1651: {
1652: struct uath_cmd_setup setup;
1653: uint32_t reg, val;
1654: int s, error;
1655:
1656: /* init device with some voodoo incantations.. */
1657: setup.magic1 = htobe32(1);
1658: setup.magic2 = htobe32(5);
1659: setup.magic3 = htobe32(200);
1660: setup.magic4 = htobe32(27);
1661: s = splusb();
1662: error = uath_cmd_write(sc, UATH_CMD_SETUP, &setup, sizeof setup,
1663: UATH_CMD_FLAG_ASYNC);
1664: /* ..and wait until firmware notifies us that it is ready */
1665: if (error == 0)
1666: error = tsleep(UATH_COND_INIT(sc), PCATCH, "uathinit", 5 * hz);
1667: splx(s);
1668: if (error != 0)
1669: return error;
1670:
1671: /* read PHY registers */
1672: for (reg = 0x09; reg <= 0x24; reg++) {
1673: if (reg == 0x0b || reg == 0x0c)
1674: continue;
1675: DELAY(100);
1676: if ((error = uath_read_reg(sc, reg, &val)) != 0)
1677: return error;
1678: DPRINTFN(2, ("reg 0x%02x=0x%08x\n", reg, val));
1679: }
1680: return error;
1681: }
1682:
1683: int
1684: uath_reset_tx_queues(struct uath_softc *sc)
1685: {
1686: int ac, error;
1687:
1688: for (ac = 0; ac < 4; ac++) {
1689: const uint32_t qid = htobe32(UATH_AC_TO_QID(ac));
1690:
1691: DPRINTF(("resetting Tx queue %d\n", UATH_AC_TO_QID(ac)));
1692: error = uath_cmd_write(sc, UATH_CMD_RESET_QUEUE, &qid,
1693: sizeof qid, 0);
1694: if (error != 0)
1695: break;
1696: }
1697: return error;
1698: }
1699:
1700: int
1701: uath_wme_init(struct uath_softc *sc)
1702: {
1703: struct uath_qinfo qinfo;
1704: int ac, error;
1705: static const struct uath_wme_settings uath_wme_11g[4] = {
1706: { 7, 4, 10, 0, 0 }, /* Background */
1707: { 3, 4, 10, 0, 0 }, /* Best-Effort */
1708: { 3, 3, 4, 26, 0 }, /* Video */
1709: { 2, 2, 3, 47, 0 } /* Voice */
1710: };
1711:
1712: bzero(&qinfo, sizeof qinfo);
1713: qinfo.size = htobe32(32);
1714: qinfo.magic1 = htobe32(1); /* XXX ack policy? */
1715: qinfo.magic2 = htobe32(1);
1716: for (ac = 0; ac < 4; ac++) {
1717: qinfo.qid = htobe32(UATH_AC_TO_QID(ac));
1718: qinfo.ac = htobe32(ac);
1719: qinfo.aifsn = htobe32(uath_wme_11g[ac].aifsn);
1720: qinfo.logcwmin = htobe32(uath_wme_11g[ac].logcwmin);
1721: qinfo.logcwmax = htobe32(uath_wme_11g[ac].logcwmax);
1722: qinfo.txop = htobe32(UATH_TXOP_TO_US(
1723: uath_wme_11g[ac].txop));
1724: qinfo.acm = htobe32(uath_wme_11g[ac].acm);
1725:
1726: DPRINTF(("setting up Tx queue %d\n", UATH_AC_TO_QID(ac)));
1727: error = uath_cmd_write(sc, UATH_CMD_SET_QUEUE, &qinfo,
1728: sizeof qinfo, 0);
1729: if (error != 0)
1730: break;
1731: }
1732: return error;
1733: }
1734:
1735: int
1736: uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
1737: {
1738: struct uath_set_chan chan;
1739:
1740: bzero(&chan, sizeof chan);
1741: chan.flags = htobe32(0x1400);
1742: chan.freq = htobe32(c->ic_freq);
1743: chan.magic1 = htobe32(20);
1744: chan.magic2 = htobe32(50);
1745: chan.magic3 = htobe32(1);
1746:
1747: DPRINTF(("switching to channel %d\n",
1748: ieee80211_chan2ieee(&sc->sc_ic, c)));
1749: return uath_cmd_write(sc, UATH_CMD_SET_CHAN, &chan, sizeof chan, 0);
1750: }
1751:
1752: int
1753: uath_set_key(struct uath_softc *sc, const struct ieee80211_key *k, int index)
1754: {
1755: struct uath_cmd_crypto crypto;
1756: int i;
1757:
1758: bzero(&crypto, sizeof crypto);
1759: crypto.keyidx = htobe32(index);
1760: crypto.magic1 = htobe32(1);
1761: crypto.size = htobe32(368);
1762: crypto.mask = htobe32(0xffff);
1763: crypto.flags = htobe32(0x80000068);
1764: if (index != UATH_DEFAULT_KEY)
1765: crypto.flags |= htobe32(index << 16);
1766: memset(crypto.magic2, 0xff, sizeof crypto.magic2);
1767:
1768: /*
1769: * Each byte of the key must be XOR'ed with 10101010 before being
1770: * transmitted to the firmware.
1771: */
1772: for (i = 0; i < k->k_len; i++)
1773: crypto.key[i] = k->k_key[i] ^ 0xaa;
1774:
1775: DPRINTF(("setting crypto key index=%d len=%d\n", index, k->k_len));
1776: return uath_cmd_write(sc, UATH_CMD_CRYPTO, &crypto, sizeof crypto, 0);
1777: }
1778:
1779: int
1780: uath_set_keys(struct uath_softc *sc)
1781: {
1782: const struct ieee80211com *ic = &sc->sc_ic;
1783: int i, error;
1784:
1785: for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1786: const struct ieee80211_key *k = &ic->ic_nw_keys[i];
1787:
1788: if (k->k_len > 0 && (error = uath_set_key(sc, k, i)) != 0)
1789: return error;
1790: }
1791: return uath_set_key(sc, &ic->ic_nw_keys[ic->ic_wep_txkey],
1792: UATH_DEFAULT_KEY);
1793: }
1794:
1795: int
1796: uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
1797: {
1798: struct uath_cmd_rates rates;
1799:
1800: bzero(&rates, sizeof rates);
1801: rates.magic1 = htobe32(0x02);
1802: rates.size = htobe32(1 + sizeof rates.rates);
1803: rates.nrates = rs->rs_nrates;
1804: bcopy(rs->rs_rates, rates.rates, rs->rs_nrates);
1805:
1806: DPRINTF(("setting supported rates nrates=%d\n", rs->rs_nrates));
1807: return uath_cmd_write(sc, UATH_CMD_SET_RATES, &rates, sizeof rates, 0);
1808: }
1809:
1810: int
1811: uath_set_rxfilter(struct uath_softc *sc, uint32_t filter, uint32_t flags)
1812: {
1813: struct uath_cmd_filter rxfilter;
1814:
1815: rxfilter.filter = htobe32(filter);
1816: rxfilter.flags = htobe32(flags);
1817:
1818: DPRINTF(("setting Rx filter=0x%x flags=0x%x\n", filter, flags));
1819: return uath_cmd_write(sc, UATH_CMD_SET_FILTER, &rxfilter,
1820: sizeof rxfilter, 0);
1821: }
1822:
1823: int
1824: uath_set_led(struct uath_softc *sc, int which, int on)
1825: {
1826: struct uath_cmd_led led;
1827:
1828: led.which = htobe32(which);
1829: led.state = htobe32(on ? UATH_LED_ON : UATH_LED_OFF);
1830:
1831: DPRINTFN(2, ("switching %s led %s\n",
1832: (which == UATH_LED_LINK) ? "link" : "activity",
1833: on ? "on" : "off"));
1834: return uath_cmd_write(sc, UATH_CMD_SET_LED, &led, sizeof led, 0);
1835: }
1836:
1837: int
1838: uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
1839: {
1840: uint32_t val;
1841: int error;
1842:
1843: /* set radio frequency */
1844: if ((error = uath_set_chan(sc, c)) != 0) {
1845: printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1846: return error;
1847: }
1848:
1849: /* reset Tx rings */
1850: if ((error = uath_reset_tx_queues(sc)) != 0) {
1851: printf("%s: could not reset Tx queues\n",
1852: sc->sc_dev.dv_xname);
1853: return error;
1854: }
1855:
1856: /* set Tx rings WME properties */
1857: if ((error = uath_wme_init(sc)) != 0) {
1858: printf("%s: could not init Tx queues\n",
1859: sc->sc_dev.dv_xname);
1860: return error;
1861: }
1862:
1863: val = htobe32(0);
1864: error = uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val, 0);
1865: if (error != 0) {
1866: printf("%s: could not set state\n", sc->sc_dev.dv_xname);
1867: return error;
1868: }
1869:
1870: return uath_tx_null(sc);
1871: }
1872:
1873: int
1874: uath_init(struct ifnet *ifp)
1875: {
1876: struct uath_softc *sc = ifp->if_softc;
1877: struct ieee80211com *ic = &sc->sc_ic;
1878: struct uath_cmd_31 cmd31;
1879: uint32_t val;
1880: int i, error;
1881:
1882: /* reset data and command rings */
1883: sc->tx_queued = sc->data_idx = sc->cmd_idx = 0;
1884:
1885: val = htobe32(0);
1886: (void)uath_cmd_write(sc, UATH_CMD_02, &val, sizeof val, 0);
1887:
1888: /* set MAC address */
1889: IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
1890: (void)uath_write_multi(sc, 0x13, ic->ic_myaddr, IEEE80211_ADDR_LEN);
1891:
1892: (void)uath_write_reg(sc, 0x02, 0x00000001);
1893: (void)uath_write_reg(sc, 0x0e, 0x0000003f);
1894: (void)uath_write_reg(sc, 0x10, 0x00000001);
1895: (void)uath_write_reg(sc, 0x06, 0x0000001e);
1896:
1897: /*
1898: * Queue Rx data xfers.
1899: */
1900: for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
1901: struct uath_rx_data *data = SLIST_FIRST(&sc->rx_freelist);
1902:
1903: usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
1904: sc->rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
1905: USBD_NO_TIMEOUT, uath_data_rxeof);
1906: error = usbd_transfer(data->xfer);
1907: if (error != USBD_IN_PROGRESS && error != 0) {
1908: printf("%s: could not queue Rx transfer\n",
1909: sc->sc_dev.dv_xname);
1910: goto fail;
1911: }
1912: SLIST_REMOVE_HEAD(&sc->rx_freelist, next);
1913: }
1914:
1915: error = uath_cmd_read(sc, UATH_CMD_07, 0, NULL, &val,
1916: UATH_CMD_FLAG_MAGIC);
1917: if (error != 0) {
1918: printf("%s: could not send read command 07h\n",
1919: sc->sc_dev.dv_xname);
1920: goto fail;
1921: }
1922: DPRINTF(("command 07h return code: %x\n", betoh32(val)));
1923:
1924: /* set default channel */
1925: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1926: if ((error = uath_set_chan(sc, ic->ic_bss->ni_chan)) != 0) {
1927: printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1928: goto fail;
1929: }
1930:
1931: if ((error = uath_wme_init(sc)) != 0) {
1932: printf("%s: could not setup WME parameters\n",
1933: sc->sc_dev.dv_xname);
1934: goto fail;
1935: }
1936:
1937: /* init MAC registers */
1938: (void)uath_write_reg(sc, 0x19, 0x00000000);
1939: (void)uath_write_reg(sc, 0x1a, 0x0000003c);
1940: (void)uath_write_reg(sc, 0x1b, 0x0000003c);
1941: (void)uath_write_reg(sc, 0x1c, 0x00000000);
1942: (void)uath_write_reg(sc, 0x1e, 0x00000000);
1943: (void)uath_write_reg(sc, 0x1f, 0x00000003);
1944: (void)uath_write_reg(sc, 0x0c, 0x00000000);
1945: (void)uath_write_reg(sc, 0x0f, 0x00000002);
1946: (void)uath_write_reg(sc, 0x0a, 0x00000007); /* XXX retry? */
1947: (void)uath_write_reg(sc, 0x09, ic->ic_rtsthreshold);
1948:
1949: val = htobe32(4);
1950: (void)uath_cmd_write(sc, UATH_CMD_27, &val, sizeof val, 0);
1951: (void)uath_cmd_write(sc, UATH_CMD_27, &val, sizeof val, 0);
1952: (void)uath_cmd_write(sc, UATH_CMD_1B, NULL, 0, 0);
1953:
1954: if ((error = uath_set_keys(sc)) != 0) {
1955: printf("%s: could not set crypto keys\n",
1956: sc->sc_dev.dv_xname);
1957: goto fail;
1958: }
1959:
1960: /* enable Rx */
1961: (void)uath_set_rxfilter(sc, 0x0000, 4);
1962: (void)uath_set_rxfilter(sc, 0x0817, 1);
1963:
1964: cmd31.magic1 = htobe32(0xffffffff);
1965: cmd31.magic2 = htobe32(0xffffffff);
1966: (void)uath_cmd_write(sc, UATH_CMD_31, &cmd31, sizeof cmd31, 0);
1967:
1968: ifp->if_flags &= ~IFF_OACTIVE;
1969: ifp->if_flags |= IFF_RUNNING;
1970:
1971: if (ic->ic_opmode == IEEE80211_M_MONITOR)
1972: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1973: else
1974: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1975:
1976: return 0;
1977:
1978: fail: uath_stop(ifp, 1);
1979: return error;
1980: }
1981:
1982: void
1983: uath_stop(struct ifnet *ifp, int disable)
1984: {
1985: struct uath_softc *sc = ifp->if_softc;
1986: struct ieee80211com *ic = &sc->sc_ic;
1987: uint32_t val;
1988: int s;
1989:
1990: s = splusb();
1991:
1992: sc->sc_tx_timer = 0;
1993: ifp->if_timer = 0;
1994: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1995:
1996: ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */
1997:
1998: val = htobe32(0);
1999: (void)uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val, 0);
2000: (void)uath_cmd_write(sc, UATH_CMD_RESET, NULL, 0, 0);
2001:
2002: val = htobe32(0);
2003: (void)uath_cmd_write(sc, UATH_CMD_15, &val, sizeof val, 0);
2004:
2005: #if 0
2006: (void)uath_cmd_read(sc, UATH_CMD_SHUTDOWN, NULL, 0, NULL,
2007: UATH_CMD_FLAG_MAGIC);
2008: #endif
2009:
2010: /* abort any pending transfers */
2011: usbd_abort_pipe(sc->data_tx_pipe);
2012: usbd_abort_pipe(sc->data_rx_pipe);
2013: usbd_abort_pipe(sc->cmd_tx_pipe);
2014:
2015: splx(s);
2016: }
2017:
2018: /*
2019: * Load the MIPS R4000 microcode into the device. Once the image is loaded,
2020: * the device will detach itself from the bus and reattach later with a new
2021: * product Id (a la ezusb). XXX this could also be implemented in userland
2022: * through /dev/ugen.
2023: */
2024: int
2025: uath_loadfirmware(struct uath_softc *sc, const u_char *fw, int len)
2026: {
2027: usbd_xfer_handle ctlxfer, txxfer, rxxfer;
2028: struct uath_fwblock *txblock, *rxblock;
2029: uint8_t *txdata;
2030: int error = 0;
2031:
2032: if ((ctlxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
2033: printf("%s: could not allocate Tx control xfer\n",
2034: sc->sc_dev.dv_xname);
2035: error = USBD_NOMEM;
2036: goto fail1;
2037: }
2038: txblock = usbd_alloc_buffer(ctlxfer, sizeof (struct uath_fwblock));
2039: if (txblock == NULL) {
2040: printf("%s: could not allocate Tx control block\n",
2041: sc->sc_dev.dv_xname);
2042: error = USBD_NOMEM;
2043: goto fail2;
2044: }
2045:
2046: if ((txxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
2047: printf("%s: could not allocate Tx xfer\n",
2048: sc->sc_dev.dv_xname);
2049: error = USBD_NOMEM;
2050: goto fail2;
2051: }
2052: txdata = usbd_alloc_buffer(txxfer, UATH_MAX_FWBLOCK_SIZE);
2053: if (txdata == NULL) {
2054: printf("%s: could not allocate Tx buffer\n",
2055: sc->sc_dev.dv_xname);
2056: error = USBD_NOMEM;
2057: goto fail3;
2058: }
2059:
2060: if ((rxxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
2061: printf("%s: could not allocate Rx control xfer\n",
2062: sc->sc_dev.dv_xname);
2063: error = USBD_NOMEM;
2064: goto fail3;
2065: }
2066: rxblock = usbd_alloc_buffer(rxxfer, sizeof (struct uath_fwblock));
2067: if (rxblock == NULL) {
2068: printf("%s: could not allocate Rx control block\n",
2069: sc->sc_dev.dv_xname);
2070: error = USBD_NOMEM;
2071: goto fail4;
2072: }
2073:
2074: bzero(txblock, sizeof (struct uath_fwblock));
2075: txblock->flags = htobe32(UATH_WRITE_BLOCK);
2076: txblock->total = htobe32(len);
2077:
2078: while (len > 0) {
2079: int mlen = min(len, UATH_MAX_FWBLOCK_SIZE);
2080:
2081: txblock->remain = htobe32(len - mlen);
2082: txblock->len = htobe32(mlen);
2083:
2084: DPRINTF(("sending firmware block: %d bytes remaining\n",
2085: len - mlen));
2086:
2087: /* send firmware block meta-data */
2088: usbd_setup_xfer(ctlxfer, sc->cmd_tx_pipe, sc, txblock,
2089: sizeof (struct uath_fwblock), USBD_NO_COPY,
2090: UATH_CMD_TIMEOUT, NULL);
2091: if ((error = usbd_sync_transfer(ctlxfer)) != 0) {
2092: printf("%s: could not send firmware block info\n",
2093: sc->sc_dev.dv_xname);
2094: break;
2095: }
2096:
2097: /* send firmware block data */
2098: bcopy(fw, txdata, mlen);
2099: usbd_setup_xfer(txxfer, sc->data_tx_pipe, sc, txdata, mlen,
2100: USBD_NO_COPY, UATH_DATA_TIMEOUT, NULL);
2101: if ((error = usbd_sync_transfer(txxfer)) != 0) {
2102: printf("%s: could not send firmware block data\n",
2103: sc->sc_dev.dv_xname);
2104: break;
2105: }
2106:
2107: /* wait for ack from firmware */
2108: usbd_setup_xfer(rxxfer, sc->cmd_rx_pipe, sc, rxblock,
2109: sizeof (struct uath_fwblock), USBD_SHORT_XFER_OK |
2110: USBD_NO_COPY, UATH_CMD_TIMEOUT, NULL);
2111: if ((error = usbd_sync_transfer(rxxfer)) != 0) {
2112: printf("%s: could not read firmware answer\n",
2113: sc->sc_dev.dv_xname);
2114: break;
2115: }
2116:
2117: DPRINTFN(2, ("rxblock flags=0x%x total=%d\n",
2118: betoh32(rxblock->flags), betoh32(rxblock->rxtotal)));
2119: fw += mlen;
2120: len -= mlen;
2121: }
2122:
2123: fail4: usbd_free_xfer(rxxfer);
2124: fail3: usbd_free_xfer(txxfer);
2125: fail2: usbd_free_xfer(ctlxfer);
2126: fail1: return error;
2127: }
2128:
2129: int
2130: uath_activate(struct device *self, enum devact act)
2131: {
2132: switch (act) {
2133: case DVACT_ACTIVATE:
2134: break;
2135:
2136: case DVACT_DEACTIVATE:
2137: break;
2138: }
2139: return 0;
2140: }
CVSweb