Deleted Added
full compact
if_uath.c (192502) if_uath.c (192511)
1/*-
2 * Copyright (c) 2006 Sam Leffler, Errno Consulting
3 * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer,
11 * without modification.
12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14 * redistribution must be conditioned upon including a substantially
15 * similar Disclaimer requirement for further binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31/*
32 * This driver is distantly derived from a driver of the same name
33 * by Damien Bergamini. The original copyright is included below:
34 *
35 * Copyright (c) 2006
36 * Damien Bergamini <damien.bergamini@free.fr>
37 *
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the above
40 * copyright notice and this permission notice appear in all copies.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49 */
50
51#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2006 Sam Leffler, Errno Consulting
3 * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer,
11 * without modification.
12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14 * redistribution must be conditioned upon including a substantially
15 * similar Disclaimer requirement for further binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31/*
32 * This driver is distantly derived from a driver of the same name
33 * by Damien Bergamini. The original copyright is included below:
34 *
35 * Copyright (c) 2006
36 * Damien Bergamini <damien.bergamini@free.fr>
37 *
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the above
40 * copyright notice and this permission notice appear in all copies.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49 */
50
51#include <sys/cdefs.h>
52__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_uath.c 192502 2009-05-21 01:48:42Z thompsa $");
52__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_uath.c 192511 2009-05-21 02:26:51Z thompsa $");
53
54/*-
55 * Driver for Atheros AR5523 USB parts.
56 *
57 * The driver requires firmware to be loaded into the device. This
58 * is done on device discovery from a user application (uathload)
59 * that is launched by devd when a device with suitable product ID
60 * is recognized. Once firmware has been loaded the device will
61 * reset the USB port and re-attach with the original product ID+1
62 * and this driver will be attached. The firmware is licensed for
63 * general use (royalty free) and may be incorporated in products.
64 * Note that the firmware normally packaged with the NDIS drivers
65 * for these devices does not work in this way and so does not work
66 * with this driver.
67 */
68#include <sys/param.h>
69#include <sys/sockio.h>
70#include <sys/sysctl.h>
71#include <sys/lock.h>
72#include <sys/mutex.h>
73#include <sys/mbuf.h>
74#include <sys/kernel.h>
75#include <sys/socket.h>
76#include <sys/systm.h>
77#include <sys/malloc.h>
78#include <sys/module.h>
79#include <sys/bus.h>
80#include <sys/endian.h>
81#include <sys/kdb.h>
82
83#include <machine/bus.h>
84#include <machine/resource.h>
85#include <sys/rman.h>
86
87#include <net/bpf.h>
88#include <net/if.h>
89#include <net/if_arp.h>
90#include <net/ethernet.h>
91#include <net/if_dl.h>
92#include <net/if_media.h>
93#include <net/if_types.h>
94
95#ifdef INET
96#include <netinet/in.h>
97#include <netinet/in_systm.h>
98#include <netinet/in_var.h>
99#include <netinet/if_ether.h>
100#include <netinet/ip.h>
101#endif
102
103#include <net80211/ieee80211_var.h>
104#include <net80211/ieee80211_regdomain.h>
105#include <net80211/ieee80211_radiotap.h>
106
107#include <dev/usb/usb.h>
108#include <dev/usb/usb_core.h>
109#include <dev/usb/usb_busdma.h>
110#include <dev/usb/usb_debug.h>
111#include <dev/usb/usb_error.h>
112#include <dev/usb/usb_lookup.h>
113#include <dev/usb/usb_util.h>
114#include "usbdevs.h"
115
116#include <dev/usb/wlan/if_uathreg.h>
117#include <dev/usb/wlan/if_uathvar.h>
118
119SYSCTL_NODE(_hw_usb, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros");
120
121static int uath_countrycode = CTRY_DEFAULT; /* country code */
122SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RW, &uath_countrycode,
123 0, "country code");
124TUNABLE_INT("hw.usb.uath.countrycode", &uath_countrycode);
125static int uath_regdomain = 0; /* regulatory domain */
126SYSCTL_INT(_hw_usb_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain,
127 0, "regulatory domain");
128
129#ifdef UATH_DEBUG
130int uath_debug = 0;
131SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RW, &uath_debug, 0,
132 "uath debug level");
133TUNABLE_INT("hw.usb.uath.debug", &uath_debug);
134enum {
135 UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
136 UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */
137 UATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
138 UATH_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */
139 UATH_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */
140 UATH_DEBUG_RECV_ALL = 0x00000020, /* trace all frames (beacons) */
141 UATH_DEBUG_INIT = 0x00000040, /* initialization of dev */
142 UATH_DEBUG_DEVCAP = 0x00000080, /* dev caps */
143 UATH_DEBUG_CMDS = 0x00000100, /* commands */
144 UATH_DEBUG_CMDS_DUMP = 0x00000200, /* command buffer dump */
145 UATH_DEBUG_RESET = 0x00000400, /* reset processing */
146 UATH_DEBUG_STATE = 0x00000800, /* 802.11 state transitions */
147 UATH_DEBUG_MULTICAST = 0x00001000, /* multicast */
148 UATH_DEBUG_WME = 0x00002000, /* WME */
149 UATH_DEBUG_CHANNEL = 0x00004000, /* channel */
150 UATH_DEBUG_RATES = 0x00008000, /* rates */
151 UATH_DEBUG_CRYPTO = 0x00010000, /* crypto */
152 UATH_DEBUG_LED = 0x00020000, /* LED */
153 UATH_DEBUG_ANY = 0xffffffff
154};
155#define DPRINTF(sc, m, fmt, ...) do { \
156 if (sc->sc_debug & (m)) \
157 printf(fmt, __VA_ARGS__); \
158} while (0)
159#else
160#define DPRINTF(sc, m, fmt, ...) do { \
161 (void) sc; \
162} while (0)
163#endif
164
165/* unaligned little endian access */
166#define LE_READ_2(p) \
167 ((u_int16_t) \
168 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8)))
169#define LE_READ_4(p) \
170 ((u_int32_t) \
171 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
172 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
173
174/* recognized device vendors/products */
175static const struct usb2_device_id uath_devs[] = {
176#define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
177 UATH_DEV(ATHEROS, AR5523),
178 UATH_DEV(ATHEROS2, AR5523_1),
179 UATH_DEV(ATHEROS2, AR5523_2),
180 UATH_DEV(ATHEROS2, AR5523_3),
181 UATH_DEV(CONCEPTRONIC, AR5523_1),
182 UATH_DEV(CONCEPTRONIC, AR5523_2),
183 UATH_DEV(DLINK, DWLAG122),
184 UATH_DEV(DLINK, DWLAG132),
185 UATH_DEV(DLINK, DWLG132),
186 UATH_DEV(GIGASET, AR5523),
187 UATH_DEV(GIGASET, SMCWUSBTG),
188 UATH_DEV(GLOBALSUN, AR5523_1),
189 UATH_DEV(GLOBALSUN, AR5523_2),
190 UATH_DEV(NETGEAR, WG111U),
191 UATH_DEV(NETGEAR3, WG111T),
192 UATH_DEV(NETGEAR3, WPN111),
193 UATH_DEV(UMEDIA, TEW444UBEU),
194 UATH_DEV(UMEDIA, AR5523_2),
195 UATH_DEV(UMEDIA, AR5523_3),
196 UATH_DEV(WISTRONNEWEB, AR5523_1),
197 UATH_DEV(WISTRONNEWEB, AR5523_2),
198 UATH_DEV(ZCOM, AR5523)
199#undef UATH_DEV
200};
201
202static usb2_callback_t uath_intr_rx_callback;
203static usb2_callback_t uath_intr_tx_callback;
204static usb2_callback_t uath_bulk_rx_callback;
205static usb2_callback_t uath_bulk_tx_callback;
206
207static const struct usb2_config uath_usbconfig[UATH_N_XFERS] = {
208 [UATH_INTR_RX] = {
209 .type = UE_BULK,
210 .endpoint = 0x1,
211 .direction = UE_DIR_IN,
212 .bufsize = UATH_MAX_CMDSZ,
213 .flags = {
214 .pipe_bof = 1,
215 .short_xfer_ok = 1
216 },
217 .callback = uath_intr_rx_callback
218 },
219 [UATH_INTR_TX] = {
220 .type = UE_BULK,
221 .endpoint = 0x1,
222 .direction = UE_DIR_OUT,
223 .bufsize = UATH_MAX_CMDSZ,
224 .flags = {
225 .ext_buffer = 1,
226 .force_short_xfer = 1,
227 .pipe_bof = 1,
228 },
229 .callback = uath_intr_tx_callback,
230 .timeout = UATH_CMD_TIMEOUT
231 },
232 [UATH_BULK_RX] = {
233 .type = UE_BULK,
234 .endpoint = 0x2,
235 .direction = UE_DIR_IN,
236 .bufsize = MCLBYTES,
237 .flags = {
238 .ext_buffer = 1,
239 .pipe_bof = 1,
240 .short_xfer_ok = 1
241 },
242 .callback = uath_bulk_rx_callback
243 },
244 [UATH_BULK_TX] = {
245 .type = UE_BULK,
246 .endpoint = 0x2,
247 .direction = UE_DIR_OUT,
248 .bufsize = UATH_MAX_TXBUFSZ,
249 .flags = {
250 .ext_buffer = 1,
251 .force_short_xfer = 1,
252 .pipe_bof = 1
253 },
254 .callback = uath_bulk_tx_callback,
255 .timeout = UATH_DATA_TIMEOUT
256 }
257};
258
259static struct ieee80211vap *uath_vap_create(struct ieee80211com *,
260 const char name[IFNAMSIZ], int unit, int opmode,
261 int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
262 const uint8_t mac[IEEE80211_ADDR_LEN]);
263static void uath_vap_delete(struct ieee80211vap *);
264static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
265 int, int);
266static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
267 int);
268static int uath_host_available(struct uath_softc *);
269static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
270static int uath_get_devcap(struct uath_softc *);
271static struct uath_cmd *
272 uath_get_cmdbuf(struct uath_softc *);
273static int uath_cmd_read(struct uath_softc *, uint32_t, const void *,
274 int, void *, int, int);
275static int uath_cmd_write(struct uath_softc *, uint32_t, const void *,
276 int, int);
277static void uath_stat(void *);
278#ifdef UATH_DEBUG
279static void uath_dump_cmd(const uint8_t *, int, char);
280static const char *
281 uath_codename(int);
282#endif
283static int uath_get_devstatus(struct uath_softc *,
284 uint8_t macaddr[IEEE80211_ADDR_LEN]);
285static int uath_get_status(struct uath_softc *, uint32_t, void *, int);
286static int uath_alloc_rx_data_list(struct uath_softc *);
287static int uath_alloc_tx_data_list(struct uath_softc *);
288static void uath_free_rx_data_list(struct uath_softc *);
289static void uath_free_tx_data_list(struct uath_softc *);
290static int uath_init_locked(void *);
291static void uath_init(void *);
292static void uath_stop_locked(struct ifnet *);
293static void uath_stop(struct ifnet *);
294static int uath_ioctl(struct ifnet *, u_long, caddr_t);
295static void uath_start(struct ifnet *);
296static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
297 const struct ieee80211_bpf_params *);
298static void uath_scan_start(struct ieee80211com *);
299static void uath_scan_end(struct ieee80211com *);
300static void uath_set_channel(struct ieee80211com *);
301static void uath_update_mcast(struct ifnet *);
302static void uath_update_promisc(struct ifnet *);
303static int uath_config(struct uath_softc *, uint32_t, uint32_t);
304static int uath_config_multi(struct uath_softc *, uint32_t, const void *,
305 int);
306static int uath_switch_channel(struct uath_softc *,
307 struct ieee80211_channel *);
308static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
309static void uath_watchdog(void *);
310static void uath_abort_xfers(struct uath_softc *);
311static int uath_dataflush(struct uath_softc *);
312static int uath_cmdflush(struct uath_softc *);
313static int uath_flush(struct uath_softc *);
314static int uath_set_ledstate(struct uath_softc *, int);
315static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
316static int uath_reset_tx_queues(struct uath_softc *);
317static int uath_wme_init(struct uath_softc *);
318static struct uath_data *
319 uath_getbuf(struct uath_softc *);
320static int uath_newstate(struct ieee80211vap *, enum ieee80211_state,
321 int);
322static int uath_set_key(struct uath_softc *,
323 const struct ieee80211_key *, int);
324static int uath_set_keys(struct uath_softc *, struct ieee80211vap *);
325static void uath_sysctl_node(struct uath_softc *);
326
327static int
328uath_match(device_t dev)
329{
330 struct usb2_attach_arg *uaa = device_get_ivars(dev);
331
332 if (uaa->usb_mode != USB_MODE_HOST)
333 return (ENXIO);
334 if (uaa->info.bConfigIndex != UATH_CONFIG_INDEX)
335 return (ENXIO);
336 if (uaa->info.bIfaceIndex != UATH_IFACE_INDEX)
337 return (ENXIO);
338
339 return (usb2_lookup_id_by_uaa(uath_devs, sizeof(uath_devs), uaa));
340}
341
342static int
343uath_attach(device_t dev)
344{
345 struct uath_softc *sc = device_get_softc(dev);
346 struct usb2_attach_arg *uaa = device_get_ivars(dev);
347 struct ieee80211com *ic;
348 struct ifnet *ifp;
349 uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
350 usb2_error_t error;
351 uint8_t macaddr[IEEE80211_ADDR_LEN];
352
353 sc->sc_dev = dev;
354 sc->sc_udev = uaa->device;
355#ifdef UATH_DEBUG
356 sc->sc_debug = uath_debug;
357#endif
53
54/*-
55 * Driver for Atheros AR5523 USB parts.
56 *
57 * The driver requires firmware to be loaded into the device. This
58 * is done on device discovery from a user application (uathload)
59 * that is launched by devd when a device with suitable product ID
60 * is recognized. Once firmware has been loaded the device will
61 * reset the USB port and re-attach with the original product ID+1
62 * and this driver will be attached. The firmware is licensed for
63 * general use (royalty free) and may be incorporated in products.
64 * Note that the firmware normally packaged with the NDIS drivers
65 * for these devices does not work in this way and so does not work
66 * with this driver.
67 */
68#include <sys/param.h>
69#include <sys/sockio.h>
70#include <sys/sysctl.h>
71#include <sys/lock.h>
72#include <sys/mutex.h>
73#include <sys/mbuf.h>
74#include <sys/kernel.h>
75#include <sys/socket.h>
76#include <sys/systm.h>
77#include <sys/malloc.h>
78#include <sys/module.h>
79#include <sys/bus.h>
80#include <sys/endian.h>
81#include <sys/kdb.h>
82
83#include <machine/bus.h>
84#include <machine/resource.h>
85#include <sys/rman.h>
86
87#include <net/bpf.h>
88#include <net/if.h>
89#include <net/if_arp.h>
90#include <net/ethernet.h>
91#include <net/if_dl.h>
92#include <net/if_media.h>
93#include <net/if_types.h>
94
95#ifdef INET
96#include <netinet/in.h>
97#include <netinet/in_systm.h>
98#include <netinet/in_var.h>
99#include <netinet/if_ether.h>
100#include <netinet/ip.h>
101#endif
102
103#include <net80211/ieee80211_var.h>
104#include <net80211/ieee80211_regdomain.h>
105#include <net80211/ieee80211_radiotap.h>
106
107#include <dev/usb/usb.h>
108#include <dev/usb/usb_core.h>
109#include <dev/usb/usb_busdma.h>
110#include <dev/usb/usb_debug.h>
111#include <dev/usb/usb_error.h>
112#include <dev/usb/usb_lookup.h>
113#include <dev/usb/usb_util.h>
114#include "usbdevs.h"
115
116#include <dev/usb/wlan/if_uathreg.h>
117#include <dev/usb/wlan/if_uathvar.h>
118
119SYSCTL_NODE(_hw_usb, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros");
120
121static int uath_countrycode = CTRY_DEFAULT; /* country code */
122SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RW, &uath_countrycode,
123 0, "country code");
124TUNABLE_INT("hw.usb.uath.countrycode", &uath_countrycode);
125static int uath_regdomain = 0; /* regulatory domain */
126SYSCTL_INT(_hw_usb_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain,
127 0, "regulatory domain");
128
129#ifdef UATH_DEBUG
130int uath_debug = 0;
131SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RW, &uath_debug, 0,
132 "uath debug level");
133TUNABLE_INT("hw.usb.uath.debug", &uath_debug);
134enum {
135 UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
136 UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */
137 UATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
138 UATH_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */
139 UATH_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */
140 UATH_DEBUG_RECV_ALL = 0x00000020, /* trace all frames (beacons) */
141 UATH_DEBUG_INIT = 0x00000040, /* initialization of dev */
142 UATH_DEBUG_DEVCAP = 0x00000080, /* dev caps */
143 UATH_DEBUG_CMDS = 0x00000100, /* commands */
144 UATH_DEBUG_CMDS_DUMP = 0x00000200, /* command buffer dump */
145 UATH_DEBUG_RESET = 0x00000400, /* reset processing */
146 UATH_DEBUG_STATE = 0x00000800, /* 802.11 state transitions */
147 UATH_DEBUG_MULTICAST = 0x00001000, /* multicast */
148 UATH_DEBUG_WME = 0x00002000, /* WME */
149 UATH_DEBUG_CHANNEL = 0x00004000, /* channel */
150 UATH_DEBUG_RATES = 0x00008000, /* rates */
151 UATH_DEBUG_CRYPTO = 0x00010000, /* crypto */
152 UATH_DEBUG_LED = 0x00020000, /* LED */
153 UATH_DEBUG_ANY = 0xffffffff
154};
155#define DPRINTF(sc, m, fmt, ...) do { \
156 if (sc->sc_debug & (m)) \
157 printf(fmt, __VA_ARGS__); \
158} while (0)
159#else
160#define DPRINTF(sc, m, fmt, ...) do { \
161 (void) sc; \
162} while (0)
163#endif
164
165/* unaligned little endian access */
166#define LE_READ_2(p) \
167 ((u_int16_t) \
168 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8)))
169#define LE_READ_4(p) \
170 ((u_int32_t) \
171 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
172 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
173
174/* recognized device vendors/products */
175static const struct usb2_device_id uath_devs[] = {
176#define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
177 UATH_DEV(ATHEROS, AR5523),
178 UATH_DEV(ATHEROS2, AR5523_1),
179 UATH_DEV(ATHEROS2, AR5523_2),
180 UATH_DEV(ATHEROS2, AR5523_3),
181 UATH_DEV(CONCEPTRONIC, AR5523_1),
182 UATH_DEV(CONCEPTRONIC, AR5523_2),
183 UATH_DEV(DLINK, DWLAG122),
184 UATH_DEV(DLINK, DWLAG132),
185 UATH_DEV(DLINK, DWLG132),
186 UATH_DEV(GIGASET, AR5523),
187 UATH_DEV(GIGASET, SMCWUSBTG),
188 UATH_DEV(GLOBALSUN, AR5523_1),
189 UATH_DEV(GLOBALSUN, AR5523_2),
190 UATH_DEV(NETGEAR, WG111U),
191 UATH_DEV(NETGEAR3, WG111T),
192 UATH_DEV(NETGEAR3, WPN111),
193 UATH_DEV(UMEDIA, TEW444UBEU),
194 UATH_DEV(UMEDIA, AR5523_2),
195 UATH_DEV(UMEDIA, AR5523_3),
196 UATH_DEV(WISTRONNEWEB, AR5523_1),
197 UATH_DEV(WISTRONNEWEB, AR5523_2),
198 UATH_DEV(ZCOM, AR5523)
199#undef UATH_DEV
200};
201
202static usb2_callback_t uath_intr_rx_callback;
203static usb2_callback_t uath_intr_tx_callback;
204static usb2_callback_t uath_bulk_rx_callback;
205static usb2_callback_t uath_bulk_tx_callback;
206
207static const struct usb2_config uath_usbconfig[UATH_N_XFERS] = {
208 [UATH_INTR_RX] = {
209 .type = UE_BULK,
210 .endpoint = 0x1,
211 .direction = UE_DIR_IN,
212 .bufsize = UATH_MAX_CMDSZ,
213 .flags = {
214 .pipe_bof = 1,
215 .short_xfer_ok = 1
216 },
217 .callback = uath_intr_rx_callback
218 },
219 [UATH_INTR_TX] = {
220 .type = UE_BULK,
221 .endpoint = 0x1,
222 .direction = UE_DIR_OUT,
223 .bufsize = UATH_MAX_CMDSZ,
224 .flags = {
225 .ext_buffer = 1,
226 .force_short_xfer = 1,
227 .pipe_bof = 1,
228 },
229 .callback = uath_intr_tx_callback,
230 .timeout = UATH_CMD_TIMEOUT
231 },
232 [UATH_BULK_RX] = {
233 .type = UE_BULK,
234 .endpoint = 0x2,
235 .direction = UE_DIR_IN,
236 .bufsize = MCLBYTES,
237 .flags = {
238 .ext_buffer = 1,
239 .pipe_bof = 1,
240 .short_xfer_ok = 1
241 },
242 .callback = uath_bulk_rx_callback
243 },
244 [UATH_BULK_TX] = {
245 .type = UE_BULK,
246 .endpoint = 0x2,
247 .direction = UE_DIR_OUT,
248 .bufsize = UATH_MAX_TXBUFSZ,
249 .flags = {
250 .ext_buffer = 1,
251 .force_short_xfer = 1,
252 .pipe_bof = 1
253 },
254 .callback = uath_bulk_tx_callback,
255 .timeout = UATH_DATA_TIMEOUT
256 }
257};
258
259static struct ieee80211vap *uath_vap_create(struct ieee80211com *,
260 const char name[IFNAMSIZ], int unit, int opmode,
261 int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
262 const uint8_t mac[IEEE80211_ADDR_LEN]);
263static void uath_vap_delete(struct ieee80211vap *);
264static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
265 int, int);
266static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
267 int);
268static int uath_host_available(struct uath_softc *);
269static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
270static int uath_get_devcap(struct uath_softc *);
271static struct uath_cmd *
272 uath_get_cmdbuf(struct uath_softc *);
273static int uath_cmd_read(struct uath_softc *, uint32_t, const void *,
274 int, void *, int, int);
275static int uath_cmd_write(struct uath_softc *, uint32_t, const void *,
276 int, int);
277static void uath_stat(void *);
278#ifdef UATH_DEBUG
279static void uath_dump_cmd(const uint8_t *, int, char);
280static const char *
281 uath_codename(int);
282#endif
283static int uath_get_devstatus(struct uath_softc *,
284 uint8_t macaddr[IEEE80211_ADDR_LEN]);
285static int uath_get_status(struct uath_softc *, uint32_t, void *, int);
286static int uath_alloc_rx_data_list(struct uath_softc *);
287static int uath_alloc_tx_data_list(struct uath_softc *);
288static void uath_free_rx_data_list(struct uath_softc *);
289static void uath_free_tx_data_list(struct uath_softc *);
290static int uath_init_locked(void *);
291static void uath_init(void *);
292static void uath_stop_locked(struct ifnet *);
293static void uath_stop(struct ifnet *);
294static int uath_ioctl(struct ifnet *, u_long, caddr_t);
295static void uath_start(struct ifnet *);
296static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
297 const struct ieee80211_bpf_params *);
298static void uath_scan_start(struct ieee80211com *);
299static void uath_scan_end(struct ieee80211com *);
300static void uath_set_channel(struct ieee80211com *);
301static void uath_update_mcast(struct ifnet *);
302static void uath_update_promisc(struct ifnet *);
303static int uath_config(struct uath_softc *, uint32_t, uint32_t);
304static int uath_config_multi(struct uath_softc *, uint32_t, const void *,
305 int);
306static int uath_switch_channel(struct uath_softc *,
307 struct ieee80211_channel *);
308static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
309static void uath_watchdog(void *);
310static void uath_abort_xfers(struct uath_softc *);
311static int uath_dataflush(struct uath_softc *);
312static int uath_cmdflush(struct uath_softc *);
313static int uath_flush(struct uath_softc *);
314static int uath_set_ledstate(struct uath_softc *, int);
315static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
316static int uath_reset_tx_queues(struct uath_softc *);
317static int uath_wme_init(struct uath_softc *);
318static struct uath_data *
319 uath_getbuf(struct uath_softc *);
320static int uath_newstate(struct ieee80211vap *, enum ieee80211_state,
321 int);
322static int uath_set_key(struct uath_softc *,
323 const struct ieee80211_key *, int);
324static int uath_set_keys(struct uath_softc *, struct ieee80211vap *);
325static void uath_sysctl_node(struct uath_softc *);
326
327static int
328uath_match(device_t dev)
329{
330 struct usb2_attach_arg *uaa = device_get_ivars(dev);
331
332 if (uaa->usb_mode != USB_MODE_HOST)
333 return (ENXIO);
334 if (uaa->info.bConfigIndex != UATH_CONFIG_INDEX)
335 return (ENXIO);
336 if (uaa->info.bIfaceIndex != UATH_IFACE_INDEX)
337 return (ENXIO);
338
339 return (usb2_lookup_id_by_uaa(uath_devs, sizeof(uath_devs), uaa));
340}
341
342static int
343uath_attach(device_t dev)
344{
345 struct uath_softc *sc = device_get_softc(dev);
346 struct usb2_attach_arg *uaa = device_get_ivars(dev);
347 struct ieee80211com *ic;
348 struct ifnet *ifp;
349 uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
350 usb2_error_t error;
351 uint8_t macaddr[IEEE80211_ADDR_LEN];
352
353 sc->sc_dev = dev;
354 sc->sc_udev = uaa->device;
355#ifdef UATH_DEBUG
356 sc->sc_debug = uath_debug;
357#endif
358 device_set_usb2_desc(dev);
358
359 /*
360 * Only post-firmware devices here.
361 */
362 mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
363 MTX_DEF);
364 callout_init(&sc->stat_ch, 0);
365 callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
366
367 /*
368 * Allocate xfers for firmware commands.
369 */
370 error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
371 UATH_MAX_CMDSZ);
372 if (error != 0) {
373 device_printf(sc->sc_dev,
374 "could not allocate Tx command list\n");
375 goto fail;
376 }
377
378 error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
379 uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
380 if (error) {
381 device_printf(dev, "could not allocate USB transfers, "
382 "err=%s\n", usb2_errstr(error));
383 goto fail1;
384 }
385
386 /*
387 * We're now ready to send+receive firmware commands.
388 */
389 UATH_LOCK(sc);
390 error = uath_host_available(sc);
391 if (error != 0) {
392 device_printf(sc->sc_dev, "could not initialize adapter\n");
393 goto fail3;
394 }
395 error = uath_get_devcap(sc);
396 if (error != 0) {
397 device_printf(sc->sc_dev,
398 "could not get device capabilities\n");
399 goto fail3;
400 }
401 UATH_UNLOCK(sc);
402
403 /* Create device sysctl node. */
404 uath_sysctl_node(sc);
405
406 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
407 if (ifp == NULL) {
408 device_printf(sc->sc_dev, "can not allocate ifnet\n");
409 error = ENXIO;
410 goto fail2;
411 }
412
413 UATH_LOCK(sc);
414 error = uath_get_devstatus(sc, macaddr);
415 if (error != 0) {
416 device_printf(sc->sc_dev, "could not get device status\n");
417 goto fail4;
418 }
419
420 /*
421 * Allocate xfers for Rx/Tx data pipes.
422 */
423 error = uath_alloc_rx_data_list(sc);
424 if (error != 0) {
425 device_printf(sc->sc_dev, "could not allocate Rx data list\n");
426 goto fail4;
427 }
428 error = uath_alloc_tx_data_list(sc);
429 if (error != 0) {
430 device_printf(sc->sc_dev, "could not allocate Tx data list\n");
431 goto fail4;
432 }
433 UATH_UNLOCK(sc);
434
435 ifp->if_softc = sc;
436 if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
437 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
438 ifp->if_init = uath_init;
439 ifp->if_ioctl = uath_ioctl;
440 ifp->if_start = uath_start;
441 /* XXX UATH_TX_DATA_LIST_COUNT */
442 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
443 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
444 IFQ_SET_READY(&ifp->if_snd);
445
446 ic = ifp->if_l2com;
447 ic->ic_ifp = ifp;
448 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
449 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
450
451 /* set device capabilities */
452 ic->ic_caps =
453 IEEE80211_C_STA | /* station mode */
454 IEEE80211_C_MONITOR | /* monitor mode supported */
455 IEEE80211_C_TXPMGT | /* tx power management */
456 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
457 IEEE80211_C_SHSLOT | /* short slot time supported */
458 IEEE80211_C_WPA | /* 802.11i */
459 IEEE80211_C_BGSCAN | /* capable of bg scanning */
460 IEEE80211_C_TXFRAG; /* handle tx frags */
461
462 /* put a regulatory domain to reveal informations. */
463 uath_regdomain = sc->sc_devcap.regDomain;
464
465 bands = 0;
466 setbit(&bands, IEEE80211_MODE_11B);
467 setbit(&bands, IEEE80211_MODE_11G);
468 if ((sc->sc_devcap.analog5GhzRevision & 0xf0) == 0x30)
469 setbit(&bands, IEEE80211_MODE_11A);
470 /* XXX turbo */
471 ieee80211_init_channels(ic, NULL, &bands);
472
473 ieee80211_ifattach(ic, macaddr);
474 ic->ic_raw_xmit = uath_raw_xmit;
475 ic->ic_scan_start = uath_scan_start;
476 ic->ic_scan_end = uath_scan_end;
477 ic->ic_set_channel = uath_set_channel;
478
479 ic->ic_vap_create = uath_vap_create;
480 ic->ic_vap_delete = uath_vap_delete;
481 ic->ic_update_mcast = uath_update_mcast;
482 ic->ic_update_promisc = uath_update_promisc;
483
484 ieee80211_radiotap_attach(ic,
485 &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
486 UATH_TX_RADIOTAP_PRESENT,
487 &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
488 UATH_RX_RADIOTAP_PRESENT);
489
490 if (bootverbose)
491 ieee80211_announce(ic);
492
493 return (0);
494
495fail4: if_free(ifp);
496fail3: UATH_UNLOCK(sc);
497fail2: usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
498fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
499fail:
500 return (error);
501}
502
503static int
504uath_detach(device_t dev)
505{
506 struct uath_softc *sc = device_get_softc(dev);
507 struct ifnet *ifp = sc->sc_ifp;
508 struct ieee80211com *ic = ifp->if_l2com;
509
510 if (!device_is_attached(dev))
511 return (0);
512
513 sc->sc_flags |= UATH_FLAG_INVALID;
514 uath_stop(ifp);
515
516 callout_drain(&sc->stat_ch);
517 callout_drain(&sc->watchdog_ch);
518
519 usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
520 ieee80211_ifdetach(ic);
521
522 /* free buffers */
523 UATH_LOCK(sc);
524 uath_free_rx_data_list(sc);
525 uath_free_tx_data_list(sc);
526 uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
527 UATH_UNLOCK(sc);
528
529 if_free(ifp);
530 mtx_destroy(&sc->sc_mtx);
531 return (0);
532}
533
534static void
535uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
536{
537 int i;
538
539 for (i = 0; i < ncmd; i++)
540 if (cmds[i].buf != NULL)
541 free(cmds[i].buf, M_USBDEV);
542}
543
544static int
545uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
546 int ncmd, int maxsz)
547{
548 int i, error;
549
550 STAILQ_INIT(&sc->sc_cmd_active);
551 STAILQ_INIT(&sc->sc_cmd_pending);
552 STAILQ_INIT(&sc->sc_cmd_waiting);
553 STAILQ_INIT(&sc->sc_cmd_inactive);
554
555 for (i = 0; i < ncmd; i++) {
556 struct uath_cmd *cmd = &cmds[i];
557
558 cmd->sc = sc; /* backpointer for callbacks */
559 cmd->msgid = i;
560 cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
561 if (cmd->buf == NULL) {
562 device_printf(sc->sc_dev,
563 "could not allocate xfer buffer\n");
564 error = ENOMEM;
565 goto fail;
566 }
567 STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
568 UATH_STAT_INC(sc, st_cmd_inactive);
569 }
570 return (0);
571
572fail: uath_free_cmd_list(sc, cmds, ncmd);
573 return (error);
574}
575
576static int
577uath_host_available(struct uath_softc *sc)
578{
579 struct uath_cmd_host_available setup;
580
581 UATH_ASSERT_LOCKED(sc);
582
583 /* inform target the host is available */
584 setup.sw_ver_major = htobe32(ATH_SW_VER_MAJOR);
585 setup.sw_ver_minor = htobe32(ATH_SW_VER_MINOR);
586 setup.sw_ver_patch = htobe32(ATH_SW_VER_PATCH);
587 setup.sw_ver_build = htobe32(ATH_SW_VER_BUILD);
588 return uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE,
589 &setup, sizeof setup, NULL, 0, 0);
590}
591
592#ifdef UATH_DEBUG
593static void
594uath_dump_cmd(const uint8_t *buf, int len, char prefix)
595{
596 const char *sep = "";
597 int i;
598
599 for (i = 0; i < len; i++) {
600 if ((i % 16) == 0) {
601 printf("%s%c ", sep, prefix);
602 sep = "\n";
603 }
604 else if ((i % 4) == 0)
605 printf(" ");
606 printf("%02x", buf[i]);
607 }
608 printf("\n");
609}
610
611static const char *
612uath_codename(int code)
613{
614#define N(a) (sizeof(a)/sizeof(a[0]))
615 static const char *names[] = {
616 "0x00",
617 "HOST_AVAILABLE",
618 "BIND",
619 "TARGET_RESET",
620 "TARGET_GET_CAPABILITY",
621 "TARGET_SET_CONFIG",
622 "TARGET_GET_STATUS",
623 "TARGET_GET_STATS",
624 "TARGET_START",
625 "TARGET_STOP",
626 "TARGET_ENABLE",
627 "TARGET_DISABLE",
628 "CREATE_CONNECTION",
629 "UPDATE_CONNECT_ATTR",
630 "DELETE_CONNECT",
631 "SEND",
632 "FLUSH",
633 "STATS_UPDATE",
634 "BMISS",
635 "DEVICE_AVAIL",
636 "SEND_COMPLETE",
637 "DATA_AVAIL",
638 "SET_PWR_MODE",
639 "BMISS_ACK",
640 "SET_LED_STEADY",
641 "SET_LED_BLINK",
642 "SETUP_BEACON_DESC",
643 "BEACON_INIT",
644 "RESET_KEY_CACHE",
645 "RESET_KEY_CACHE_ENTRY",
646 "SET_KEY_CACHE_ENTRY",
647 "SET_DECOMP_MASK",
648 "SET_REGULATORY_DOMAIN",
649 "SET_LED_STATE",
650 "WRITE_ASSOCID",
651 "SET_STA_BEACON_TIMERS",
652 "GET_TSF",
653 "RESET_TSF",
654 "SET_ADHOC_MODE",
655 "SET_BASIC_RATE",
656 "MIB_CONTROL",
657 "GET_CHANNEL_DATA",
658 "GET_CUR_RSSI",
659 "SET_ANTENNA_SWITCH",
660 "0x2c", "0x2d", "0x2e",
661 "USE_SHORT_SLOT_TIME",
662 "SET_POWER_MODE",
663 "SETUP_PSPOLL_DESC",
664 "SET_RX_MULTICAST_FILTER",
665 "RX_FILTER",
666 "PER_CALIBRATION",
667 "RESET",
668 "DISABLE",
669 "PHY_DISABLE",
670 "SET_TX_POWER_LIMIT",
671 "SET_TX_QUEUE_PARAMS",
672 "SETUP_TX_QUEUE",
673 "RELEASE_TX_QUEUE",
674 };
675 static char buf[8];
676
677 if (code < N(names))
678 return names[code];
679 if (code == WDCMSG_SET_DEFAULT_KEY)
680 return "SET_DEFAULT_KEY";
681 snprintf(buf, sizeof(buf), "0x%02x", code);
682 return buf;
683#undef N
684}
685#endif
686
687/*
688 * Low-level function to send read or write commands to the firmware.
689 */
690static int
691uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
692 void *odata, int olen, int flags)
693{
694 struct uath_cmd_hdr *hdr;
695 struct uath_cmd *cmd;
696 int error;
697
698 UATH_ASSERT_LOCKED(sc);
699
700 /* grab a xfer */
701 cmd = uath_get_cmdbuf(sc);
702 if (cmd == NULL) {
703 device_printf(sc->sc_dev, "%s: empty inactive queue\n",
704 __func__);
705 return (ENOBUFS);
706 }
707 cmd->flags = flags;
708 /* always bulk-out a multiple of 4 bytes */
709 cmd->buflen = roundup2(sizeof(struct uath_cmd_hdr) + ilen, 4);
710
711 hdr = (struct uath_cmd_hdr *)cmd->buf;
712 bzero(hdr, sizeof (struct uath_cmd_hdr)); /* XXX not needed */
713 hdr->len = htobe32(cmd->buflen);
714 hdr->code = htobe32(code);
715 hdr->msgid = cmd->msgid; /* don't care about endianness */
716 hdr->magic = htobe32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
717 bcopy(idata, (uint8_t *)(hdr + 1), ilen);
718
719#ifdef UATH_DEBUG
720 if (sc->sc_debug & UATH_DEBUG_CMDS) {
721 printf("%s: send %s [flags 0x%x] olen %d\n",
722 __func__, uath_codename(code), cmd->flags, olen);
723 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
724 uath_dump_cmd(cmd->buf, cmd->buflen, '+');
725 }
726#endif
727 cmd->odata = odata;
728 KASSERT(odata == NULL ||
729 olen < UATH_MAX_CMDSZ - sizeof(*hdr) + sizeof(uint32_t),
730 ("odata %p olen %u", odata, olen));
731 cmd->olen = olen;
732
733 STAILQ_INSERT_TAIL(&sc->sc_cmd_pending, cmd, next);
734 UATH_STAT_INC(sc, st_cmd_pending);
735 usb2_transfer_start(sc->sc_xfer[UATH_INTR_TX]);
736
737 if (cmd->flags & UATH_CMD_FLAG_READ) {
738 usb2_transfer_start(sc->sc_xfer[UATH_INTR_RX]);
739
740 /* wait at most two seconds for command reply */
741 error = mtx_sleep(cmd, &sc->sc_mtx, 0, "uathcmd", 2 * hz);
742 cmd->odata = NULL; /* in case reply comes too late */
743 if (error != 0) {
744 device_printf(sc->sc_dev, "timeout waiting for reply "
745 "to cmd 0x%x (%u)\n", code, code);
746 } else if (cmd->olen != olen) {
747 device_printf(sc->sc_dev, "unexpected reply data count "
748 "to cmd 0x%x (%u), got %u, expected %u\n",
749 code, code, cmd->olen, olen);
750 error = EINVAL;
751 }
752 return (error);
753 }
754 return (0);
755}
756
757static int
758uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
759 int ilen, void *odata, int olen, int flags)
760{
761
762 flags |= UATH_CMD_FLAG_READ;
763 return uath_cmdsend(sc, code, idata, ilen, odata, olen, flags);
764}
765
766static int
767uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
768 int flags)
769{
770
771 flags &= ~UATH_CMD_FLAG_READ;
772 return uath_cmdsend(sc, code, data, len, NULL, 0, flags);
773}
774
775static struct uath_cmd *
776uath_get_cmdbuf(struct uath_softc *sc)
777{
778 struct uath_cmd *uc;
779
780 UATH_ASSERT_LOCKED(sc);
781
782 uc = STAILQ_FIRST(&sc->sc_cmd_inactive);
783 if (uc != NULL) {
784 STAILQ_REMOVE_HEAD(&sc->sc_cmd_inactive, next);
785 UATH_STAT_DEC(sc, st_cmd_inactive);
786 } else
787 uc = NULL;
788 if (uc == NULL)
789 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
790 "out of command xmit buffers");
791 return (uc);
792}
793
794/*
795 * This function is called periodically (every second) when associated to
796 * query device statistics.
797 */
798static void
799uath_stat(void *arg)
800{
801 struct uath_softc *sc = arg;
802 int error;
803
804 UATH_LOCK(sc);
805 /*
806 * Send request for statistics asynchronously. The timer will be
807 * restarted when we'll get the stats notification.
808 */
809 error = uath_cmd_write(sc, WDCMSG_TARGET_GET_STATS, NULL, 0,
810 UATH_CMD_FLAG_ASYNC);
811 if (error != 0) {
812 device_printf(sc->sc_dev,
813 "could not query stats, error %d\n", error);
814 }
815 UATH_UNLOCK(sc);
816}
817
818static int
819uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val)
820{
821 int error;
822
823 cap = htobe32(cap);
824 error = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY,
825 &cap, sizeof cap, val, sizeof(uint32_t), UATH_CMD_FLAG_MAGIC);
826 if (error != 0) {
827 device_printf(sc->sc_dev, "could not read capability %u\n",
828 be32toh(cap));
829 return (error);
830 }
831 *val = be32toh(*val);
832 return (error);
833}
834
835static int
836uath_get_devcap(struct uath_softc *sc)
837{
838#define GETCAP(x, v) do { \
839 error = uath_get_capability(sc, x, &v); \
840 if (error != 0) \
841 return (error); \
842 DPRINTF(sc, UATH_DEBUG_DEVCAP, \
843 "%s: %s=0x%08x\n", __func__, #x, v); \
844} while (0)
845 struct uath_devcap *cap = &sc->sc_devcap;
846 int error;
847
848 /* collect device capabilities */
849 GETCAP(CAP_TARGET_VERSION, cap->targetVersion);
850 GETCAP(CAP_TARGET_REVISION, cap->targetRevision);
851 GETCAP(CAP_MAC_VERSION, cap->macVersion);
852 GETCAP(CAP_MAC_REVISION, cap->macRevision);
853 GETCAP(CAP_PHY_REVISION, cap->phyRevision);
854 GETCAP(CAP_ANALOG_5GHz_REVISION, cap->analog5GhzRevision);
855 GETCAP(CAP_ANALOG_2GHz_REVISION, cap->analog2GhzRevision);
856
857 GETCAP(CAP_REG_DOMAIN, cap->regDomain);
858 GETCAP(CAP_REG_CAP_BITS, cap->regCapBits);
859#if 0
860 /* NB: not supported in rev 1.5 */
861 GETCAP(CAP_COUNTRY_CODE, cap->countryCode);
862#endif
863 GETCAP(CAP_WIRELESS_MODES, cap->wirelessModes);
864 GETCAP(CAP_CHAN_SPREAD_SUPPORT, cap->chanSpreadSupport);
865 GETCAP(CAP_COMPRESS_SUPPORT, cap->compressSupport);
866 GETCAP(CAP_BURST_SUPPORT, cap->burstSupport);
867 GETCAP(CAP_FAST_FRAMES_SUPPORT, cap->fastFramesSupport);
868 GETCAP(CAP_CHAP_TUNING_SUPPORT, cap->chapTuningSupport);
869 GETCAP(CAP_TURBOG_SUPPORT, cap->turboGSupport);
870 GETCAP(CAP_TURBO_PRIME_SUPPORT, cap->turboPrimeSupport);
871 GETCAP(CAP_DEVICE_TYPE, cap->deviceType);
872 GETCAP(CAP_WME_SUPPORT, cap->wmeSupport);
873 GETCAP(CAP_TOTAL_QUEUES, cap->numTxQueues);
874 GETCAP(CAP_CONNECTION_ID_MAX, cap->connectionIdMax);
875
876 GETCAP(CAP_LOW_5GHZ_CHAN, cap->low5GhzChan);
877 GETCAP(CAP_HIGH_5GHZ_CHAN, cap->high5GhzChan);
878 GETCAP(CAP_LOW_2GHZ_CHAN, cap->low2GhzChan);
879 GETCAP(CAP_HIGH_2GHZ_CHAN, cap->high2GhzChan);
880 GETCAP(CAP_TWICE_ANTENNAGAIN_5G, cap->twiceAntennaGain5G);
881 GETCAP(CAP_TWICE_ANTENNAGAIN_2G, cap->twiceAntennaGain2G);
882
883 GETCAP(CAP_CIPHER_AES_CCM, cap->supportCipherAES_CCM);
884 GETCAP(CAP_CIPHER_TKIP, cap->supportCipherTKIP);
885 GETCAP(CAP_MIC_TKIP, cap->supportMicTKIP);
886
887 cap->supportCipherWEP = 1; /* NB: always available */
888
889 return (0);
890}
891
892static int
893uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
894{
895 int error;
896
897 /* retrieve MAC address */
898 error = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN);
899 if (error != 0) {
900 device_printf(sc->sc_dev, "could not read MAC address\n");
901 return (error);
902 }
903
904 error = uath_get_status(sc, ST_SERIAL_NUMBER,
905 &sc->sc_serial[0], sizeof(sc->sc_serial));
906 if (error != 0) {
907 device_printf(sc->sc_dev,
908 "could not read device serial number\n");
909 return (error);
910 }
911 return (0);
912}
913
914static int
915uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen)
916{
917 int error;
918
919 which = htobe32(which);
920 error = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS,
921 &which, sizeof(which), odata, olen, UATH_CMD_FLAG_MAGIC);
922 if (error != 0)
923 device_printf(sc->sc_dev,
924 "could not read EEPROM offset 0x%02x\n", be32toh(which));
925 return (error);
926}
927
928static void
929uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata,
930 int fillmbuf)
931{
932 int i;
933
934 for (i = 0; i < ndata; i++) {
935 struct uath_data *dp = &data[i];
936
937 if (fillmbuf == 1) {
938 if (dp->m != NULL) {
939 m_freem(dp->m);
940 dp->m = NULL;
941 dp->buf = NULL;
942 }
943 } else {
944 if (dp->buf != NULL) {
945 free(dp->buf, M_USBDEV);
946 dp->buf = NULL;
947 }
948 }
949#ifdef UATH_DEBUG
950 if (dp->ni != NULL)
951 device_printf(sc->sc_dev, "Node isn't NULL\n");
952#endif
953 }
954}
955
956static int
957uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
958 int ndata, int maxsz, int fillmbuf)
959{
960 int i, error;
961
962 for (i = 0; i < ndata; i++) {
963 struct uath_data *dp = &data[i];
964
965 dp->sc = sc;
966 if (fillmbuf) {
967 /* XXX check maxsz */
968 dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
969 if (dp->m == NULL) {
970 device_printf(sc->sc_dev,
971 "could not allocate rx mbuf\n");
972 error = ENOMEM;
973 goto fail;
974 }
975 dp->buf = mtod(dp->m, uint8_t *);
976 } else {
977 dp->m = NULL;
978 dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
979 if (dp->buf == NULL) {
980 device_printf(sc->sc_dev,
981 "could not allocate buffer\n");
982 error = ENOMEM;
983 goto fail;
984 }
985 }
986 dp->ni = NULL;
987 }
988
989 return (0);
990
991fail: uath_free_data_list(sc, data, ndata, fillmbuf);
992 return (error);
993}
994
995static int
996uath_alloc_rx_data_list(struct uath_softc *sc)
997{
998 int error, i;
999
1000 /* XXX is it enough to store the RX packet with MCLBYTES bytes? */
1001 error = uath_alloc_data_list(sc,
1002 sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
1003 1 /* setup mbufs */);
1004 if (error != 0)
1005 return (error);
1006
1007 STAILQ_INIT(&sc->sc_rx_active);
1008 STAILQ_INIT(&sc->sc_rx_inactive);
1009
1010 for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
1011 STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i],
1012 next);
1013 UATH_STAT_INC(sc, st_rx_inactive);
1014 }
1015
1016 return (0);
1017}
1018
1019static int
1020uath_alloc_tx_data_list(struct uath_softc *sc)
1021{
1022 int error, i;
1023
1024 error = uath_alloc_data_list(sc,
1025 sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
1026 0 /* no mbufs */);
1027 if (error != 0)
1028 return (error);
1029
1030 STAILQ_INIT(&sc->sc_tx_active);
1031 STAILQ_INIT(&sc->sc_tx_inactive);
1032 STAILQ_INIT(&sc->sc_tx_pending);
1033
1034 for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
1035 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i],
1036 next);
1037 UATH_STAT_INC(sc, st_tx_inactive);
1038 }
1039
1040 return (0);
1041}
1042
1043static void
1044uath_free_rx_data_list(struct uath_softc *sc)
1045{
1046
1047 STAILQ_INIT(&sc->sc_rx_active);
1048 STAILQ_INIT(&sc->sc_rx_inactive);
1049
1050 uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
1051 1 /* free mbufs */);
1052}
1053
1054static void
1055uath_free_tx_data_list(struct uath_softc *sc)
1056{
1057
1058 STAILQ_INIT(&sc->sc_tx_active);
1059 STAILQ_INIT(&sc->sc_tx_inactive);
1060 STAILQ_INIT(&sc->sc_tx_pending);
1061
1062 uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
1063 0 /* no mbufs */);
1064}
1065
1066static struct ieee80211vap *
1067uath_vap_create(struct ieee80211com *ic,
1068 const char name[IFNAMSIZ], int unit, int opmode, int flags,
1069 const uint8_t bssid[IEEE80211_ADDR_LEN],
1070 const uint8_t mac[IEEE80211_ADDR_LEN])
1071{
1072 struct uath_vap *uvp;
1073 struct ieee80211vap *vap;
1074
1075 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1076 return (NULL);
1077 uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
1078 M_80211_VAP, M_NOWAIT | M_ZERO);
1079 if (uvp == NULL)
1080 return (NULL);
1081 vap = &uvp->vap;
1082 /* enable s/w bmiss handling for sta mode */
1083 ieee80211_vap_setup(ic, vap, name, unit, opmode,
1084 flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
1085
1086 /* override state transition machine */
1087 uvp->newstate = vap->iv_newstate;
1088 vap->iv_newstate = uath_newstate;
1089
1090 /* complete setup */
1091 ieee80211_vap_attach(vap, ieee80211_media_change,
1092 ieee80211_media_status);
1093 ic->ic_opmode = opmode;
1094 return (vap);
1095}
1096
1097static void
1098uath_vap_delete(struct ieee80211vap *vap)
1099{
1100 struct uath_vap *uvp = UATH_VAP(vap);
1101
1102 ieee80211_vap_detach(vap);
1103 free(uvp, M_80211_VAP);
1104}
1105
1106static int
1107uath_init_locked(void *arg)
1108{
1109 struct uath_softc *sc = arg;
1110 struct ifnet *ifp = sc->sc_ifp;
1111 struct ieee80211com *ic = ifp->if_l2com;
1112 uint32_t val;
1113 int error;
1114
1115 UATH_ASSERT_LOCKED(sc);
1116
1117 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1118 uath_stop_locked(ifp);
1119
1120 /* reset variables */
1121 sc->sc_intrx_nextnum = sc->sc_msgid = 0;
1122
1123 val = htobe32(0);
1124 uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
1125
1126 /* set MAC address */
1127 uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
1128
1129 /* XXX honor net80211 state */
1130 uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
1131 uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001);
1132 uath_config(sc, CFG_ABOLT, 0x0000003f);
1133 uath_config(sc, CFG_WME_ENABLED, 0x00000001);
1134
1135 uath_config(sc, CFG_SERVICE_TYPE, 1);
1136 uath_config(sc, CFG_TP_SCALE, 0x00000000);
1137 uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c);
1138 uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c);
1139 uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000);
1140 uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000);
1141 uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
1142 uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000);
1143 uath_config(sc, CFG_MODE_CTS, 0x00000002);
1144
1145 error = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0,
1146 &val, sizeof(val), UATH_CMD_FLAG_MAGIC);
1147 if (error) {
1148 device_printf(sc->sc_dev,
1149 "could not start target, error %d\n", error);
1150 goto fail;
1151 }
1152 DPRINTF(sc, UATH_DEBUG_INIT, "%s returns handle: 0x%x\n",
1153 uath_codename(WDCMSG_TARGET_START), be32toh(val));
1154
1155 /* set default channel */
1156 error = uath_switch_channel(sc, ic->ic_curchan);
1157 if (error) {
1158 device_printf(sc->sc_dev,
1159 "could not switch channel, error %d\n", error);
1160 goto fail;
1161 }
1162
1163 val = htobe32(TARGET_DEVICE_AWAKE);
1164 uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof val, 0);
1165 /* XXX? check */
1166 uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
1167
1168 usb2_transfer_start(sc->sc_xfer[UATH_BULK_RX]);
1169 /* enable Rx */
1170 uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT);
1171 uath_set_rxfilter(sc,
1172 UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
1173 UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
1174 UATH_FILTER_OP_SET);
1175
1176 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1177 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1178 sc->sc_flags |= UATH_FLAG_INITDONE;
1179
1180 callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
1181
1182 return (0);
1183
1184fail:
1185 uath_stop_locked(ifp);
1186 return (error);
1187}
1188
1189static void
1190uath_init(void *arg)
1191{
1192 struct uath_softc *sc = arg;
1193
1194 UATH_LOCK(sc);
1195 (void)uath_init_locked(sc);
1196 UATH_UNLOCK(sc);
1197}
1198
1199static void
1200uath_stop_locked(struct ifnet *ifp)
1201{
1202 struct uath_softc *sc = ifp->if_softc;
1203
1204 UATH_ASSERT_LOCKED(sc);
1205
1206 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1207 sc->sc_flags &= ~UATH_FLAG_INITDONE;
1208
1209 callout_stop(&sc->stat_ch);
1210 callout_stop(&sc->watchdog_ch);
1211 sc->sc_tx_timer = 0;
1212 /* abort pending transmits */
1213 uath_abort_xfers(sc);
1214 /* flush data & control requests into the target */
1215 (void)uath_flush(sc);
1216 /* set a LED status to the disconnected. */
1217 uath_set_ledstate(sc, 0);
1218 /* stop the target */
1219 uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
1220}
1221
1222static void
1223uath_stop(struct ifnet *ifp)
1224{
1225 struct uath_softc *sc = ifp->if_softc;
1226
1227 UATH_LOCK(sc);
1228 uath_stop_locked(ifp);
1229 UATH_UNLOCK(sc);
1230}
1231
1232static int
1233uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
1234{
1235 struct uath_write_mac write;
1236 int error;
1237
1238 write.reg = htobe32(reg);
1239 write.len = htobe32(0); /* 0 = single write */
1240 *(uint32_t *)write.data = htobe32(val);
1241
1242 error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
1243 3 * sizeof (uint32_t), 0);
1244 if (error != 0) {
1245 device_printf(sc->sc_dev, "could not write register 0x%02x\n",
1246 reg);
1247 }
1248 return (error);
1249}
1250
1251static int
1252uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data,
1253 int len)
1254{
1255 struct uath_write_mac write;
1256 int error;
1257
1258 write.reg = htobe32(reg);
1259 write.len = htobe32(len);
1260 bcopy(data, write.data, len);
1261
1262 /* properly handle the case where len is zero (reset) */
1263 error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
1264 (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
1265 if (error != 0) {
1266 device_printf(sc->sc_dev,
1267 "could not write %d bytes to register 0x%02x\n", len, reg);
1268 }
1269 return (error);
1270}
1271
1272static int
1273uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
1274{
1275 int error;
1276
1277 UATH_ASSERT_LOCKED(sc);
1278
1279 /* set radio frequency */
1280 error = uath_set_chan(sc, c);
1281 if (error) {
1282 device_printf(sc->sc_dev,
1283 "could not set channel, error %d\n", error);
1284 goto failed;
1285 }
1286 /* reset Tx rings */
1287 error = uath_reset_tx_queues(sc);
1288 if (error) {
1289 device_printf(sc->sc_dev,
1290 "could not reset Tx queues, error %d\n", error);
1291 goto failed;
1292 }
1293 /* set Tx rings WME properties */
1294 error = uath_wme_init(sc);
1295 if (error) {
1296 device_printf(sc->sc_dev,
1297 "could not init Tx queues, error %d\n", error);
1298 goto failed;
1299 }
1300 error = uath_set_ledstate(sc, 0);
1301 if (error) {
1302 device_printf(sc->sc_dev,
1303 "could not set led state, error %d\n", error);
1304 goto failed;
1305 }
1306 error = uath_flush(sc);
1307 if (error) {
1308 device_printf(sc->sc_dev,
1309 "could not flush pipes, error %d\n", error);
1310 goto failed;
1311 }
1312failed:
1313 return (error);
1314}
1315
1316static int
1317uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op)
1318{
1319 struct uath_cmd_rx_filter rxfilter;
1320
1321 rxfilter.bits = htobe32(bits);
1322 rxfilter.op = htobe32(op);
1323
1324 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
1325 "setting Rx filter=0x%x flags=0x%x\n", bits, op);
1326 return uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter,
1327 sizeof rxfilter, 0);
1328}
1329
1330static void
1331uath_watchdog(void *arg)
1332{
1333 struct uath_softc *sc = arg;
1334 struct ifnet *ifp = sc->sc_ifp;
1335
1336 if (sc->sc_tx_timer > 0) {
1337 if (--sc->sc_tx_timer == 0) {
1338 device_printf(sc->sc_dev, "device timeout\n");
1339 /*uath_init(ifp); XXX needs a process context! */
1340 ifp->if_oerrors++;
1341 return;
1342 }
1343 callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
1344 }
1345}
1346
1347static void
1348uath_abort_xfers(struct uath_softc *sc)
1349{
1350 int i;
1351
1352 UATH_ASSERT_LOCKED(sc);
1353 /* abort any pending transfers */
1354 for (i = 0; i < UATH_N_XFERS; i++)
1355 usb2_transfer_stop(sc->sc_xfer[i]);
1356}
1357
1358static int
1359uath_flush(struct uath_softc *sc)
1360{
1361 int error;
1362
1363 error = uath_dataflush(sc);
1364 if (error != 0)
1365 goto failed;
1366
1367 error = uath_cmdflush(sc);
1368 if (error != 0)
1369 goto failed;
1370
1371failed:
1372 return (error);
1373}
1374
1375static int
1376uath_cmdflush(struct uath_softc *sc)
1377{
1378
1379 return uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0);
1380}
1381
1382static int
1383uath_dataflush(struct uath_softc *sc)
1384{
1385 struct uath_data *data;
1386 struct uath_chunk *chunk;
1387 struct uath_tx_desc *desc;
1388
1389 UATH_ASSERT_LOCKED(sc);
1390
1391 data = uath_getbuf(sc);
1392 if (data == NULL)
1393 return (ENOBUFS);
1394 data->buflen = sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc);
1395 data->m = NULL;
1396 data->ni = NULL;
1397 chunk = (struct uath_chunk *)data->buf;
1398 desc = (struct uath_tx_desc *)(chunk + 1);
1399
1400 /* one chunk only */
1401 chunk->seqnum = 0;
1402 chunk->flags = UATH_CFLAGS_FINAL;
1403 chunk->length = htobe16(sizeof (struct uath_tx_desc));
1404
1405 bzero(desc, sizeof(struct uath_tx_desc));
1406 desc->msglen = htobe32(sizeof(struct uath_tx_desc));
1407 desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
1408 desc->type = htobe32(WDCMSG_FLUSH);
1409 desc->txqid = htobe32(0);
1410 desc->connid = htobe32(0);
1411 desc->flags = htobe32(0);
1412
1413#ifdef UATH_DEBUG
1414 if (sc->sc_debug & UATH_DEBUG_CMDS) {
1415 DPRINTF(sc, UATH_DEBUG_RESET, "send flush ix %d\n",
1416 desc->msgid);
1417 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
1418 uath_dump_cmd(data->buf, data->buflen, '+');
1419 }
1420#endif
1421
1422 STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
1423 UATH_STAT_INC(sc, st_tx_pending);
1424 sc->sc_tx_timer = 5;
1425 usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
1426
1427 return (0);
1428}
1429
1430static struct uath_data *
1431_uath_getbuf(struct uath_softc *sc)
1432{
1433 struct uath_data *bf;
1434
1435 bf = STAILQ_FIRST(&sc->sc_tx_inactive);
1436 if (bf != NULL) {
1437 STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
1438 UATH_STAT_DEC(sc, st_tx_inactive);
1439 } else
1440 bf = NULL;
1441 if (bf == NULL)
1442 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
1443 "out of xmit buffers");
1444 return (bf);
1445}
1446
1447static struct uath_data *
1448uath_getbuf(struct uath_softc *sc)
1449{
1450 struct uath_data *bf;
1451
1452 UATH_ASSERT_LOCKED(sc);
1453
1454 bf = _uath_getbuf(sc);
1455 if (bf == NULL) {
1456 struct ifnet *ifp = sc->sc_ifp;
1457
1458 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
1459 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1460 }
1461 return (bf);
1462}
1463
1464static int
1465uath_set_ledstate(struct uath_softc *sc, int connected)
1466{
1467
1468 DPRINTF(sc, UATH_DEBUG_LED,
1469 "set led state %sconnected\n", connected ? "" : "!");
1470 connected = htobe32(connected);
1471 return uath_cmd_write(sc, WDCMSG_SET_LED_STATE,
1472 &connected, sizeof connected, 0);
1473}
1474
1475static int
1476uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
1477{
1478#ifdef UATH_DEBUG
1479 struct ifnet *ifp = sc->sc_ifp;
1480 struct ieee80211com *ic = ifp->if_l2com;
1481#endif
1482 struct uath_cmd_reset reset;
1483
1484 bzero(&reset, sizeof reset);
1485 if (IEEE80211_IS_CHAN_2GHZ(c))
1486 reset.flags |= htobe32(UATH_CHAN_2GHZ);
1487 if (IEEE80211_IS_CHAN_5GHZ(c))
1488 reset.flags |= htobe32(UATH_CHAN_5GHZ);
1489 /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */
1490 if (IEEE80211_IS_CHAN_OFDM(c))
1491 reset.flags |= htobe32(UATH_CHAN_OFDM);
1492 else if (IEEE80211_IS_CHAN_CCK(c))
1493 reset.flags |= htobe32(UATH_CHAN_CCK);
1494 /* turbo can be used in either 2GHz or 5GHz */
1495 if (c->ic_flags & IEEE80211_CHAN_TURBO)
1496 reset.flags |= htobe32(UATH_CHAN_TURBO);
1497 reset.freq = htobe32(c->ic_freq);
1498 reset.maxrdpower = htobe32(50); /* XXX */
1499 reset.channelchange = htobe32(1);
1500 reset.keeprccontent = htobe32(0);
1501
1502 DPRINTF(sc, UATH_DEBUG_CHANNEL, "set channel %d, flags 0x%x freq %u\n",
1503 ieee80211_chan2ieee(ic, c),
1504 be32toh(reset.flags), be32toh(reset.freq));
1505 return uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof reset, 0);
1506}
1507
1508static int
1509uath_reset_tx_queues(struct uath_softc *sc)
1510{
1511 int ac, error;
1512
1513 DPRINTF(sc, UATH_DEBUG_RESET, "%s: reset Tx queues\n", __func__);
1514 for (ac = 0; ac < 4; ac++) {
1515 const uint32_t qid = htobe32(ac);
1516
1517 error = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid,
1518 sizeof qid, 0);
1519 if (error != 0)
1520 break;
1521 }
1522 return (error);
1523}
1524
1525static int
1526uath_wme_init(struct uath_softc *sc)
1527{
1528 /* XXX get from net80211 */
1529 static const struct uath_wme_settings uath_wme_11g[4] = {
1530 { 7, 4, 10, 0, 0 }, /* Background */
1531 { 3, 4, 10, 0, 0 }, /* Best-Effort */
1532 { 3, 3, 4, 26, 0 }, /* Video */
1533 { 2, 2, 3, 47, 0 } /* Voice */
1534 };
1535 struct uath_cmd_txq_setup qinfo;
1536 int ac, error;
1537
1538 DPRINTF(sc, UATH_DEBUG_WME, "%s: setup Tx queues\n", __func__);
1539 for (ac = 0; ac < 4; ac++) {
1540 qinfo.qid = htobe32(ac);
1541 qinfo.len = htobe32(sizeof(qinfo.attr));
1542 qinfo.attr.priority = htobe32(ac); /* XXX */
1543 qinfo.attr.aifs = htobe32(uath_wme_11g[ac].aifsn);
1544 qinfo.attr.logcwmin = htobe32(uath_wme_11g[ac].logcwmin);
1545 qinfo.attr.logcwmax = htobe32(uath_wme_11g[ac].logcwmax);
1546 qinfo.attr.bursttime = htobe32(UATH_TXOP_TO_US(
1547 uath_wme_11g[ac].txop));
1548 qinfo.attr.mode = htobe32(uath_wme_11g[ac].acm);/*XXX? */
1549 qinfo.attr.qflags = htobe32(1); /* XXX? */
1550
1551 error = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo,
1552 sizeof qinfo, 0);
1553 if (error != 0)
1554 break;
1555 }
1556 return (error);
1557}
1558
1559static int
1560uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1561{
1562 struct ieee80211com *ic = ifp->if_l2com;
1563 struct ifreq *ifr = (struct ifreq *) data;
1564 int error = 0, startall = 0;
1565
1566 switch (cmd) {
1567 case SIOCSIFFLAGS:
1568 if (ifp->if_flags & IFF_UP) {
1569 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1570 uath_init(ifp->if_softc);
1571 startall = 1;
1572 }
1573 } else {
1574 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1575 uath_stop(ifp);
1576 }
1577 if (startall)
1578 ieee80211_start_all(ic);
1579 break;
1580 case SIOCGIFMEDIA:
1581 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1582 break;
1583 case SIOCGIFADDR:
1584 error = ether_ioctl(ifp, cmd, data);
1585 break;
1586 default:
1587 error = EINVAL;
1588 break;
1589 }
1590
1591 return (error);
1592}
1593
1594static int
1595uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
1596 struct uath_data *data)
1597{
1598 struct ieee80211vap *vap = ni->ni_vap;
1599 struct uath_chunk *chunk;
1600 struct uath_tx_desc *desc;
1601 const struct ieee80211_frame *wh;
1602 struct ieee80211_key *k;
1603 int framelen, msglen;
1604
1605 UATH_ASSERT_LOCKED(sc);
1606
1607 data->ni = ni;
1608 data->m = m0;
1609 chunk = (struct uath_chunk *)data->buf;
1610 desc = (struct uath_tx_desc *)(chunk + 1);
1611
1612 if (ieee80211_radiotap_active_vap(vap)) {
1613 struct uath_tx_radiotap_header *tap = &sc->sc_txtap;
1614
1615 tap->wt_flags = 0;
1616 if (m0->m_flags & M_FRAG)
1617 tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
1618
1619 ieee80211_radiotap_tx(vap, m0);
1620 }
1621
1622 wh = mtod(m0, struct ieee80211_frame *);
1623 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1624 k = ieee80211_crypto_encap(ni, m0);
1625 if (k == NULL) {
1626 m_freem(m0);
1627 return (ENOBUFS);
1628 }
1629
1630 /* packet header may have moved, reset our local pointer */
1631 wh = mtod(m0, struct ieee80211_frame *);
1632 }
1633 m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1));
1634
1635 framelen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
1636 msglen = framelen + sizeof (struct uath_tx_desc);
1637 data->buflen = msglen + sizeof (struct uath_chunk);
1638
1639 /* one chunk only for now */
1640 chunk->seqnum = sc->sc_seqnum++;
1641 chunk->flags = (m0->m_flags & M_FRAG) ? 0 : UATH_CFLAGS_FINAL;
1642 if (m0->m_flags & M_LASTFRAG)
1643 chunk->flags |= UATH_CFLAGS_FINAL;
1644 chunk->flags = UATH_CFLAGS_FINAL;
1645 chunk->length = htobe16(msglen);
1646
1647 /* fill Tx descriptor */
1648 desc->msglen = htobe32(msglen);
1649 /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */
1650 desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
1651 desc->type = htobe32(WDCMSG_SEND);
1652 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1653 case IEEE80211_FC0_TYPE_CTL:
1654 case IEEE80211_FC0_TYPE_MGT:
1655 /* NB: force all management frames to highest queue */
1656 if (ni->ni_flags & IEEE80211_NODE_QOS) {
1657 /* NB: force all management frames to highest queue */
1658 desc->txqid = htobe32(WME_AC_VO | UATH_TXQID_MINRATE);
1659 } else
1660 desc->txqid = htobe32(WME_AC_BE | UATH_TXQID_MINRATE);
1661 break;
1662 case IEEE80211_FC0_TYPE_DATA:
1663 /* XXX multicast frames should honor mcastrate */
1664 desc->txqid = htobe32(M_WME_GETAC(m0));
1665 break;
1666 default:
1667 device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
1668 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
1669 m_freem(m0);
1670 return (EIO);
1671 }
1672 if (vap->iv_state == IEEE80211_S_AUTH ||
1673 vap->iv_state == IEEE80211_S_ASSOC ||
1674 vap->iv_state == IEEE80211_S_RUN)
1675 desc->connid = htobe32(UATH_ID_BSS);
1676 else
1677 desc->connid = htobe32(UATH_ID_INVALID);
1678 desc->flags = htobe32(0 /* no UATH_TX_NOTIFY */);
1679 desc->buflen = htobe32(m0->m_pkthdr.len);
1680
1681#ifdef UATH_DEBUG
1682 DPRINTF(sc, UATH_DEBUG_XMIT,
1683 "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n",
1684 desc->msgid, framelen, msglen, be32toh(desc->connid),
1685 be32toh(desc->txqid));
1686 if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP)
1687 uath_dump_cmd(data->buf, data->buflen, '+');
1688#endif
1689
1690 STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
1691 UATH_STAT_INC(sc, st_tx_pending);
1692 usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
1693
1694 return (0);
1695}
1696
1697/*
1698 * Cleanup driver resources when we run out of buffers while processing
1699 * fragments; return the tx buffers allocated and drop node references.
1700 */
1701static void
1702uath_txfrag_cleanup(struct uath_softc *sc,
1703 uath_datahead *frags, struct ieee80211_node *ni)
1704{
1705 struct uath_data *bf, *next;
1706
1707 UATH_ASSERT_LOCKED(sc);
1708
1709 STAILQ_FOREACH_SAFE(bf, frags, next, next) {
1710 /* NB: bf assumed clean */
1711 STAILQ_REMOVE_HEAD(frags, next);
1712 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1713 UATH_STAT_INC(sc, st_tx_inactive);
1714 ieee80211_node_decref(ni);
1715 }
1716}
1717
1718/*
1719 * Setup xmit of a fragmented frame. Allocate a buffer for each frag and bump
1720 * the node reference count to reflect the held reference to be setup by
1721 * uath_tx_start.
1722 */
1723static int
1724uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags,
1725 struct mbuf *m0, struct ieee80211_node *ni)
1726{
1727 struct mbuf *m;
1728 struct uath_data *bf;
1729
1730 UATH_ASSERT_LOCKED(sc);
1731 for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) {
1732 bf = uath_getbuf(sc);
1733 if (bf == NULL) { /* out of buffers, cleanup */
1734 uath_txfrag_cleanup(sc, frags, ni);
1735 break;
1736 }
1737 ieee80211_node_incref(ni);
1738 STAILQ_INSERT_TAIL(frags, bf, next);
1739 }
1740
1741 return !STAILQ_EMPTY(frags);
1742}
1743
1744/*
1745 * Reclaim mbuf resources. For fragmented frames we need to claim each frag
1746 * chained with m_nextpkt.
1747 */
1748static void
1749uath_freetx(struct mbuf *m)
1750{
1751 struct mbuf *next;
1752
1753 do {
1754 next = m->m_nextpkt;
1755 m->m_nextpkt = NULL;
1756 m_freem(m);
1757 } while ((m = next) != NULL);
1758}
1759
1760static void
1761uath_start(struct ifnet *ifp)
1762{
1763 struct uath_data *bf;
1764 struct uath_softc *sc = ifp->if_softc;
1765 struct ieee80211_node *ni;
1766 struct mbuf *m, *next;
1767 uath_datahead frags;
1768
1769 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
1770 (sc->sc_flags & UATH_FLAG_INVALID))
1771 return;
1772
1773 UATH_LOCK(sc);
1774 for (;;) {
1775 bf = uath_getbuf(sc);
1776 if (bf == NULL)
1777 break;
1778
1779 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1780 if (m == NULL) {
1781 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1782 UATH_STAT_INC(sc, st_tx_inactive);
1783 break;
1784 }
1785 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
1786 m->m_pkthdr.rcvif = NULL;
1787
1788 /*
1789 * Check for fragmentation. If this frame has been broken up
1790 * verify we have enough buffers to send all the fragments
1791 * so all go out or none...
1792 */
1793 STAILQ_INIT(&frags);
1794 if ((m->m_flags & M_FRAG) &&
1795 !uath_txfrag_setup(sc, &frags, m, ni)) {
1796 DPRINTF(sc, UATH_DEBUG_XMIT,
1797 "%s: out of txfrag buffers\n", __func__);
1798 uath_freetx(m);
1799 goto bad;
1800 }
1801 sc->sc_seqnum = 0;
1802 nextfrag:
1803 /*
1804 * Pass the frame to the h/w for transmission.
1805 * Fragmented frames have each frag chained together
1806 * with m_nextpkt. We know there are sufficient uath_data's
1807 * to send all the frags because of work done by
1808 * uath_txfrag_setup.
1809 */
1810 next = m->m_nextpkt;
1811 if (uath_tx_start(sc, m, ni, bf) != 0) {
1812 bad:
1813 ifp->if_oerrors++;
1814 reclaim:
1815 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1816 UATH_STAT_INC(sc, st_tx_inactive);
1817 uath_txfrag_cleanup(sc, &frags, ni);
1818 ieee80211_free_node(ni);
1819 continue;
1820 }
1821
1822 if (next != NULL) {
1823 /*
1824 * Beware of state changing between frags.
1825 XXX check sta power-save state?
1826 */
1827 if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
1828 DPRINTF(sc, UATH_DEBUG_XMIT,
1829 "%s: flush fragmented packet, state %s\n",
1830 __func__,
1831 ieee80211_state_name[ni->ni_vap->iv_state]);
1832 uath_freetx(next);
1833 goto reclaim;
1834 }
1835 m = next;
1836 bf = STAILQ_FIRST(&frags);
1837 KASSERT(bf != NULL, ("no buf for txfrag"));
1838 STAILQ_REMOVE_HEAD(&frags, next);
1839 goto nextfrag;
1840 }
1841
1842 sc->sc_tx_timer = 5;
1843 }
1844 UATH_UNLOCK(sc);
1845}
1846
1847static int
1848uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1849 const struct ieee80211_bpf_params *params)
1850{
1851 struct ieee80211com *ic = ni->ni_ic;
1852 struct ifnet *ifp = ic->ic_ifp;
1853 struct uath_data *bf;
1854 struct uath_softc *sc = ifp->if_softc;
1855
1856 /* prevent management frames from being sent if we're not ready */
1857 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1858 m_freem(m);
1859 ieee80211_free_node(ni);
1860 return (ENETDOWN);
1861 }
1862
1863 UATH_LOCK(sc);
1864 /* grab a TX buffer */
1865 bf = uath_getbuf(sc);
1866 if (bf == NULL) {
1867 ieee80211_free_node(ni);
1868 m_freem(m);
1869 UATH_UNLOCK(sc);
1870 return (ENOBUFS);
1871 }
1872
1873 sc->sc_seqnum = 0;
1874 if (uath_tx_start(sc, m, ni, bf) != 0) {
1875 ieee80211_free_node(ni);
1876 ifp->if_oerrors++;
1877 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1878 UATH_STAT_INC(sc, st_tx_inactive);
1879 UATH_UNLOCK(sc);
1880 return (EIO);
1881 }
1882 UATH_UNLOCK(sc);
1883
1884 sc->sc_tx_timer = 5;
1885 return (0);
1886}
1887
1888static void
1889uath_scan_start(struct ieee80211com *ic)
1890{
1891 /* do nothing */
1892}
1893
1894static void
1895uath_scan_end(struct ieee80211com *ic)
1896{
1897 /* do nothing */
1898}
1899
1900static void
1901uath_set_channel(struct ieee80211com *ic)
1902{
1903 struct ifnet *ifp = ic->ic_ifp;
1904 struct uath_softc *sc = ifp->if_softc;
1905
1906 UATH_LOCK(sc);
1907 (void)uath_switch_channel(sc, ic->ic_curchan);
1908 UATH_UNLOCK(sc);
1909}
1910
1911static int
1912uath_set_rxmulti_filter(struct uath_softc *sc)
1913{
1914 /* XXX broken */
1915 return (0);
1916}
1917static void
1918uath_update_mcast(struct ifnet *ifp)
1919{
1920 struct uath_softc *sc = ifp->if_softc;
1921
1922 UATH_LOCK(sc);
1923 /*
1924 * this is for avoiding the race condition when we're try to
1925 * connect to the AP with WPA.
1926 */
1927 if (sc->sc_flags & UATH_FLAG_INITDONE)
1928 (void)uath_set_rxmulti_filter(sc);
1929 UATH_UNLOCK(sc);
1930}
1931
1932static void
1933uath_update_promisc(struct ifnet *ifp)
1934{
1935 struct uath_softc *sc = ifp->if_softc;
1936
1937 UATH_LOCK(sc);
1938 if (sc->sc_flags & UATH_FLAG_INITDONE) {
1939 uath_set_rxfilter(sc,
1940 UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
1941 UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON |
1942 UATH_FILTER_RX_PROM, UATH_FILTER_OP_SET);
1943 }
1944 UATH_UNLOCK(sc);
1945}
1946
1947static int
1948uath_create_connection(struct uath_softc *sc, uint32_t connid)
1949{
1950 const struct ieee80211_rateset *rs;
1951 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
1952 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1953 struct ieee80211_node *ni = vap->iv_bss;
1954 struct uath_cmd_create_connection create;
1955
1956 bzero(&create, sizeof create);
1957 create.connid = htobe32(connid);
1958 create.bssid = htobe32(0);
1959 /* XXX packed or not? */
1960 create.size = htobe32(sizeof(struct uath_cmd_rateset));
1961
1962 rs = &ni->ni_rates;
1963 create.connattr.rateset.length = rs->rs_nrates;
1964 bcopy(rs->rs_rates, &create.connattr.rateset.set[0],
1965 rs->rs_nrates);
1966
1967 /* XXX turbo */
1968 if (IEEE80211_IS_CHAN_A(ni->ni_chan))
1969 create.connattr.wlanmode = htobe32(WLAN_MODE_11a);
1970 else if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan))
1971 create.connattr.wlanmode = htobe32(WLAN_MODE_11g);
1972 else
1973 create.connattr.wlanmode = htobe32(WLAN_MODE_11b);
1974
1975 return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create,
1976 sizeof create, 0);
1977}
1978
1979static int
1980uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
1981{
1982 struct uath_cmd_rates rates;
1983
1984 bzero(&rates, sizeof rates);
1985 rates.connid = htobe32(UATH_ID_BSS); /* XXX */
1986 rates.size = htobe32(sizeof(struct uath_cmd_rateset));
1987 /* XXX bounds check rs->rs_nrates */
1988 rates.rateset.length = rs->rs_nrates;
1989 bcopy(rs->rs_rates, &rates.rateset.set[0], rs->rs_nrates);
1990
1991 DPRINTF(sc, UATH_DEBUG_RATES,
1992 "setting supported rates nrates=%d\n", rs->rs_nrates);
1993 return uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE,
1994 &rates, sizeof rates, 0);
1995}
1996
1997static int
1998uath_write_associd(struct uath_softc *sc)
1999{
2000 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2001 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2002 struct ieee80211_node *ni = vap->iv_bss;
2003 struct uath_cmd_set_associd associd;
2004
2005 bzero(&associd, sizeof associd);
2006 associd.defaultrateix = htobe32(1); /* XXX */
2007 associd.associd = htobe32(ni->ni_associd);
2008 associd.timoffset = htobe32(0x3b); /* XXX */
2009 IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid);
2010 return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd,
2011 sizeof associd, 0);
2012}
2013
2014static int
2015uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode)
2016{
2017 struct uath_cmd_ledsteady led;
2018
2019 led.lednum = htobe32(lednum);
2020 led.ledmode = htobe32(ledmode);
2021
2022 DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (steady)\n",
2023 (lednum == UATH_LED_LINK) ? "link" : "activity",
2024 ledmode ? "on" : "off");
2025 return uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof led, 0);
2026}
2027
2028static int
2029uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode,
2030 int blinkrate, int slowmode)
2031{
2032 struct uath_cmd_ledblink led;
2033
2034 led.lednum = htobe32(lednum);
2035 led.ledmode = htobe32(ledmode);
2036 led.blinkrate = htobe32(blinkrate);
2037 led.slowmode = htobe32(slowmode);
2038
2039 DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (blink)\n",
2040 (lednum == UATH_LED_LINK) ? "link" : "activity",
2041 ledmode ? "on" : "off");
2042 return uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, &led, sizeof led, 0);
2043}
2044
2045static int
2046uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
2047{
2048 enum ieee80211_state ostate = vap->iv_state;
2049 int error;
2050 struct ieee80211_node *ni = vap->iv_bss;
2051 struct ieee80211com *ic = vap->iv_ic;
2052 struct uath_softc *sc = ic->ic_ifp->if_softc;
2053 struct uath_vap *uvp = UATH_VAP(vap);
2054
2055 DPRINTF(sc, UATH_DEBUG_STATE,
2056 "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state],
2057 ieee80211_state_name[nstate]);
2058
2059 IEEE80211_UNLOCK(ic);
2060 UATH_LOCK(sc);
2061 callout_stop(&sc->stat_ch);
2062 callout_stop(&sc->watchdog_ch);
2063
2064 switch (nstate) {
2065 case IEEE80211_S_INIT:
2066 if (ostate == IEEE80211_S_RUN) {
2067 /* turn link and activity LEDs off */
2068 uath_set_ledstate(sc, 0);
2069 }
2070 break;
2071
2072 case IEEE80211_S_SCAN:
2073 break;
2074
2075 case IEEE80211_S_AUTH:
2076 /* XXX good place? set RTS threshold */
2077 uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold);
2078 /* XXX bad place */
2079 error = uath_set_keys(sc, vap);
2080 if (error != 0) {
2081 device_printf(sc->sc_dev,
2082 "could not set crypto keys, error %d\n", error);
2083 break;
2084 }
2085 if (uath_switch_channel(sc, ni->ni_chan) != 0) {
2086 device_printf(sc->sc_dev, "could not switch channel\n");
2087 break;
2088 }
2089 if (uath_create_connection(sc, UATH_ID_BSS) != 0) {
2090 device_printf(sc->sc_dev,
2091 "could not create connection\n");
2092 break;
2093 }
2094 break;
2095
2096 case IEEE80211_S_ASSOC:
2097 if (uath_set_rates(sc, &ni->ni_rates) != 0) {
2098 device_printf(sc->sc_dev,
2099 "could not set negotiated rate set\n");
2100 break;
2101 }
2102 break;
2103
2104 case IEEE80211_S_RUN:
2105 /* XXX monitor mode doesn't be tested */
2106 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2107 uath_set_ledstate(sc, 1);
2108 break;
2109 }
2110
2111 /*
2112 * Tx rate is controlled by firmware, report the maximum
2113 * negotiated rate in ifconfig output.
2114 */
2115 ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1];
2116
2117 if (uath_write_associd(sc) != 0) {
2118 device_printf(sc->sc_dev,
2119 "could not write association id\n");
2120 break;
2121 }
2122 /* turn link LED on */
2123 uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON);
2124 /* make activity LED blink */
2125 uath_set_ledblink(sc, UATH_LED_ACTIVITY, UATH_LED_ON, 1, 2);
2126 /* set state to associated */
2127 uath_set_ledstate(sc, 1);
2128
2129 /* start statistics timer */
2130 callout_reset(&sc->stat_ch, hz, uath_stat, sc);
2131 break;
2132 default:
2133 break;
2134 }
2135 UATH_UNLOCK(sc);
2136 IEEE80211_LOCK(ic);
2137 return (uvp->newstate(vap, nstate, arg));
2138}
2139
2140static int
2141uath_set_key(struct uath_softc *sc, const struct ieee80211_key *wk,
2142 int index)
2143{
2144#if 0
2145 struct uath_cmd_crypto crypto;
2146 int i;
2147
2148 bzero(&crypto, sizeof crypto);
2149 crypto.keyidx = htobe32(index);
2150 crypto.magic1 = htobe32(1);
2151 crypto.size = htobe32(368);
2152 crypto.mask = htobe32(0xffff);
2153 crypto.flags = htobe32(0x80000068);
2154 if (index != UATH_DEFAULT_KEY)
2155 crypto.flags |= htobe32(index << 16);
2156 memset(crypto.magic2, 0xff, sizeof crypto.magic2);
2157
2158 /*
2159 * Each byte of the key must be XOR'ed with 10101010 before being
2160 * transmitted to the firmware.
2161 */
2162 for (i = 0; i < wk->wk_keylen; i++)
2163 crypto.key[i] = wk->wk_key[i] ^ 0xaa;
2164
2165 DPRINTF(sc, UATH_DEBUG_CRYPTO,
2166 "setting crypto key index=%d len=%d\n", index, wk->wk_keylen);
2167 return uath_cmd_write(sc, WDCMSG_SET_KEY_CACHE_ENTRY, &crypto,
2168 sizeof crypto, 0);
2169#else
2170 /* XXX support H/W cryto */
2171 return (0);
2172#endif
2173}
2174
2175static int
2176uath_set_keys(struct uath_softc *sc, struct ieee80211vap *vap)
2177{
2178 int i, error;
2179
2180 error = 0;
2181 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2182 const struct ieee80211_key *wk = &vap->iv_nw_keys[i];
2183
2184 if (wk->wk_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV)) {
2185 error = uath_set_key(sc, wk, i);
2186 if (error)
2187 return (error);
2188 }
2189 }
2190 if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) {
2191 error = uath_set_key(sc, &vap->iv_nw_keys[vap->iv_def_txkey],
2192 UATH_DEFAULT_KEY);
2193 }
2194 return (error);
2195}
2196
2197#define UATH_SYSCTL_STAT_ADD32(c, h, n, p, d) \
2198 SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
2199
2200static void
2201uath_sysctl_node(struct uath_softc *sc)
2202{
2203 struct sysctl_ctx_list *ctx;
2204 struct sysctl_oid_list *child;
2205 struct sysctl_oid *tree;
2206 struct uath_stat *stats;
2207
2208 stats = &sc->sc_stat;
2209 ctx = device_get_sysctl_ctx(sc->sc_dev);
2210 child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev));
2211
2212 tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
2213 NULL, "UATH statistics");
2214 child = SYSCTL_CHILDREN(tree);
2215 UATH_SYSCTL_STAT_ADD32(ctx, child, "badchunkseqnum",
2216 &stats->st_badchunkseqnum, "Bad chunk sequence numbers");
2217 UATH_SYSCTL_STAT_ADD32(ctx, child, "invalidlen", &stats->st_invalidlen,
2218 "Invalid length");
2219 UATH_SYSCTL_STAT_ADD32(ctx, child, "multichunk", &stats->st_multichunk,
2220 "Multi chunks");
2221 UATH_SYSCTL_STAT_ADD32(ctx, child, "toobigrxpkt",
2222 &stats->st_toobigrxpkt, "Too big rx packets");
2223 UATH_SYSCTL_STAT_ADD32(ctx, child, "stopinprogress",
2224 &stats->st_stopinprogress, "Stop in progress");
2225 UATH_SYSCTL_STAT_ADD32(ctx, child, "crcerrs", &stats->st_crcerr,
2226 "CRC errors");
2227 UATH_SYSCTL_STAT_ADD32(ctx, child, "phyerr", &stats->st_phyerr,
2228 "PHY errors");
2229 UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_crcerr",
2230 &stats->st_decrypt_crcerr, "Decryption CRC errors");
2231 UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_micerr",
2232 &stats->st_decrypt_micerr, "Decryption Misc errors");
2233 UATH_SYSCTL_STAT_ADD32(ctx, child, "decomperr", &stats->st_decomperr,
2234 "Decomp errors");
2235 UATH_SYSCTL_STAT_ADD32(ctx, child, "keyerr", &stats->st_keyerr,
2236 "Key errors");
2237 UATH_SYSCTL_STAT_ADD32(ctx, child, "err", &stats->st_err,
2238 "Unknown errors");
2239
2240 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_active",
2241 &stats->st_cmd_active, "Active numbers in Command queue");
2242 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_inactive",
2243 &stats->st_cmd_inactive, "Inactive numbers in Command queue");
2244 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_pending",
2245 &stats->st_cmd_pending, "Pending numbers in Command queue");
2246 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_waiting",
2247 &stats->st_cmd_waiting, "Waiting numbers in Command queue");
2248 UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_active",
2249 &stats->st_rx_active, "Active numbers in RX queue");
2250 UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_inactive",
2251 &stats->st_rx_inactive, "Inactive numbers in RX queue");
2252 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_active",
2253 &stats->st_tx_active, "Active numbers in TX queue");
2254 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive",
2255 &stats->st_tx_inactive, "Inactive numbers in TX queue");
2256 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_pending",
2257 &stats->st_tx_pending, "Pending numbers in TX queue");
2258}
2259
2260#undef UATH_SYSCTL_STAT_ADD32
2261
2262static void
2263uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
2264{
2265 struct uath_cmd_hdr *hdr;
2266 int dlen;
2267
2268 hdr = (struct uath_cmd_hdr *)cmd->buf;
2269 /* NB: msgid is passed thru w/o byte swapping */
2270#ifdef UATH_DEBUG
2271 if (sc->sc_debug & UATH_DEBUG_CMDS) {
2272 int len = be32toh(hdr->len);
2273 printf("%s: %s [ix %u] len %u status %u\n",
2274 __func__, uath_codename(be32toh(hdr->code)),
2275 hdr->msgid, len, be32toh(hdr->magic));
2276 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
2277 uath_dump_cmd(cmd->buf,
2278 len > UATH_MAX_CMDSZ ? sizeof(*hdr) : len, '-');
2279 }
2280#endif
2281 hdr->code = be32toh(hdr->code);
2282 hdr->len = be32toh(hdr->len);
2283 hdr->magic = be32toh(hdr->magic); /* target status on return */
2284
2285 switch (hdr->code & 0xff) {
2286 /* reply to a read command */
2287 default:
2288 dlen = hdr->len - sizeof(*hdr);
2289 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2290 "%s: code %d data len %u\n",
2291 __func__, hdr->code & 0xff, dlen);
2292 /*
2293 * The first response from the target after the
2294 * HOST_AVAILABLE has an invalid msgid so we must
2295 * treat it specially.
2296 */
2297 if (hdr->msgid < UATH_CMD_LIST_COUNT) {
2298 uint32_t *rp = (uint32_t *)(hdr+1);
2299 u_int olen;
2300
2301 if (!(sizeof(*hdr) <= hdr->len &&
2302 hdr->len < UATH_MAX_CMDSZ)) {
2303 device_printf(sc->sc_dev,
2304 "%s: invalid WDC msg length %u; "
2305 "msg ignored\n", __func__, hdr->len);
2306 return;
2307 }
2308 /*
2309 * Calculate return/receive payload size; the
2310 * first word, if present, always gives the
2311 * number of bytes--unless it's 0 in which
2312 * case a single 32-bit word should be present.
2313 */
2314 if (dlen >= sizeof(uint32_t)) {
2315 olen = be32toh(rp[0]);
2316 dlen -= sizeof(uint32_t);
2317 if (olen == 0) {
2318 /* convention is 0 =>'s one word */
2319 olen = sizeof(uint32_t);
2320 /* XXX KASSERT(olen == dlen ) */
2321 }
2322 } else
2323 olen = 0;
2324 if (cmd->odata != NULL) {
2325 /* NB: cmd->olen validated in uath_cmd */
2326 if (olen > cmd->olen) {
2327 /* XXX complain? */
2328 device_printf(sc->sc_dev,
2329 "%s: cmd 0x%x olen %u cmd olen %u\n",
2330 __func__, hdr->code, olen,
2331 cmd->olen);
2332 olen = cmd->olen;
2333 }
2334 if (olen > dlen) {
2335 /* XXX complain, shouldn't happen */
2336 device_printf(sc->sc_dev,
2337 "%s: cmd 0x%x olen %u dlen %u\n",
2338 __func__, hdr->code, olen, dlen);
2339 olen = dlen;
2340 }
2341 /* XXX have submitter do this */
2342 /* copy answer into caller's supplied buffer */
2343 bcopy(&rp[1], cmd->odata, olen);
2344 cmd->olen = olen;
2345 }
2346 }
2347 wakeup_one(cmd); /* wake up caller */
2348 break;
2349
2350 case WDCMSG_TARGET_START:
2351 if (hdr->msgid >= UATH_CMD_LIST_COUNT) {
2352 /* XXX */
2353 return;
2354 }
2355 dlen = hdr->len - sizeof(*hdr);
2356 if (dlen != sizeof(uint32_t)) {
2357 /* XXX something wrong */
2358 return;
2359 }
2360 /* XXX have submitter do this */
2361 /* copy answer into caller's supplied buffer */
2362 bcopy(hdr+1, cmd->odata, sizeof(uint32_t));
2363 cmd->olen = sizeof(uint32_t);
2364 wakeup_one(cmd); /* wake up caller */
2365 break;
2366
2367 case WDCMSG_SEND_COMPLETE:
2368 /* this notification is sent when UATH_TX_NOTIFY is set */
2369 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2370 "%s: received Tx notification\n", __func__);
2371 break;
2372
2373 case WDCMSG_TARGET_GET_STATS:
2374 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2375 "%s: received device statistics\n", __func__);
2376 callout_reset(&sc->stat_ch, hz, uath_stat, sc);
2377 break;
2378 }
2379}
2380
2381static void
2382uath_intr_rx_callback(struct usb2_xfer *xfer)
2383{
2384 struct uath_softc *sc = xfer->priv_sc;
2385 struct uath_cmd *cmd;
2386
2387 UATH_ASSERT_LOCKED(sc);
2388
2389 switch (USB_GET_STATE(xfer)) {
2390 case USB_ST_TRANSFERRED:
2391 cmd = STAILQ_FIRST(&sc->sc_cmd_waiting);
2392 if (cmd == NULL)
2393 goto setup;
2394 STAILQ_REMOVE_HEAD(&sc->sc_cmd_waiting, next);
2395 UATH_STAT_DEC(sc, st_cmd_waiting);
2396 STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
2397 UATH_STAT_INC(sc, st_cmd_inactive);
2398
2399 KASSERT(xfer->actlen >= sizeof(struct uath_cmd_hdr),
2400 ("short xfer error"));
2401 usb2_copy_out(xfer->frbuffers, 0, cmd->buf, xfer->actlen);
2402 uath_cmdeof(sc, cmd);
2403 case USB_ST_SETUP:
2404setup:
2405 xfer->frlengths[0] = xfer->max_data_length;
2406 usb2_start_hardware(xfer);
2407 break;
2408 default:
2409 if (xfer->error != USB_ERR_CANCELLED) {
2410 xfer->flags.stall_pipe = 1;
2411 goto setup;
2412 }
2413 break;
2414 }
2415}
2416
2417static void
2418uath_intr_tx_callback(struct usb2_xfer *xfer)
2419{
2420 struct uath_softc *sc = xfer->priv_sc;
2421 struct uath_cmd *cmd;
2422
2423 UATH_ASSERT_LOCKED(sc);
2424
2425 switch (USB_GET_STATE(xfer)) {
2426 case USB_ST_TRANSFERRED:
2427 cmd = STAILQ_FIRST(&sc->sc_cmd_active);
2428 if (cmd == NULL)
2429 goto setup;
2430 STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next);
2431 UATH_STAT_DEC(sc, st_cmd_active);
2432 STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ?
2433 &sc->sc_cmd_waiting : &sc->sc_cmd_inactive, cmd, next);
2434 if (cmd->flags & UATH_CMD_FLAG_READ)
2435 UATH_STAT_INC(sc, st_cmd_waiting);
2436 else
2437 UATH_STAT_INC(sc, st_cmd_inactive);
2438 /* FALLTHROUGH */
2439 case USB_ST_SETUP:
2440setup:
2441 cmd = STAILQ_FIRST(&sc->sc_cmd_pending);
2442 if (cmd == NULL) {
2443 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
2444 __func__);
2445 return;
2446 }
2447 STAILQ_REMOVE_HEAD(&sc->sc_cmd_pending, next);
2448 UATH_STAT_DEC(sc, st_cmd_pending);
2449 STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_ASYNC) ?
2450 &sc->sc_cmd_inactive : &sc->sc_cmd_active, cmd, next);
2451 if (cmd->flags & UATH_CMD_FLAG_ASYNC)
2452 UATH_STAT_INC(sc, st_cmd_inactive);
2453 else
2454 UATH_STAT_INC(sc, st_cmd_active);
2455
2456 usb2_set_frame_data(xfer, cmd->buf, 0);
2457 xfer->frlengths[0] = cmd->buflen;
2458 usb2_start_hardware(xfer);
2459 break;
2460 default:
2461 if (xfer->error != USB_ERR_CANCELLED) {
2462 xfer->flags.stall_pipe = 1;
2463 goto setup;
2464 }
2465 break;
2466 }
2467}
2468
2469static void
2470uath_update_rxstat(struct uath_softc *sc, uint32_t status)
2471{
2472
2473 switch (status) {
2474 case UATH_STATUS_STOP_IN_PROGRESS:
2475 UATH_STAT_INC(sc, st_stopinprogress);
2476 break;
2477 case UATH_STATUS_CRC_ERR:
2478 UATH_STAT_INC(sc, st_crcerr);
2479 break;
2480 case UATH_STATUS_PHY_ERR:
2481 UATH_STAT_INC(sc, st_phyerr);
2482 break;
2483 case UATH_STATUS_DECRYPT_CRC_ERR:
2484 UATH_STAT_INC(sc, st_decrypt_crcerr);
2485 break;
2486 case UATH_STATUS_DECRYPT_MIC_ERR:
2487 UATH_STAT_INC(sc, st_decrypt_micerr);
2488 break;
2489 case UATH_STATUS_DECOMP_ERR:
2490 UATH_STAT_INC(sc, st_decomperr);
2491 break;
2492 case UATH_STATUS_KEY_ERR:
2493 UATH_STAT_INC(sc, st_keyerr);
2494 break;
2495 case UATH_STATUS_ERR:
2496 UATH_STAT_INC(sc, st_err);
2497 break;
2498 default:
2499 break;
2500 }
2501}
2502
2503static struct mbuf *
2504uath_data_rxeof(struct usb2_xfer *xfer, struct uath_data *data,
2505 struct uath_rx_desc **pdesc)
2506{
2507 struct uath_softc *sc = xfer->priv_sc;
2508 struct ifnet *ifp = sc->sc_ifp;
2509 struct ieee80211com *ic = ifp->if_l2com;
2510 struct uath_chunk *chunk;
2511 struct uath_rx_desc *desc;
2512 struct mbuf *m = data->m, *mnew, *mp;
2513 uint16_t chunklen;
2514
2515 if (xfer->actlen < UATH_MIN_RXBUFSZ) {
2516 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2517 "%s: wrong xfer size (len=%d)\n", __func__, xfer->actlen);
2518 ifp->if_ierrors++;
2519 return (NULL);
2520 }
2521
2522 chunk = (struct uath_chunk *)data->buf;
2523 if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
2524 device_printf(sc->sc_dev, "%s: strange response\n", __func__);
2525 ifp->if_ierrors++;
2526 UATH_RESET_INTRX(sc);
2527 return (NULL);
2528 }
2529
2530 if (chunk->seqnum != sc->sc_intrx_nextnum) {
2531 DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
2532 chunk->seqnum, sc->sc_intrx_nextnum);
2533 UATH_STAT_INC(sc, st_badchunkseqnum);
2534 if (sc->sc_intrx_head != NULL)
2535 m_freem(sc->sc_intrx_head);
2536 UATH_RESET_INTRX(sc);
2537 return (NULL);
2538 }
2539
2540 /* check multi-chunk frames */
2541 if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) ||
2542 (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) ||
2543 chunk->flags & UATH_CFLAGS_RXMSG)
2544 UATH_STAT_INC(sc, st_multichunk);
2545
2546 chunklen = be16toh(chunk->length);
2547 if (chunk->flags & UATH_CFLAGS_FINAL)
2548 chunklen -= sizeof(struct uath_rx_desc);
2549
2550 if (chunklen > 0 &&
2551 (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
2552 /* we should use intermediate RX buffer */
2553 if (chunk->seqnum == 0)
2554 UATH_RESET_INTRX(sc);
2555 if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
2556 chunklen) > UATH_MAX_INTRX_SIZE) {
2557 UATH_STAT_INC(sc, st_invalidlen);
2558 ifp->if_iqdrops++;
2559 if (sc->sc_intrx_head != NULL)
2560 m_freem(sc->sc_intrx_head);
2561 UATH_RESET_INTRX(sc);
2562 return (NULL);
2563 }
2564
2565 m->m_len = chunklen;
2566 m->m_data += sizeof(struct uath_chunk);
2567
2568 if (sc->sc_intrx_head == NULL) {
2569 sc->sc_intrx_head = m;
2570 sc->sc_intrx_tail = m;
2571 } else {
2572 m->m_flags &= ~M_PKTHDR;
2573 sc->sc_intrx_tail->m_next = m;
2574 sc->sc_intrx_tail = m;
2575 }
2576 }
2577 sc->sc_intrx_len += chunklen;
2578
2579 mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2580 if (mnew == NULL) {
2581 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2582 "%s: can't get new mbuf, drop frame\n", __func__);
2583 ifp->if_ierrors++;
2584 if (sc->sc_intrx_head != NULL)
2585 m_freem(sc->sc_intrx_head);
2586 UATH_RESET_INTRX(sc);
2587 return (NULL);
2588 }
2589
2590 data->m = mnew;
2591 data->buf = mtod(mnew, uint8_t *);
2592
2593 /* if the frame is not final continue the transfer */
2594 if (!(chunk->flags & UATH_CFLAGS_FINAL)) {
2595 sc->sc_intrx_nextnum++;
2596 UATH_RESET_INTRX(sc);
2597 return (NULL);
2598 }
2599
2600 /*
2601 * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is
2602 * located at the end, 32-bit aligned
2603 */
2604 desc = (chunk->flags & UATH_CFLAGS_RXMSG) ?
2605 (struct uath_rx_desc *)(chunk + 1) :
2606 (struct uath_rx_desc *)(((uint8_t *)chunk) +
2607 sizeof(struct uath_chunk) + be16toh(chunk->length) -
2608 sizeof(struct uath_rx_desc));
2609 *pdesc = desc;
2610
2611 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2612 "%s: frame len %u code %u status %u rate %u antenna %u "
2613 "rssi %d channel %u phyerror %u connix %u decrypterror %u "
2614 "keycachemiss %u\n", __func__, be32toh(desc->framelen)
2615 , be32toh(desc->code), be32toh(desc->status), be32toh(desc->rate)
2616 , be32toh(desc->antenna), be32toh(desc->rssi), be32toh(desc->channel)
2617 , be32toh(desc->phyerror), be32toh(desc->connix)
2618 , be32toh(desc->decrypterror), be32toh(desc->keycachemiss));
2619
2620 if (be32toh(desc->len) > MCLBYTES) {
2621 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2622 "%s: bad descriptor (len=%d)\n", __func__,
2623 be32toh(desc->len));
2624 ifp->if_iqdrops++;
2625 UATH_STAT_INC(sc, st_toobigrxpkt);
2626 if (sc->sc_intrx_head != NULL)
2627 m_freem(sc->sc_intrx_head);
2628 UATH_RESET_INTRX(sc);
2629 return (NULL);
2630 }
2631
2632 uath_update_rxstat(sc, be32toh(desc->status));
2633
2634 /* finalize mbuf */
2635 if (sc->sc_intrx_head == NULL) {
2636 m->m_pkthdr.rcvif = ifp;
2637 m->m_pkthdr.len = m->m_len =
2638 be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
2639 m->m_data += sizeof(struct uath_chunk);
2640 } else {
2641 mp = sc->sc_intrx_head;
2642 mp->m_pkthdr.rcvif = ifp;
2643 mp->m_flags |= M_PKTHDR;
2644 mp->m_pkthdr.len = sc->sc_intrx_len;
2645 m = mp;
2646 }
2647
2648 /* there are a lot more fields in the RX descriptor */
2649 if (ieee80211_radiotap_active(ic)) {
2650 struct uath_rx_radiotap_header *tap = &sc->sc_rxtap;
2651 uint32_t tsf_hi = be32toh(desc->tstamp_high);
2652 uint32_t tsf_lo = be32toh(desc->tstamp_low);
2653
2654 /* XXX only get low order 24bits of tsf from h/w */
2655 tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
2656 tap->wr_flags = 0;
2657 if (be32toh(desc->status) == UATH_STATUS_CRC_ERR)
2658 tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
2659 /* XXX map other status to BADFCS? */
2660 /* XXX ath h/w rate code, need to map */
2661 tap->wr_rate = be32toh(desc->rate);
2662 tap->wr_antenna = be32toh(desc->antenna);
2663 tap->wr_antsignal = -95 + be32toh(desc->rssi);
2664 tap->wr_antnoise = -95;
2665 }
2666
2667 ifp->if_ipackets++;
2668 UATH_RESET_INTRX(sc);
2669
2670 return (m);
2671}
2672
2673static void
2674uath_bulk_rx_callback(struct usb2_xfer *xfer)
2675{
2676 struct uath_softc *sc = xfer->priv_sc;
2677 struct ifnet *ifp = sc->sc_ifp;
2678 struct ieee80211com *ic = ifp->if_l2com;
2679 struct ieee80211_frame *wh;
2680 struct ieee80211_node *ni;
2681 struct mbuf *m = NULL;
2682 struct uath_data *data;
2683 struct uath_rx_desc *desc = NULL;
2684 int8_t nf;
2685
2686 UATH_ASSERT_LOCKED(sc);
2687
2688 switch (USB_GET_STATE(xfer)) {
2689 case USB_ST_TRANSFERRED:
2690 data = STAILQ_FIRST(&sc->sc_rx_active);
2691 if (data == NULL)
2692 goto setup;
2693 STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
2694 UATH_STAT_DEC(sc, st_rx_active);
2695 m = uath_data_rxeof(xfer, data, &desc);
2696 STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
2697 UATH_STAT_INC(sc, st_rx_inactive);
2698 /* FALLTHROUGH */
2699 case USB_ST_SETUP:
2700setup:
2701 data = STAILQ_FIRST(&sc->sc_rx_inactive);
2702 if (data == NULL)
2703 return;
2704 STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
2705 UATH_STAT_DEC(sc, st_rx_inactive);
2706 STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
2707 UATH_STAT_INC(sc, st_rx_active);
2708 usb2_set_frame_data(xfer, data->buf, 0);
2709 xfer->frlengths[0] = xfer->max_data_length;
2710 usb2_start_hardware(xfer);
2711
2712 /*
2713 * To avoid LOR we should unlock our private mutex here to call
2714 * ieee80211_input() because here is at the end of a USB
2715 * callback and safe to unlock.
2716 */
2717 UATH_UNLOCK(sc);
2718 if (m != NULL && desc != NULL) {
2719 wh = mtod(m, struct ieee80211_frame *);
2720 ni = ieee80211_find_rxnode(ic,
2721 (struct ieee80211_frame_min *)wh);
2722 nf = -95; /* XXX */
2723 if (ni != NULL) {
2724 (void) ieee80211_input(ni, m,
2725 (int)be32toh(desc->rssi), nf);
2726 /* node is no longer needed */
2727 ieee80211_free_node(ni);
2728 } else
2729 (void) ieee80211_input_all(ic, m,
2730 (int)be32toh(desc->rssi), nf);
2731 m = NULL;
2732 desc = NULL;
2733 }
2734 UATH_LOCK(sc);
2735 break;
2736 default:
2737 /* needs it to the inactive queue due to a error. */
2738 data = STAILQ_FIRST(&sc->sc_rx_active);
2739 if (data != NULL) {
2740 STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
2741 UATH_STAT_DEC(sc, st_rx_active);
2742 STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
2743 UATH_STAT_INC(sc, st_rx_inactive);
2744 }
2745 if (xfer->error != USB_ERR_CANCELLED) {
2746 xfer->flags.stall_pipe = 1;
2747 ifp->if_ierrors++;
2748 goto setup;
2749 }
2750 break;
2751 }
2752}
2753
2754static void
2755uath_data_txeof(struct usb2_xfer *xfer, struct uath_data *data)
2756{
2757 struct uath_softc *sc = xfer->priv_sc;
2758 struct ifnet *ifp = sc->sc_ifp;
2759 struct mbuf *m;
2760
2761 UATH_ASSERT_LOCKED(sc);
2762
2763 /*
2764 * Do any tx complete callback. Note this must be done before releasing
2765 * the node reference.
2766 */
2767 if (data->m) {
2768 m = data->m;
2769 if (m->m_flags & M_TXCB) {
2770 /* XXX status? */
2771 ieee80211_process_callback(data->ni, m, 0);
2772 }
2773 m_freem(m);
2774 data->m = NULL;
2775 }
2776 if (data->ni) {
2777 ieee80211_free_node(data->ni);
2778 data->ni = NULL;
2779 }
2780 sc->sc_tx_timer = 0;
2781 ifp->if_opackets++;
2782 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2783}
2784
2785static void
2786uath_bulk_tx_callback(struct usb2_xfer *xfer)
2787{
2788 struct uath_softc *sc = xfer->priv_sc;
2789 struct ifnet *ifp = sc->sc_ifp;
2790 struct uath_data *data;
2791
2792 UATH_ASSERT_LOCKED(sc);
2793
2794 switch (USB_GET_STATE(xfer)) {
2795 case USB_ST_TRANSFERRED:
2796 data = STAILQ_FIRST(&sc->sc_tx_active);
2797 if (data == NULL)
2798 goto setup;
2799 STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next);
2800 UATH_STAT_DEC(sc, st_tx_active);
2801 uath_data_txeof(xfer, data);
2802 STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
2803 UATH_STAT_INC(sc, st_tx_inactive);
2804 /* FALLTHROUGH */
2805 case USB_ST_SETUP:
2806setup:
2807 data = STAILQ_FIRST(&sc->sc_tx_pending);
2808 if (data == NULL) {
2809 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
2810 __func__);
2811 return;
2812 }
2813 STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
2814 UATH_STAT_DEC(sc, st_tx_pending);
2815 STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
2816 UATH_STAT_INC(sc, st_tx_active);
2817
2818 usb2_set_frame_data(xfer, data->buf, 0);
2819 xfer->frlengths[0] = data->buflen;
2820 usb2_start_hardware(xfer);
2821
2822 UATH_UNLOCK(sc);
2823 uath_start(ifp);
2824 UATH_LOCK(sc);
2825 break;
2826 default:
2827 data = STAILQ_FIRST(&sc->sc_tx_active);
2828 if (data == NULL)
2829 goto setup;
2830 if (data->ni != NULL) {
2831 ieee80211_free_node(data->ni);
2832 data->ni = NULL;
2833 ifp->if_oerrors++;
2834 }
2835 if (xfer->error != USB_ERR_CANCELLED) {
2836 xfer->flags.stall_pipe = 1;
2837 goto setup;
2838 }
2839 break;
2840 }
2841}
2842
2843static device_method_t uath_methods[] = {
2844 DEVMETHOD(device_probe, uath_match),
2845 DEVMETHOD(device_attach, uath_attach),
2846 DEVMETHOD(device_detach, uath_detach),
2847 { 0, 0 }
2848};
2849static driver_t uath_driver = {
2850 "uath",
2851 uath_methods,
2852 sizeof(struct uath_softc)
2853};
2854static devclass_t uath_devclass;
2855
2856DRIVER_MODULE(uath, uhub, uath_driver, uath_devclass, NULL, 0);
2857MODULE_DEPEND(uath, wlan, 1, 1, 1);
2858MODULE_DEPEND(uath, usb, 1, 1, 1);
359
360 /*
361 * Only post-firmware devices here.
362 */
363 mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
364 MTX_DEF);
365 callout_init(&sc->stat_ch, 0);
366 callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
367
368 /*
369 * Allocate xfers for firmware commands.
370 */
371 error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
372 UATH_MAX_CMDSZ);
373 if (error != 0) {
374 device_printf(sc->sc_dev,
375 "could not allocate Tx command list\n");
376 goto fail;
377 }
378
379 error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
380 uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
381 if (error) {
382 device_printf(dev, "could not allocate USB transfers, "
383 "err=%s\n", usb2_errstr(error));
384 goto fail1;
385 }
386
387 /*
388 * We're now ready to send+receive firmware commands.
389 */
390 UATH_LOCK(sc);
391 error = uath_host_available(sc);
392 if (error != 0) {
393 device_printf(sc->sc_dev, "could not initialize adapter\n");
394 goto fail3;
395 }
396 error = uath_get_devcap(sc);
397 if (error != 0) {
398 device_printf(sc->sc_dev,
399 "could not get device capabilities\n");
400 goto fail3;
401 }
402 UATH_UNLOCK(sc);
403
404 /* Create device sysctl node. */
405 uath_sysctl_node(sc);
406
407 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
408 if (ifp == NULL) {
409 device_printf(sc->sc_dev, "can not allocate ifnet\n");
410 error = ENXIO;
411 goto fail2;
412 }
413
414 UATH_LOCK(sc);
415 error = uath_get_devstatus(sc, macaddr);
416 if (error != 0) {
417 device_printf(sc->sc_dev, "could not get device status\n");
418 goto fail4;
419 }
420
421 /*
422 * Allocate xfers for Rx/Tx data pipes.
423 */
424 error = uath_alloc_rx_data_list(sc);
425 if (error != 0) {
426 device_printf(sc->sc_dev, "could not allocate Rx data list\n");
427 goto fail4;
428 }
429 error = uath_alloc_tx_data_list(sc);
430 if (error != 0) {
431 device_printf(sc->sc_dev, "could not allocate Tx data list\n");
432 goto fail4;
433 }
434 UATH_UNLOCK(sc);
435
436 ifp->if_softc = sc;
437 if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
438 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
439 ifp->if_init = uath_init;
440 ifp->if_ioctl = uath_ioctl;
441 ifp->if_start = uath_start;
442 /* XXX UATH_TX_DATA_LIST_COUNT */
443 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
444 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
445 IFQ_SET_READY(&ifp->if_snd);
446
447 ic = ifp->if_l2com;
448 ic->ic_ifp = ifp;
449 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
450 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
451
452 /* set device capabilities */
453 ic->ic_caps =
454 IEEE80211_C_STA | /* station mode */
455 IEEE80211_C_MONITOR | /* monitor mode supported */
456 IEEE80211_C_TXPMGT | /* tx power management */
457 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
458 IEEE80211_C_SHSLOT | /* short slot time supported */
459 IEEE80211_C_WPA | /* 802.11i */
460 IEEE80211_C_BGSCAN | /* capable of bg scanning */
461 IEEE80211_C_TXFRAG; /* handle tx frags */
462
463 /* put a regulatory domain to reveal informations. */
464 uath_regdomain = sc->sc_devcap.regDomain;
465
466 bands = 0;
467 setbit(&bands, IEEE80211_MODE_11B);
468 setbit(&bands, IEEE80211_MODE_11G);
469 if ((sc->sc_devcap.analog5GhzRevision & 0xf0) == 0x30)
470 setbit(&bands, IEEE80211_MODE_11A);
471 /* XXX turbo */
472 ieee80211_init_channels(ic, NULL, &bands);
473
474 ieee80211_ifattach(ic, macaddr);
475 ic->ic_raw_xmit = uath_raw_xmit;
476 ic->ic_scan_start = uath_scan_start;
477 ic->ic_scan_end = uath_scan_end;
478 ic->ic_set_channel = uath_set_channel;
479
480 ic->ic_vap_create = uath_vap_create;
481 ic->ic_vap_delete = uath_vap_delete;
482 ic->ic_update_mcast = uath_update_mcast;
483 ic->ic_update_promisc = uath_update_promisc;
484
485 ieee80211_radiotap_attach(ic,
486 &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
487 UATH_TX_RADIOTAP_PRESENT,
488 &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
489 UATH_RX_RADIOTAP_PRESENT);
490
491 if (bootverbose)
492 ieee80211_announce(ic);
493
494 return (0);
495
496fail4: if_free(ifp);
497fail3: UATH_UNLOCK(sc);
498fail2: usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
499fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
500fail:
501 return (error);
502}
503
504static int
505uath_detach(device_t dev)
506{
507 struct uath_softc *sc = device_get_softc(dev);
508 struct ifnet *ifp = sc->sc_ifp;
509 struct ieee80211com *ic = ifp->if_l2com;
510
511 if (!device_is_attached(dev))
512 return (0);
513
514 sc->sc_flags |= UATH_FLAG_INVALID;
515 uath_stop(ifp);
516
517 callout_drain(&sc->stat_ch);
518 callout_drain(&sc->watchdog_ch);
519
520 usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
521 ieee80211_ifdetach(ic);
522
523 /* free buffers */
524 UATH_LOCK(sc);
525 uath_free_rx_data_list(sc);
526 uath_free_tx_data_list(sc);
527 uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
528 UATH_UNLOCK(sc);
529
530 if_free(ifp);
531 mtx_destroy(&sc->sc_mtx);
532 return (0);
533}
534
535static void
536uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
537{
538 int i;
539
540 for (i = 0; i < ncmd; i++)
541 if (cmds[i].buf != NULL)
542 free(cmds[i].buf, M_USBDEV);
543}
544
545static int
546uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
547 int ncmd, int maxsz)
548{
549 int i, error;
550
551 STAILQ_INIT(&sc->sc_cmd_active);
552 STAILQ_INIT(&sc->sc_cmd_pending);
553 STAILQ_INIT(&sc->sc_cmd_waiting);
554 STAILQ_INIT(&sc->sc_cmd_inactive);
555
556 for (i = 0; i < ncmd; i++) {
557 struct uath_cmd *cmd = &cmds[i];
558
559 cmd->sc = sc; /* backpointer for callbacks */
560 cmd->msgid = i;
561 cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
562 if (cmd->buf == NULL) {
563 device_printf(sc->sc_dev,
564 "could not allocate xfer buffer\n");
565 error = ENOMEM;
566 goto fail;
567 }
568 STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
569 UATH_STAT_INC(sc, st_cmd_inactive);
570 }
571 return (0);
572
573fail: uath_free_cmd_list(sc, cmds, ncmd);
574 return (error);
575}
576
577static int
578uath_host_available(struct uath_softc *sc)
579{
580 struct uath_cmd_host_available setup;
581
582 UATH_ASSERT_LOCKED(sc);
583
584 /* inform target the host is available */
585 setup.sw_ver_major = htobe32(ATH_SW_VER_MAJOR);
586 setup.sw_ver_minor = htobe32(ATH_SW_VER_MINOR);
587 setup.sw_ver_patch = htobe32(ATH_SW_VER_PATCH);
588 setup.sw_ver_build = htobe32(ATH_SW_VER_BUILD);
589 return uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE,
590 &setup, sizeof setup, NULL, 0, 0);
591}
592
593#ifdef UATH_DEBUG
594static void
595uath_dump_cmd(const uint8_t *buf, int len, char prefix)
596{
597 const char *sep = "";
598 int i;
599
600 for (i = 0; i < len; i++) {
601 if ((i % 16) == 0) {
602 printf("%s%c ", sep, prefix);
603 sep = "\n";
604 }
605 else if ((i % 4) == 0)
606 printf(" ");
607 printf("%02x", buf[i]);
608 }
609 printf("\n");
610}
611
612static const char *
613uath_codename(int code)
614{
615#define N(a) (sizeof(a)/sizeof(a[0]))
616 static const char *names[] = {
617 "0x00",
618 "HOST_AVAILABLE",
619 "BIND",
620 "TARGET_RESET",
621 "TARGET_GET_CAPABILITY",
622 "TARGET_SET_CONFIG",
623 "TARGET_GET_STATUS",
624 "TARGET_GET_STATS",
625 "TARGET_START",
626 "TARGET_STOP",
627 "TARGET_ENABLE",
628 "TARGET_DISABLE",
629 "CREATE_CONNECTION",
630 "UPDATE_CONNECT_ATTR",
631 "DELETE_CONNECT",
632 "SEND",
633 "FLUSH",
634 "STATS_UPDATE",
635 "BMISS",
636 "DEVICE_AVAIL",
637 "SEND_COMPLETE",
638 "DATA_AVAIL",
639 "SET_PWR_MODE",
640 "BMISS_ACK",
641 "SET_LED_STEADY",
642 "SET_LED_BLINK",
643 "SETUP_BEACON_DESC",
644 "BEACON_INIT",
645 "RESET_KEY_CACHE",
646 "RESET_KEY_CACHE_ENTRY",
647 "SET_KEY_CACHE_ENTRY",
648 "SET_DECOMP_MASK",
649 "SET_REGULATORY_DOMAIN",
650 "SET_LED_STATE",
651 "WRITE_ASSOCID",
652 "SET_STA_BEACON_TIMERS",
653 "GET_TSF",
654 "RESET_TSF",
655 "SET_ADHOC_MODE",
656 "SET_BASIC_RATE",
657 "MIB_CONTROL",
658 "GET_CHANNEL_DATA",
659 "GET_CUR_RSSI",
660 "SET_ANTENNA_SWITCH",
661 "0x2c", "0x2d", "0x2e",
662 "USE_SHORT_SLOT_TIME",
663 "SET_POWER_MODE",
664 "SETUP_PSPOLL_DESC",
665 "SET_RX_MULTICAST_FILTER",
666 "RX_FILTER",
667 "PER_CALIBRATION",
668 "RESET",
669 "DISABLE",
670 "PHY_DISABLE",
671 "SET_TX_POWER_LIMIT",
672 "SET_TX_QUEUE_PARAMS",
673 "SETUP_TX_QUEUE",
674 "RELEASE_TX_QUEUE",
675 };
676 static char buf[8];
677
678 if (code < N(names))
679 return names[code];
680 if (code == WDCMSG_SET_DEFAULT_KEY)
681 return "SET_DEFAULT_KEY";
682 snprintf(buf, sizeof(buf), "0x%02x", code);
683 return buf;
684#undef N
685}
686#endif
687
688/*
689 * Low-level function to send read or write commands to the firmware.
690 */
691static int
692uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
693 void *odata, int olen, int flags)
694{
695 struct uath_cmd_hdr *hdr;
696 struct uath_cmd *cmd;
697 int error;
698
699 UATH_ASSERT_LOCKED(sc);
700
701 /* grab a xfer */
702 cmd = uath_get_cmdbuf(sc);
703 if (cmd == NULL) {
704 device_printf(sc->sc_dev, "%s: empty inactive queue\n",
705 __func__);
706 return (ENOBUFS);
707 }
708 cmd->flags = flags;
709 /* always bulk-out a multiple of 4 bytes */
710 cmd->buflen = roundup2(sizeof(struct uath_cmd_hdr) + ilen, 4);
711
712 hdr = (struct uath_cmd_hdr *)cmd->buf;
713 bzero(hdr, sizeof (struct uath_cmd_hdr)); /* XXX not needed */
714 hdr->len = htobe32(cmd->buflen);
715 hdr->code = htobe32(code);
716 hdr->msgid = cmd->msgid; /* don't care about endianness */
717 hdr->magic = htobe32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
718 bcopy(idata, (uint8_t *)(hdr + 1), ilen);
719
720#ifdef UATH_DEBUG
721 if (sc->sc_debug & UATH_DEBUG_CMDS) {
722 printf("%s: send %s [flags 0x%x] olen %d\n",
723 __func__, uath_codename(code), cmd->flags, olen);
724 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
725 uath_dump_cmd(cmd->buf, cmd->buflen, '+');
726 }
727#endif
728 cmd->odata = odata;
729 KASSERT(odata == NULL ||
730 olen < UATH_MAX_CMDSZ - sizeof(*hdr) + sizeof(uint32_t),
731 ("odata %p olen %u", odata, olen));
732 cmd->olen = olen;
733
734 STAILQ_INSERT_TAIL(&sc->sc_cmd_pending, cmd, next);
735 UATH_STAT_INC(sc, st_cmd_pending);
736 usb2_transfer_start(sc->sc_xfer[UATH_INTR_TX]);
737
738 if (cmd->flags & UATH_CMD_FLAG_READ) {
739 usb2_transfer_start(sc->sc_xfer[UATH_INTR_RX]);
740
741 /* wait at most two seconds for command reply */
742 error = mtx_sleep(cmd, &sc->sc_mtx, 0, "uathcmd", 2 * hz);
743 cmd->odata = NULL; /* in case reply comes too late */
744 if (error != 0) {
745 device_printf(sc->sc_dev, "timeout waiting for reply "
746 "to cmd 0x%x (%u)\n", code, code);
747 } else if (cmd->olen != olen) {
748 device_printf(sc->sc_dev, "unexpected reply data count "
749 "to cmd 0x%x (%u), got %u, expected %u\n",
750 code, code, cmd->olen, olen);
751 error = EINVAL;
752 }
753 return (error);
754 }
755 return (0);
756}
757
758static int
759uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
760 int ilen, void *odata, int olen, int flags)
761{
762
763 flags |= UATH_CMD_FLAG_READ;
764 return uath_cmdsend(sc, code, idata, ilen, odata, olen, flags);
765}
766
767static int
768uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
769 int flags)
770{
771
772 flags &= ~UATH_CMD_FLAG_READ;
773 return uath_cmdsend(sc, code, data, len, NULL, 0, flags);
774}
775
776static struct uath_cmd *
777uath_get_cmdbuf(struct uath_softc *sc)
778{
779 struct uath_cmd *uc;
780
781 UATH_ASSERT_LOCKED(sc);
782
783 uc = STAILQ_FIRST(&sc->sc_cmd_inactive);
784 if (uc != NULL) {
785 STAILQ_REMOVE_HEAD(&sc->sc_cmd_inactive, next);
786 UATH_STAT_DEC(sc, st_cmd_inactive);
787 } else
788 uc = NULL;
789 if (uc == NULL)
790 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
791 "out of command xmit buffers");
792 return (uc);
793}
794
795/*
796 * This function is called periodically (every second) when associated to
797 * query device statistics.
798 */
799static void
800uath_stat(void *arg)
801{
802 struct uath_softc *sc = arg;
803 int error;
804
805 UATH_LOCK(sc);
806 /*
807 * Send request for statistics asynchronously. The timer will be
808 * restarted when we'll get the stats notification.
809 */
810 error = uath_cmd_write(sc, WDCMSG_TARGET_GET_STATS, NULL, 0,
811 UATH_CMD_FLAG_ASYNC);
812 if (error != 0) {
813 device_printf(sc->sc_dev,
814 "could not query stats, error %d\n", error);
815 }
816 UATH_UNLOCK(sc);
817}
818
819static int
820uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val)
821{
822 int error;
823
824 cap = htobe32(cap);
825 error = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY,
826 &cap, sizeof cap, val, sizeof(uint32_t), UATH_CMD_FLAG_MAGIC);
827 if (error != 0) {
828 device_printf(sc->sc_dev, "could not read capability %u\n",
829 be32toh(cap));
830 return (error);
831 }
832 *val = be32toh(*val);
833 return (error);
834}
835
836static int
837uath_get_devcap(struct uath_softc *sc)
838{
839#define GETCAP(x, v) do { \
840 error = uath_get_capability(sc, x, &v); \
841 if (error != 0) \
842 return (error); \
843 DPRINTF(sc, UATH_DEBUG_DEVCAP, \
844 "%s: %s=0x%08x\n", __func__, #x, v); \
845} while (0)
846 struct uath_devcap *cap = &sc->sc_devcap;
847 int error;
848
849 /* collect device capabilities */
850 GETCAP(CAP_TARGET_VERSION, cap->targetVersion);
851 GETCAP(CAP_TARGET_REVISION, cap->targetRevision);
852 GETCAP(CAP_MAC_VERSION, cap->macVersion);
853 GETCAP(CAP_MAC_REVISION, cap->macRevision);
854 GETCAP(CAP_PHY_REVISION, cap->phyRevision);
855 GETCAP(CAP_ANALOG_5GHz_REVISION, cap->analog5GhzRevision);
856 GETCAP(CAP_ANALOG_2GHz_REVISION, cap->analog2GhzRevision);
857
858 GETCAP(CAP_REG_DOMAIN, cap->regDomain);
859 GETCAP(CAP_REG_CAP_BITS, cap->regCapBits);
860#if 0
861 /* NB: not supported in rev 1.5 */
862 GETCAP(CAP_COUNTRY_CODE, cap->countryCode);
863#endif
864 GETCAP(CAP_WIRELESS_MODES, cap->wirelessModes);
865 GETCAP(CAP_CHAN_SPREAD_SUPPORT, cap->chanSpreadSupport);
866 GETCAP(CAP_COMPRESS_SUPPORT, cap->compressSupport);
867 GETCAP(CAP_BURST_SUPPORT, cap->burstSupport);
868 GETCAP(CAP_FAST_FRAMES_SUPPORT, cap->fastFramesSupport);
869 GETCAP(CAP_CHAP_TUNING_SUPPORT, cap->chapTuningSupport);
870 GETCAP(CAP_TURBOG_SUPPORT, cap->turboGSupport);
871 GETCAP(CAP_TURBO_PRIME_SUPPORT, cap->turboPrimeSupport);
872 GETCAP(CAP_DEVICE_TYPE, cap->deviceType);
873 GETCAP(CAP_WME_SUPPORT, cap->wmeSupport);
874 GETCAP(CAP_TOTAL_QUEUES, cap->numTxQueues);
875 GETCAP(CAP_CONNECTION_ID_MAX, cap->connectionIdMax);
876
877 GETCAP(CAP_LOW_5GHZ_CHAN, cap->low5GhzChan);
878 GETCAP(CAP_HIGH_5GHZ_CHAN, cap->high5GhzChan);
879 GETCAP(CAP_LOW_2GHZ_CHAN, cap->low2GhzChan);
880 GETCAP(CAP_HIGH_2GHZ_CHAN, cap->high2GhzChan);
881 GETCAP(CAP_TWICE_ANTENNAGAIN_5G, cap->twiceAntennaGain5G);
882 GETCAP(CAP_TWICE_ANTENNAGAIN_2G, cap->twiceAntennaGain2G);
883
884 GETCAP(CAP_CIPHER_AES_CCM, cap->supportCipherAES_CCM);
885 GETCAP(CAP_CIPHER_TKIP, cap->supportCipherTKIP);
886 GETCAP(CAP_MIC_TKIP, cap->supportMicTKIP);
887
888 cap->supportCipherWEP = 1; /* NB: always available */
889
890 return (0);
891}
892
893static int
894uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
895{
896 int error;
897
898 /* retrieve MAC address */
899 error = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN);
900 if (error != 0) {
901 device_printf(sc->sc_dev, "could not read MAC address\n");
902 return (error);
903 }
904
905 error = uath_get_status(sc, ST_SERIAL_NUMBER,
906 &sc->sc_serial[0], sizeof(sc->sc_serial));
907 if (error != 0) {
908 device_printf(sc->sc_dev,
909 "could not read device serial number\n");
910 return (error);
911 }
912 return (0);
913}
914
915static int
916uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen)
917{
918 int error;
919
920 which = htobe32(which);
921 error = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS,
922 &which, sizeof(which), odata, olen, UATH_CMD_FLAG_MAGIC);
923 if (error != 0)
924 device_printf(sc->sc_dev,
925 "could not read EEPROM offset 0x%02x\n", be32toh(which));
926 return (error);
927}
928
929static void
930uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata,
931 int fillmbuf)
932{
933 int i;
934
935 for (i = 0; i < ndata; i++) {
936 struct uath_data *dp = &data[i];
937
938 if (fillmbuf == 1) {
939 if (dp->m != NULL) {
940 m_freem(dp->m);
941 dp->m = NULL;
942 dp->buf = NULL;
943 }
944 } else {
945 if (dp->buf != NULL) {
946 free(dp->buf, M_USBDEV);
947 dp->buf = NULL;
948 }
949 }
950#ifdef UATH_DEBUG
951 if (dp->ni != NULL)
952 device_printf(sc->sc_dev, "Node isn't NULL\n");
953#endif
954 }
955}
956
957static int
958uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
959 int ndata, int maxsz, int fillmbuf)
960{
961 int i, error;
962
963 for (i = 0; i < ndata; i++) {
964 struct uath_data *dp = &data[i];
965
966 dp->sc = sc;
967 if (fillmbuf) {
968 /* XXX check maxsz */
969 dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
970 if (dp->m == NULL) {
971 device_printf(sc->sc_dev,
972 "could not allocate rx mbuf\n");
973 error = ENOMEM;
974 goto fail;
975 }
976 dp->buf = mtod(dp->m, uint8_t *);
977 } else {
978 dp->m = NULL;
979 dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
980 if (dp->buf == NULL) {
981 device_printf(sc->sc_dev,
982 "could not allocate buffer\n");
983 error = ENOMEM;
984 goto fail;
985 }
986 }
987 dp->ni = NULL;
988 }
989
990 return (0);
991
992fail: uath_free_data_list(sc, data, ndata, fillmbuf);
993 return (error);
994}
995
996static int
997uath_alloc_rx_data_list(struct uath_softc *sc)
998{
999 int error, i;
1000
1001 /* XXX is it enough to store the RX packet with MCLBYTES bytes? */
1002 error = uath_alloc_data_list(sc,
1003 sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
1004 1 /* setup mbufs */);
1005 if (error != 0)
1006 return (error);
1007
1008 STAILQ_INIT(&sc->sc_rx_active);
1009 STAILQ_INIT(&sc->sc_rx_inactive);
1010
1011 for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
1012 STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i],
1013 next);
1014 UATH_STAT_INC(sc, st_rx_inactive);
1015 }
1016
1017 return (0);
1018}
1019
1020static int
1021uath_alloc_tx_data_list(struct uath_softc *sc)
1022{
1023 int error, i;
1024
1025 error = uath_alloc_data_list(sc,
1026 sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
1027 0 /* no mbufs */);
1028 if (error != 0)
1029 return (error);
1030
1031 STAILQ_INIT(&sc->sc_tx_active);
1032 STAILQ_INIT(&sc->sc_tx_inactive);
1033 STAILQ_INIT(&sc->sc_tx_pending);
1034
1035 for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
1036 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i],
1037 next);
1038 UATH_STAT_INC(sc, st_tx_inactive);
1039 }
1040
1041 return (0);
1042}
1043
1044static void
1045uath_free_rx_data_list(struct uath_softc *sc)
1046{
1047
1048 STAILQ_INIT(&sc->sc_rx_active);
1049 STAILQ_INIT(&sc->sc_rx_inactive);
1050
1051 uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
1052 1 /* free mbufs */);
1053}
1054
1055static void
1056uath_free_tx_data_list(struct uath_softc *sc)
1057{
1058
1059 STAILQ_INIT(&sc->sc_tx_active);
1060 STAILQ_INIT(&sc->sc_tx_inactive);
1061 STAILQ_INIT(&sc->sc_tx_pending);
1062
1063 uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
1064 0 /* no mbufs */);
1065}
1066
1067static struct ieee80211vap *
1068uath_vap_create(struct ieee80211com *ic,
1069 const char name[IFNAMSIZ], int unit, int opmode, int flags,
1070 const uint8_t bssid[IEEE80211_ADDR_LEN],
1071 const uint8_t mac[IEEE80211_ADDR_LEN])
1072{
1073 struct uath_vap *uvp;
1074 struct ieee80211vap *vap;
1075
1076 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1077 return (NULL);
1078 uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
1079 M_80211_VAP, M_NOWAIT | M_ZERO);
1080 if (uvp == NULL)
1081 return (NULL);
1082 vap = &uvp->vap;
1083 /* enable s/w bmiss handling for sta mode */
1084 ieee80211_vap_setup(ic, vap, name, unit, opmode,
1085 flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
1086
1087 /* override state transition machine */
1088 uvp->newstate = vap->iv_newstate;
1089 vap->iv_newstate = uath_newstate;
1090
1091 /* complete setup */
1092 ieee80211_vap_attach(vap, ieee80211_media_change,
1093 ieee80211_media_status);
1094 ic->ic_opmode = opmode;
1095 return (vap);
1096}
1097
1098static void
1099uath_vap_delete(struct ieee80211vap *vap)
1100{
1101 struct uath_vap *uvp = UATH_VAP(vap);
1102
1103 ieee80211_vap_detach(vap);
1104 free(uvp, M_80211_VAP);
1105}
1106
1107static int
1108uath_init_locked(void *arg)
1109{
1110 struct uath_softc *sc = arg;
1111 struct ifnet *ifp = sc->sc_ifp;
1112 struct ieee80211com *ic = ifp->if_l2com;
1113 uint32_t val;
1114 int error;
1115
1116 UATH_ASSERT_LOCKED(sc);
1117
1118 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1119 uath_stop_locked(ifp);
1120
1121 /* reset variables */
1122 sc->sc_intrx_nextnum = sc->sc_msgid = 0;
1123
1124 val = htobe32(0);
1125 uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
1126
1127 /* set MAC address */
1128 uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
1129
1130 /* XXX honor net80211 state */
1131 uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
1132 uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001);
1133 uath_config(sc, CFG_ABOLT, 0x0000003f);
1134 uath_config(sc, CFG_WME_ENABLED, 0x00000001);
1135
1136 uath_config(sc, CFG_SERVICE_TYPE, 1);
1137 uath_config(sc, CFG_TP_SCALE, 0x00000000);
1138 uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c);
1139 uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c);
1140 uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000);
1141 uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000);
1142 uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
1143 uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000);
1144 uath_config(sc, CFG_MODE_CTS, 0x00000002);
1145
1146 error = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0,
1147 &val, sizeof(val), UATH_CMD_FLAG_MAGIC);
1148 if (error) {
1149 device_printf(sc->sc_dev,
1150 "could not start target, error %d\n", error);
1151 goto fail;
1152 }
1153 DPRINTF(sc, UATH_DEBUG_INIT, "%s returns handle: 0x%x\n",
1154 uath_codename(WDCMSG_TARGET_START), be32toh(val));
1155
1156 /* set default channel */
1157 error = uath_switch_channel(sc, ic->ic_curchan);
1158 if (error) {
1159 device_printf(sc->sc_dev,
1160 "could not switch channel, error %d\n", error);
1161 goto fail;
1162 }
1163
1164 val = htobe32(TARGET_DEVICE_AWAKE);
1165 uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof val, 0);
1166 /* XXX? check */
1167 uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
1168
1169 usb2_transfer_start(sc->sc_xfer[UATH_BULK_RX]);
1170 /* enable Rx */
1171 uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT);
1172 uath_set_rxfilter(sc,
1173 UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
1174 UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
1175 UATH_FILTER_OP_SET);
1176
1177 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1178 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1179 sc->sc_flags |= UATH_FLAG_INITDONE;
1180
1181 callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
1182
1183 return (0);
1184
1185fail:
1186 uath_stop_locked(ifp);
1187 return (error);
1188}
1189
1190static void
1191uath_init(void *arg)
1192{
1193 struct uath_softc *sc = arg;
1194
1195 UATH_LOCK(sc);
1196 (void)uath_init_locked(sc);
1197 UATH_UNLOCK(sc);
1198}
1199
1200static void
1201uath_stop_locked(struct ifnet *ifp)
1202{
1203 struct uath_softc *sc = ifp->if_softc;
1204
1205 UATH_ASSERT_LOCKED(sc);
1206
1207 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1208 sc->sc_flags &= ~UATH_FLAG_INITDONE;
1209
1210 callout_stop(&sc->stat_ch);
1211 callout_stop(&sc->watchdog_ch);
1212 sc->sc_tx_timer = 0;
1213 /* abort pending transmits */
1214 uath_abort_xfers(sc);
1215 /* flush data & control requests into the target */
1216 (void)uath_flush(sc);
1217 /* set a LED status to the disconnected. */
1218 uath_set_ledstate(sc, 0);
1219 /* stop the target */
1220 uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
1221}
1222
1223static void
1224uath_stop(struct ifnet *ifp)
1225{
1226 struct uath_softc *sc = ifp->if_softc;
1227
1228 UATH_LOCK(sc);
1229 uath_stop_locked(ifp);
1230 UATH_UNLOCK(sc);
1231}
1232
1233static int
1234uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
1235{
1236 struct uath_write_mac write;
1237 int error;
1238
1239 write.reg = htobe32(reg);
1240 write.len = htobe32(0); /* 0 = single write */
1241 *(uint32_t *)write.data = htobe32(val);
1242
1243 error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
1244 3 * sizeof (uint32_t), 0);
1245 if (error != 0) {
1246 device_printf(sc->sc_dev, "could not write register 0x%02x\n",
1247 reg);
1248 }
1249 return (error);
1250}
1251
1252static int
1253uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data,
1254 int len)
1255{
1256 struct uath_write_mac write;
1257 int error;
1258
1259 write.reg = htobe32(reg);
1260 write.len = htobe32(len);
1261 bcopy(data, write.data, len);
1262
1263 /* properly handle the case where len is zero (reset) */
1264 error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
1265 (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
1266 if (error != 0) {
1267 device_printf(sc->sc_dev,
1268 "could not write %d bytes to register 0x%02x\n", len, reg);
1269 }
1270 return (error);
1271}
1272
1273static int
1274uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
1275{
1276 int error;
1277
1278 UATH_ASSERT_LOCKED(sc);
1279
1280 /* set radio frequency */
1281 error = uath_set_chan(sc, c);
1282 if (error) {
1283 device_printf(sc->sc_dev,
1284 "could not set channel, error %d\n", error);
1285 goto failed;
1286 }
1287 /* reset Tx rings */
1288 error = uath_reset_tx_queues(sc);
1289 if (error) {
1290 device_printf(sc->sc_dev,
1291 "could not reset Tx queues, error %d\n", error);
1292 goto failed;
1293 }
1294 /* set Tx rings WME properties */
1295 error = uath_wme_init(sc);
1296 if (error) {
1297 device_printf(sc->sc_dev,
1298 "could not init Tx queues, error %d\n", error);
1299 goto failed;
1300 }
1301 error = uath_set_ledstate(sc, 0);
1302 if (error) {
1303 device_printf(sc->sc_dev,
1304 "could not set led state, error %d\n", error);
1305 goto failed;
1306 }
1307 error = uath_flush(sc);
1308 if (error) {
1309 device_printf(sc->sc_dev,
1310 "could not flush pipes, error %d\n", error);
1311 goto failed;
1312 }
1313failed:
1314 return (error);
1315}
1316
1317static int
1318uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op)
1319{
1320 struct uath_cmd_rx_filter rxfilter;
1321
1322 rxfilter.bits = htobe32(bits);
1323 rxfilter.op = htobe32(op);
1324
1325 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
1326 "setting Rx filter=0x%x flags=0x%x\n", bits, op);
1327 return uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter,
1328 sizeof rxfilter, 0);
1329}
1330
1331static void
1332uath_watchdog(void *arg)
1333{
1334 struct uath_softc *sc = arg;
1335 struct ifnet *ifp = sc->sc_ifp;
1336
1337 if (sc->sc_tx_timer > 0) {
1338 if (--sc->sc_tx_timer == 0) {
1339 device_printf(sc->sc_dev, "device timeout\n");
1340 /*uath_init(ifp); XXX needs a process context! */
1341 ifp->if_oerrors++;
1342 return;
1343 }
1344 callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
1345 }
1346}
1347
1348static void
1349uath_abort_xfers(struct uath_softc *sc)
1350{
1351 int i;
1352
1353 UATH_ASSERT_LOCKED(sc);
1354 /* abort any pending transfers */
1355 for (i = 0; i < UATH_N_XFERS; i++)
1356 usb2_transfer_stop(sc->sc_xfer[i]);
1357}
1358
1359static int
1360uath_flush(struct uath_softc *sc)
1361{
1362 int error;
1363
1364 error = uath_dataflush(sc);
1365 if (error != 0)
1366 goto failed;
1367
1368 error = uath_cmdflush(sc);
1369 if (error != 0)
1370 goto failed;
1371
1372failed:
1373 return (error);
1374}
1375
1376static int
1377uath_cmdflush(struct uath_softc *sc)
1378{
1379
1380 return uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0);
1381}
1382
1383static int
1384uath_dataflush(struct uath_softc *sc)
1385{
1386 struct uath_data *data;
1387 struct uath_chunk *chunk;
1388 struct uath_tx_desc *desc;
1389
1390 UATH_ASSERT_LOCKED(sc);
1391
1392 data = uath_getbuf(sc);
1393 if (data == NULL)
1394 return (ENOBUFS);
1395 data->buflen = sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc);
1396 data->m = NULL;
1397 data->ni = NULL;
1398 chunk = (struct uath_chunk *)data->buf;
1399 desc = (struct uath_tx_desc *)(chunk + 1);
1400
1401 /* one chunk only */
1402 chunk->seqnum = 0;
1403 chunk->flags = UATH_CFLAGS_FINAL;
1404 chunk->length = htobe16(sizeof (struct uath_tx_desc));
1405
1406 bzero(desc, sizeof(struct uath_tx_desc));
1407 desc->msglen = htobe32(sizeof(struct uath_tx_desc));
1408 desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
1409 desc->type = htobe32(WDCMSG_FLUSH);
1410 desc->txqid = htobe32(0);
1411 desc->connid = htobe32(0);
1412 desc->flags = htobe32(0);
1413
1414#ifdef UATH_DEBUG
1415 if (sc->sc_debug & UATH_DEBUG_CMDS) {
1416 DPRINTF(sc, UATH_DEBUG_RESET, "send flush ix %d\n",
1417 desc->msgid);
1418 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
1419 uath_dump_cmd(data->buf, data->buflen, '+');
1420 }
1421#endif
1422
1423 STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
1424 UATH_STAT_INC(sc, st_tx_pending);
1425 sc->sc_tx_timer = 5;
1426 usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
1427
1428 return (0);
1429}
1430
1431static struct uath_data *
1432_uath_getbuf(struct uath_softc *sc)
1433{
1434 struct uath_data *bf;
1435
1436 bf = STAILQ_FIRST(&sc->sc_tx_inactive);
1437 if (bf != NULL) {
1438 STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
1439 UATH_STAT_DEC(sc, st_tx_inactive);
1440 } else
1441 bf = NULL;
1442 if (bf == NULL)
1443 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
1444 "out of xmit buffers");
1445 return (bf);
1446}
1447
1448static struct uath_data *
1449uath_getbuf(struct uath_softc *sc)
1450{
1451 struct uath_data *bf;
1452
1453 UATH_ASSERT_LOCKED(sc);
1454
1455 bf = _uath_getbuf(sc);
1456 if (bf == NULL) {
1457 struct ifnet *ifp = sc->sc_ifp;
1458
1459 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
1460 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1461 }
1462 return (bf);
1463}
1464
1465static int
1466uath_set_ledstate(struct uath_softc *sc, int connected)
1467{
1468
1469 DPRINTF(sc, UATH_DEBUG_LED,
1470 "set led state %sconnected\n", connected ? "" : "!");
1471 connected = htobe32(connected);
1472 return uath_cmd_write(sc, WDCMSG_SET_LED_STATE,
1473 &connected, sizeof connected, 0);
1474}
1475
1476static int
1477uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
1478{
1479#ifdef UATH_DEBUG
1480 struct ifnet *ifp = sc->sc_ifp;
1481 struct ieee80211com *ic = ifp->if_l2com;
1482#endif
1483 struct uath_cmd_reset reset;
1484
1485 bzero(&reset, sizeof reset);
1486 if (IEEE80211_IS_CHAN_2GHZ(c))
1487 reset.flags |= htobe32(UATH_CHAN_2GHZ);
1488 if (IEEE80211_IS_CHAN_5GHZ(c))
1489 reset.flags |= htobe32(UATH_CHAN_5GHZ);
1490 /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */
1491 if (IEEE80211_IS_CHAN_OFDM(c))
1492 reset.flags |= htobe32(UATH_CHAN_OFDM);
1493 else if (IEEE80211_IS_CHAN_CCK(c))
1494 reset.flags |= htobe32(UATH_CHAN_CCK);
1495 /* turbo can be used in either 2GHz or 5GHz */
1496 if (c->ic_flags & IEEE80211_CHAN_TURBO)
1497 reset.flags |= htobe32(UATH_CHAN_TURBO);
1498 reset.freq = htobe32(c->ic_freq);
1499 reset.maxrdpower = htobe32(50); /* XXX */
1500 reset.channelchange = htobe32(1);
1501 reset.keeprccontent = htobe32(0);
1502
1503 DPRINTF(sc, UATH_DEBUG_CHANNEL, "set channel %d, flags 0x%x freq %u\n",
1504 ieee80211_chan2ieee(ic, c),
1505 be32toh(reset.flags), be32toh(reset.freq));
1506 return uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof reset, 0);
1507}
1508
1509static int
1510uath_reset_tx_queues(struct uath_softc *sc)
1511{
1512 int ac, error;
1513
1514 DPRINTF(sc, UATH_DEBUG_RESET, "%s: reset Tx queues\n", __func__);
1515 for (ac = 0; ac < 4; ac++) {
1516 const uint32_t qid = htobe32(ac);
1517
1518 error = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid,
1519 sizeof qid, 0);
1520 if (error != 0)
1521 break;
1522 }
1523 return (error);
1524}
1525
1526static int
1527uath_wme_init(struct uath_softc *sc)
1528{
1529 /* XXX get from net80211 */
1530 static const struct uath_wme_settings uath_wme_11g[4] = {
1531 { 7, 4, 10, 0, 0 }, /* Background */
1532 { 3, 4, 10, 0, 0 }, /* Best-Effort */
1533 { 3, 3, 4, 26, 0 }, /* Video */
1534 { 2, 2, 3, 47, 0 } /* Voice */
1535 };
1536 struct uath_cmd_txq_setup qinfo;
1537 int ac, error;
1538
1539 DPRINTF(sc, UATH_DEBUG_WME, "%s: setup Tx queues\n", __func__);
1540 for (ac = 0; ac < 4; ac++) {
1541 qinfo.qid = htobe32(ac);
1542 qinfo.len = htobe32(sizeof(qinfo.attr));
1543 qinfo.attr.priority = htobe32(ac); /* XXX */
1544 qinfo.attr.aifs = htobe32(uath_wme_11g[ac].aifsn);
1545 qinfo.attr.logcwmin = htobe32(uath_wme_11g[ac].logcwmin);
1546 qinfo.attr.logcwmax = htobe32(uath_wme_11g[ac].logcwmax);
1547 qinfo.attr.bursttime = htobe32(UATH_TXOP_TO_US(
1548 uath_wme_11g[ac].txop));
1549 qinfo.attr.mode = htobe32(uath_wme_11g[ac].acm);/*XXX? */
1550 qinfo.attr.qflags = htobe32(1); /* XXX? */
1551
1552 error = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo,
1553 sizeof qinfo, 0);
1554 if (error != 0)
1555 break;
1556 }
1557 return (error);
1558}
1559
1560static int
1561uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1562{
1563 struct ieee80211com *ic = ifp->if_l2com;
1564 struct ifreq *ifr = (struct ifreq *) data;
1565 int error = 0, startall = 0;
1566
1567 switch (cmd) {
1568 case SIOCSIFFLAGS:
1569 if (ifp->if_flags & IFF_UP) {
1570 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1571 uath_init(ifp->if_softc);
1572 startall = 1;
1573 }
1574 } else {
1575 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1576 uath_stop(ifp);
1577 }
1578 if (startall)
1579 ieee80211_start_all(ic);
1580 break;
1581 case SIOCGIFMEDIA:
1582 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1583 break;
1584 case SIOCGIFADDR:
1585 error = ether_ioctl(ifp, cmd, data);
1586 break;
1587 default:
1588 error = EINVAL;
1589 break;
1590 }
1591
1592 return (error);
1593}
1594
1595static int
1596uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
1597 struct uath_data *data)
1598{
1599 struct ieee80211vap *vap = ni->ni_vap;
1600 struct uath_chunk *chunk;
1601 struct uath_tx_desc *desc;
1602 const struct ieee80211_frame *wh;
1603 struct ieee80211_key *k;
1604 int framelen, msglen;
1605
1606 UATH_ASSERT_LOCKED(sc);
1607
1608 data->ni = ni;
1609 data->m = m0;
1610 chunk = (struct uath_chunk *)data->buf;
1611 desc = (struct uath_tx_desc *)(chunk + 1);
1612
1613 if (ieee80211_radiotap_active_vap(vap)) {
1614 struct uath_tx_radiotap_header *tap = &sc->sc_txtap;
1615
1616 tap->wt_flags = 0;
1617 if (m0->m_flags & M_FRAG)
1618 tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
1619
1620 ieee80211_radiotap_tx(vap, m0);
1621 }
1622
1623 wh = mtod(m0, struct ieee80211_frame *);
1624 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1625 k = ieee80211_crypto_encap(ni, m0);
1626 if (k == NULL) {
1627 m_freem(m0);
1628 return (ENOBUFS);
1629 }
1630
1631 /* packet header may have moved, reset our local pointer */
1632 wh = mtod(m0, struct ieee80211_frame *);
1633 }
1634 m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1));
1635
1636 framelen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
1637 msglen = framelen + sizeof (struct uath_tx_desc);
1638 data->buflen = msglen + sizeof (struct uath_chunk);
1639
1640 /* one chunk only for now */
1641 chunk->seqnum = sc->sc_seqnum++;
1642 chunk->flags = (m0->m_flags & M_FRAG) ? 0 : UATH_CFLAGS_FINAL;
1643 if (m0->m_flags & M_LASTFRAG)
1644 chunk->flags |= UATH_CFLAGS_FINAL;
1645 chunk->flags = UATH_CFLAGS_FINAL;
1646 chunk->length = htobe16(msglen);
1647
1648 /* fill Tx descriptor */
1649 desc->msglen = htobe32(msglen);
1650 /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */
1651 desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
1652 desc->type = htobe32(WDCMSG_SEND);
1653 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1654 case IEEE80211_FC0_TYPE_CTL:
1655 case IEEE80211_FC0_TYPE_MGT:
1656 /* NB: force all management frames to highest queue */
1657 if (ni->ni_flags & IEEE80211_NODE_QOS) {
1658 /* NB: force all management frames to highest queue */
1659 desc->txqid = htobe32(WME_AC_VO | UATH_TXQID_MINRATE);
1660 } else
1661 desc->txqid = htobe32(WME_AC_BE | UATH_TXQID_MINRATE);
1662 break;
1663 case IEEE80211_FC0_TYPE_DATA:
1664 /* XXX multicast frames should honor mcastrate */
1665 desc->txqid = htobe32(M_WME_GETAC(m0));
1666 break;
1667 default:
1668 device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
1669 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
1670 m_freem(m0);
1671 return (EIO);
1672 }
1673 if (vap->iv_state == IEEE80211_S_AUTH ||
1674 vap->iv_state == IEEE80211_S_ASSOC ||
1675 vap->iv_state == IEEE80211_S_RUN)
1676 desc->connid = htobe32(UATH_ID_BSS);
1677 else
1678 desc->connid = htobe32(UATH_ID_INVALID);
1679 desc->flags = htobe32(0 /* no UATH_TX_NOTIFY */);
1680 desc->buflen = htobe32(m0->m_pkthdr.len);
1681
1682#ifdef UATH_DEBUG
1683 DPRINTF(sc, UATH_DEBUG_XMIT,
1684 "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n",
1685 desc->msgid, framelen, msglen, be32toh(desc->connid),
1686 be32toh(desc->txqid));
1687 if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP)
1688 uath_dump_cmd(data->buf, data->buflen, '+');
1689#endif
1690
1691 STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
1692 UATH_STAT_INC(sc, st_tx_pending);
1693 usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
1694
1695 return (0);
1696}
1697
1698/*
1699 * Cleanup driver resources when we run out of buffers while processing
1700 * fragments; return the tx buffers allocated and drop node references.
1701 */
1702static void
1703uath_txfrag_cleanup(struct uath_softc *sc,
1704 uath_datahead *frags, struct ieee80211_node *ni)
1705{
1706 struct uath_data *bf, *next;
1707
1708 UATH_ASSERT_LOCKED(sc);
1709
1710 STAILQ_FOREACH_SAFE(bf, frags, next, next) {
1711 /* NB: bf assumed clean */
1712 STAILQ_REMOVE_HEAD(frags, next);
1713 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1714 UATH_STAT_INC(sc, st_tx_inactive);
1715 ieee80211_node_decref(ni);
1716 }
1717}
1718
1719/*
1720 * Setup xmit of a fragmented frame. Allocate a buffer for each frag and bump
1721 * the node reference count to reflect the held reference to be setup by
1722 * uath_tx_start.
1723 */
1724static int
1725uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags,
1726 struct mbuf *m0, struct ieee80211_node *ni)
1727{
1728 struct mbuf *m;
1729 struct uath_data *bf;
1730
1731 UATH_ASSERT_LOCKED(sc);
1732 for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) {
1733 bf = uath_getbuf(sc);
1734 if (bf == NULL) { /* out of buffers, cleanup */
1735 uath_txfrag_cleanup(sc, frags, ni);
1736 break;
1737 }
1738 ieee80211_node_incref(ni);
1739 STAILQ_INSERT_TAIL(frags, bf, next);
1740 }
1741
1742 return !STAILQ_EMPTY(frags);
1743}
1744
1745/*
1746 * Reclaim mbuf resources. For fragmented frames we need to claim each frag
1747 * chained with m_nextpkt.
1748 */
1749static void
1750uath_freetx(struct mbuf *m)
1751{
1752 struct mbuf *next;
1753
1754 do {
1755 next = m->m_nextpkt;
1756 m->m_nextpkt = NULL;
1757 m_freem(m);
1758 } while ((m = next) != NULL);
1759}
1760
1761static void
1762uath_start(struct ifnet *ifp)
1763{
1764 struct uath_data *bf;
1765 struct uath_softc *sc = ifp->if_softc;
1766 struct ieee80211_node *ni;
1767 struct mbuf *m, *next;
1768 uath_datahead frags;
1769
1770 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
1771 (sc->sc_flags & UATH_FLAG_INVALID))
1772 return;
1773
1774 UATH_LOCK(sc);
1775 for (;;) {
1776 bf = uath_getbuf(sc);
1777 if (bf == NULL)
1778 break;
1779
1780 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1781 if (m == NULL) {
1782 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1783 UATH_STAT_INC(sc, st_tx_inactive);
1784 break;
1785 }
1786 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
1787 m->m_pkthdr.rcvif = NULL;
1788
1789 /*
1790 * Check for fragmentation. If this frame has been broken up
1791 * verify we have enough buffers to send all the fragments
1792 * so all go out or none...
1793 */
1794 STAILQ_INIT(&frags);
1795 if ((m->m_flags & M_FRAG) &&
1796 !uath_txfrag_setup(sc, &frags, m, ni)) {
1797 DPRINTF(sc, UATH_DEBUG_XMIT,
1798 "%s: out of txfrag buffers\n", __func__);
1799 uath_freetx(m);
1800 goto bad;
1801 }
1802 sc->sc_seqnum = 0;
1803 nextfrag:
1804 /*
1805 * Pass the frame to the h/w for transmission.
1806 * Fragmented frames have each frag chained together
1807 * with m_nextpkt. We know there are sufficient uath_data's
1808 * to send all the frags because of work done by
1809 * uath_txfrag_setup.
1810 */
1811 next = m->m_nextpkt;
1812 if (uath_tx_start(sc, m, ni, bf) != 0) {
1813 bad:
1814 ifp->if_oerrors++;
1815 reclaim:
1816 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1817 UATH_STAT_INC(sc, st_tx_inactive);
1818 uath_txfrag_cleanup(sc, &frags, ni);
1819 ieee80211_free_node(ni);
1820 continue;
1821 }
1822
1823 if (next != NULL) {
1824 /*
1825 * Beware of state changing between frags.
1826 XXX check sta power-save state?
1827 */
1828 if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
1829 DPRINTF(sc, UATH_DEBUG_XMIT,
1830 "%s: flush fragmented packet, state %s\n",
1831 __func__,
1832 ieee80211_state_name[ni->ni_vap->iv_state]);
1833 uath_freetx(next);
1834 goto reclaim;
1835 }
1836 m = next;
1837 bf = STAILQ_FIRST(&frags);
1838 KASSERT(bf != NULL, ("no buf for txfrag"));
1839 STAILQ_REMOVE_HEAD(&frags, next);
1840 goto nextfrag;
1841 }
1842
1843 sc->sc_tx_timer = 5;
1844 }
1845 UATH_UNLOCK(sc);
1846}
1847
1848static int
1849uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1850 const struct ieee80211_bpf_params *params)
1851{
1852 struct ieee80211com *ic = ni->ni_ic;
1853 struct ifnet *ifp = ic->ic_ifp;
1854 struct uath_data *bf;
1855 struct uath_softc *sc = ifp->if_softc;
1856
1857 /* prevent management frames from being sent if we're not ready */
1858 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1859 m_freem(m);
1860 ieee80211_free_node(ni);
1861 return (ENETDOWN);
1862 }
1863
1864 UATH_LOCK(sc);
1865 /* grab a TX buffer */
1866 bf = uath_getbuf(sc);
1867 if (bf == NULL) {
1868 ieee80211_free_node(ni);
1869 m_freem(m);
1870 UATH_UNLOCK(sc);
1871 return (ENOBUFS);
1872 }
1873
1874 sc->sc_seqnum = 0;
1875 if (uath_tx_start(sc, m, ni, bf) != 0) {
1876 ieee80211_free_node(ni);
1877 ifp->if_oerrors++;
1878 STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
1879 UATH_STAT_INC(sc, st_tx_inactive);
1880 UATH_UNLOCK(sc);
1881 return (EIO);
1882 }
1883 UATH_UNLOCK(sc);
1884
1885 sc->sc_tx_timer = 5;
1886 return (0);
1887}
1888
1889static void
1890uath_scan_start(struct ieee80211com *ic)
1891{
1892 /* do nothing */
1893}
1894
1895static void
1896uath_scan_end(struct ieee80211com *ic)
1897{
1898 /* do nothing */
1899}
1900
1901static void
1902uath_set_channel(struct ieee80211com *ic)
1903{
1904 struct ifnet *ifp = ic->ic_ifp;
1905 struct uath_softc *sc = ifp->if_softc;
1906
1907 UATH_LOCK(sc);
1908 (void)uath_switch_channel(sc, ic->ic_curchan);
1909 UATH_UNLOCK(sc);
1910}
1911
1912static int
1913uath_set_rxmulti_filter(struct uath_softc *sc)
1914{
1915 /* XXX broken */
1916 return (0);
1917}
1918static void
1919uath_update_mcast(struct ifnet *ifp)
1920{
1921 struct uath_softc *sc = ifp->if_softc;
1922
1923 UATH_LOCK(sc);
1924 /*
1925 * this is for avoiding the race condition when we're try to
1926 * connect to the AP with WPA.
1927 */
1928 if (sc->sc_flags & UATH_FLAG_INITDONE)
1929 (void)uath_set_rxmulti_filter(sc);
1930 UATH_UNLOCK(sc);
1931}
1932
1933static void
1934uath_update_promisc(struct ifnet *ifp)
1935{
1936 struct uath_softc *sc = ifp->if_softc;
1937
1938 UATH_LOCK(sc);
1939 if (sc->sc_flags & UATH_FLAG_INITDONE) {
1940 uath_set_rxfilter(sc,
1941 UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
1942 UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON |
1943 UATH_FILTER_RX_PROM, UATH_FILTER_OP_SET);
1944 }
1945 UATH_UNLOCK(sc);
1946}
1947
1948static int
1949uath_create_connection(struct uath_softc *sc, uint32_t connid)
1950{
1951 const struct ieee80211_rateset *rs;
1952 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
1953 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1954 struct ieee80211_node *ni = vap->iv_bss;
1955 struct uath_cmd_create_connection create;
1956
1957 bzero(&create, sizeof create);
1958 create.connid = htobe32(connid);
1959 create.bssid = htobe32(0);
1960 /* XXX packed or not? */
1961 create.size = htobe32(sizeof(struct uath_cmd_rateset));
1962
1963 rs = &ni->ni_rates;
1964 create.connattr.rateset.length = rs->rs_nrates;
1965 bcopy(rs->rs_rates, &create.connattr.rateset.set[0],
1966 rs->rs_nrates);
1967
1968 /* XXX turbo */
1969 if (IEEE80211_IS_CHAN_A(ni->ni_chan))
1970 create.connattr.wlanmode = htobe32(WLAN_MODE_11a);
1971 else if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan))
1972 create.connattr.wlanmode = htobe32(WLAN_MODE_11g);
1973 else
1974 create.connattr.wlanmode = htobe32(WLAN_MODE_11b);
1975
1976 return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create,
1977 sizeof create, 0);
1978}
1979
1980static int
1981uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
1982{
1983 struct uath_cmd_rates rates;
1984
1985 bzero(&rates, sizeof rates);
1986 rates.connid = htobe32(UATH_ID_BSS); /* XXX */
1987 rates.size = htobe32(sizeof(struct uath_cmd_rateset));
1988 /* XXX bounds check rs->rs_nrates */
1989 rates.rateset.length = rs->rs_nrates;
1990 bcopy(rs->rs_rates, &rates.rateset.set[0], rs->rs_nrates);
1991
1992 DPRINTF(sc, UATH_DEBUG_RATES,
1993 "setting supported rates nrates=%d\n", rs->rs_nrates);
1994 return uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE,
1995 &rates, sizeof rates, 0);
1996}
1997
1998static int
1999uath_write_associd(struct uath_softc *sc)
2000{
2001 struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2002 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2003 struct ieee80211_node *ni = vap->iv_bss;
2004 struct uath_cmd_set_associd associd;
2005
2006 bzero(&associd, sizeof associd);
2007 associd.defaultrateix = htobe32(1); /* XXX */
2008 associd.associd = htobe32(ni->ni_associd);
2009 associd.timoffset = htobe32(0x3b); /* XXX */
2010 IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid);
2011 return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd,
2012 sizeof associd, 0);
2013}
2014
2015static int
2016uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode)
2017{
2018 struct uath_cmd_ledsteady led;
2019
2020 led.lednum = htobe32(lednum);
2021 led.ledmode = htobe32(ledmode);
2022
2023 DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (steady)\n",
2024 (lednum == UATH_LED_LINK) ? "link" : "activity",
2025 ledmode ? "on" : "off");
2026 return uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof led, 0);
2027}
2028
2029static int
2030uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode,
2031 int blinkrate, int slowmode)
2032{
2033 struct uath_cmd_ledblink led;
2034
2035 led.lednum = htobe32(lednum);
2036 led.ledmode = htobe32(ledmode);
2037 led.blinkrate = htobe32(blinkrate);
2038 led.slowmode = htobe32(slowmode);
2039
2040 DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (blink)\n",
2041 (lednum == UATH_LED_LINK) ? "link" : "activity",
2042 ledmode ? "on" : "off");
2043 return uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, &led, sizeof led, 0);
2044}
2045
2046static int
2047uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
2048{
2049 enum ieee80211_state ostate = vap->iv_state;
2050 int error;
2051 struct ieee80211_node *ni = vap->iv_bss;
2052 struct ieee80211com *ic = vap->iv_ic;
2053 struct uath_softc *sc = ic->ic_ifp->if_softc;
2054 struct uath_vap *uvp = UATH_VAP(vap);
2055
2056 DPRINTF(sc, UATH_DEBUG_STATE,
2057 "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state],
2058 ieee80211_state_name[nstate]);
2059
2060 IEEE80211_UNLOCK(ic);
2061 UATH_LOCK(sc);
2062 callout_stop(&sc->stat_ch);
2063 callout_stop(&sc->watchdog_ch);
2064
2065 switch (nstate) {
2066 case IEEE80211_S_INIT:
2067 if (ostate == IEEE80211_S_RUN) {
2068 /* turn link and activity LEDs off */
2069 uath_set_ledstate(sc, 0);
2070 }
2071 break;
2072
2073 case IEEE80211_S_SCAN:
2074 break;
2075
2076 case IEEE80211_S_AUTH:
2077 /* XXX good place? set RTS threshold */
2078 uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold);
2079 /* XXX bad place */
2080 error = uath_set_keys(sc, vap);
2081 if (error != 0) {
2082 device_printf(sc->sc_dev,
2083 "could not set crypto keys, error %d\n", error);
2084 break;
2085 }
2086 if (uath_switch_channel(sc, ni->ni_chan) != 0) {
2087 device_printf(sc->sc_dev, "could not switch channel\n");
2088 break;
2089 }
2090 if (uath_create_connection(sc, UATH_ID_BSS) != 0) {
2091 device_printf(sc->sc_dev,
2092 "could not create connection\n");
2093 break;
2094 }
2095 break;
2096
2097 case IEEE80211_S_ASSOC:
2098 if (uath_set_rates(sc, &ni->ni_rates) != 0) {
2099 device_printf(sc->sc_dev,
2100 "could not set negotiated rate set\n");
2101 break;
2102 }
2103 break;
2104
2105 case IEEE80211_S_RUN:
2106 /* XXX monitor mode doesn't be tested */
2107 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2108 uath_set_ledstate(sc, 1);
2109 break;
2110 }
2111
2112 /*
2113 * Tx rate is controlled by firmware, report the maximum
2114 * negotiated rate in ifconfig output.
2115 */
2116 ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1];
2117
2118 if (uath_write_associd(sc) != 0) {
2119 device_printf(sc->sc_dev,
2120 "could not write association id\n");
2121 break;
2122 }
2123 /* turn link LED on */
2124 uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON);
2125 /* make activity LED blink */
2126 uath_set_ledblink(sc, UATH_LED_ACTIVITY, UATH_LED_ON, 1, 2);
2127 /* set state to associated */
2128 uath_set_ledstate(sc, 1);
2129
2130 /* start statistics timer */
2131 callout_reset(&sc->stat_ch, hz, uath_stat, sc);
2132 break;
2133 default:
2134 break;
2135 }
2136 UATH_UNLOCK(sc);
2137 IEEE80211_LOCK(ic);
2138 return (uvp->newstate(vap, nstate, arg));
2139}
2140
2141static int
2142uath_set_key(struct uath_softc *sc, const struct ieee80211_key *wk,
2143 int index)
2144{
2145#if 0
2146 struct uath_cmd_crypto crypto;
2147 int i;
2148
2149 bzero(&crypto, sizeof crypto);
2150 crypto.keyidx = htobe32(index);
2151 crypto.magic1 = htobe32(1);
2152 crypto.size = htobe32(368);
2153 crypto.mask = htobe32(0xffff);
2154 crypto.flags = htobe32(0x80000068);
2155 if (index != UATH_DEFAULT_KEY)
2156 crypto.flags |= htobe32(index << 16);
2157 memset(crypto.magic2, 0xff, sizeof crypto.magic2);
2158
2159 /*
2160 * Each byte of the key must be XOR'ed with 10101010 before being
2161 * transmitted to the firmware.
2162 */
2163 for (i = 0; i < wk->wk_keylen; i++)
2164 crypto.key[i] = wk->wk_key[i] ^ 0xaa;
2165
2166 DPRINTF(sc, UATH_DEBUG_CRYPTO,
2167 "setting crypto key index=%d len=%d\n", index, wk->wk_keylen);
2168 return uath_cmd_write(sc, WDCMSG_SET_KEY_CACHE_ENTRY, &crypto,
2169 sizeof crypto, 0);
2170#else
2171 /* XXX support H/W cryto */
2172 return (0);
2173#endif
2174}
2175
2176static int
2177uath_set_keys(struct uath_softc *sc, struct ieee80211vap *vap)
2178{
2179 int i, error;
2180
2181 error = 0;
2182 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2183 const struct ieee80211_key *wk = &vap->iv_nw_keys[i];
2184
2185 if (wk->wk_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV)) {
2186 error = uath_set_key(sc, wk, i);
2187 if (error)
2188 return (error);
2189 }
2190 }
2191 if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) {
2192 error = uath_set_key(sc, &vap->iv_nw_keys[vap->iv_def_txkey],
2193 UATH_DEFAULT_KEY);
2194 }
2195 return (error);
2196}
2197
2198#define UATH_SYSCTL_STAT_ADD32(c, h, n, p, d) \
2199 SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
2200
2201static void
2202uath_sysctl_node(struct uath_softc *sc)
2203{
2204 struct sysctl_ctx_list *ctx;
2205 struct sysctl_oid_list *child;
2206 struct sysctl_oid *tree;
2207 struct uath_stat *stats;
2208
2209 stats = &sc->sc_stat;
2210 ctx = device_get_sysctl_ctx(sc->sc_dev);
2211 child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev));
2212
2213 tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
2214 NULL, "UATH statistics");
2215 child = SYSCTL_CHILDREN(tree);
2216 UATH_SYSCTL_STAT_ADD32(ctx, child, "badchunkseqnum",
2217 &stats->st_badchunkseqnum, "Bad chunk sequence numbers");
2218 UATH_SYSCTL_STAT_ADD32(ctx, child, "invalidlen", &stats->st_invalidlen,
2219 "Invalid length");
2220 UATH_SYSCTL_STAT_ADD32(ctx, child, "multichunk", &stats->st_multichunk,
2221 "Multi chunks");
2222 UATH_SYSCTL_STAT_ADD32(ctx, child, "toobigrxpkt",
2223 &stats->st_toobigrxpkt, "Too big rx packets");
2224 UATH_SYSCTL_STAT_ADD32(ctx, child, "stopinprogress",
2225 &stats->st_stopinprogress, "Stop in progress");
2226 UATH_SYSCTL_STAT_ADD32(ctx, child, "crcerrs", &stats->st_crcerr,
2227 "CRC errors");
2228 UATH_SYSCTL_STAT_ADD32(ctx, child, "phyerr", &stats->st_phyerr,
2229 "PHY errors");
2230 UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_crcerr",
2231 &stats->st_decrypt_crcerr, "Decryption CRC errors");
2232 UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_micerr",
2233 &stats->st_decrypt_micerr, "Decryption Misc errors");
2234 UATH_SYSCTL_STAT_ADD32(ctx, child, "decomperr", &stats->st_decomperr,
2235 "Decomp errors");
2236 UATH_SYSCTL_STAT_ADD32(ctx, child, "keyerr", &stats->st_keyerr,
2237 "Key errors");
2238 UATH_SYSCTL_STAT_ADD32(ctx, child, "err", &stats->st_err,
2239 "Unknown errors");
2240
2241 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_active",
2242 &stats->st_cmd_active, "Active numbers in Command queue");
2243 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_inactive",
2244 &stats->st_cmd_inactive, "Inactive numbers in Command queue");
2245 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_pending",
2246 &stats->st_cmd_pending, "Pending numbers in Command queue");
2247 UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_waiting",
2248 &stats->st_cmd_waiting, "Waiting numbers in Command queue");
2249 UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_active",
2250 &stats->st_rx_active, "Active numbers in RX queue");
2251 UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_inactive",
2252 &stats->st_rx_inactive, "Inactive numbers in RX queue");
2253 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_active",
2254 &stats->st_tx_active, "Active numbers in TX queue");
2255 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive",
2256 &stats->st_tx_inactive, "Inactive numbers in TX queue");
2257 UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_pending",
2258 &stats->st_tx_pending, "Pending numbers in TX queue");
2259}
2260
2261#undef UATH_SYSCTL_STAT_ADD32
2262
2263static void
2264uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
2265{
2266 struct uath_cmd_hdr *hdr;
2267 int dlen;
2268
2269 hdr = (struct uath_cmd_hdr *)cmd->buf;
2270 /* NB: msgid is passed thru w/o byte swapping */
2271#ifdef UATH_DEBUG
2272 if (sc->sc_debug & UATH_DEBUG_CMDS) {
2273 int len = be32toh(hdr->len);
2274 printf("%s: %s [ix %u] len %u status %u\n",
2275 __func__, uath_codename(be32toh(hdr->code)),
2276 hdr->msgid, len, be32toh(hdr->magic));
2277 if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
2278 uath_dump_cmd(cmd->buf,
2279 len > UATH_MAX_CMDSZ ? sizeof(*hdr) : len, '-');
2280 }
2281#endif
2282 hdr->code = be32toh(hdr->code);
2283 hdr->len = be32toh(hdr->len);
2284 hdr->magic = be32toh(hdr->magic); /* target status on return */
2285
2286 switch (hdr->code & 0xff) {
2287 /* reply to a read command */
2288 default:
2289 dlen = hdr->len - sizeof(*hdr);
2290 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2291 "%s: code %d data len %u\n",
2292 __func__, hdr->code & 0xff, dlen);
2293 /*
2294 * The first response from the target after the
2295 * HOST_AVAILABLE has an invalid msgid so we must
2296 * treat it specially.
2297 */
2298 if (hdr->msgid < UATH_CMD_LIST_COUNT) {
2299 uint32_t *rp = (uint32_t *)(hdr+1);
2300 u_int olen;
2301
2302 if (!(sizeof(*hdr) <= hdr->len &&
2303 hdr->len < UATH_MAX_CMDSZ)) {
2304 device_printf(sc->sc_dev,
2305 "%s: invalid WDC msg length %u; "
2306 "msg ignored\n", __func__, hdr->len);
2307 return;
2308 }
2309 /*
2310 * Calculate return/receive payload size; the
2311 * first word, if present, always gives the
2312 * number of bytes--unless it's 0 in which
2313 * case a single 32-bit word should be present.
2314 */
2315 if (dlen >= sizeof(uint32_t)) {
2316 olen = be32toh(rp[0]);
2317 dlen -= sizeof(uint32_t);
2318 if (olen == 0) {
2319 /* convention is 0 =>'s one word */
2320 olen = sizeof(uint32_t);
2321 /* XXX KASSERT(olen == dlen ) */
2322 }
2323 } else
2324 olen = 0;
2325 if (cmd->odata != NULL) {
2326 /* NB: cmd->olen validated in uath_cmd */
2327 if (olen > cmd->olen) {
2328 /* XXX complain? */
2329 device_printf(sc->sc_dev,
2330 "%s: cmd 0x%x olen %u cmd olen %u\n",
2331 __func__, hdr->code, olen,
2332 cmd->olen);
2333 olen = cmd->olen;
2334 }
2335 if (olen > dlen) {
2336 /* XXX complain, shouldn't happen */
2337 device_printf(sc->sc_dev,
2338 "%s: cmd 0x%x olen %u dlen %u\n",
2339 __func__, hdr->code, olen, dlen);
2340 olen = dlen;
2341 }
2342 /* XXX have submitter do this */
2343 /* copy answer into caller's supplied buffer */
2344 bcopy(&rp[1], cmd->odata, olen);
2345 cmd->olen = olen;
2346 }
2347 }
2348 wakeup_one(cmd); /* wake up caller */
2349 break;
2350
2351 case WDCMSG_TARGET_START:
2352 if (hdr->msgid >= UATH_CMD_LIST_COUNT) {
2353 /* XXX */
2354 return;
2355 }
2356 dlen = hdr->len - sizeof(*hdr);
2357 if (dlen != sizeof(uint32_t)) {
2358 /* XXX something wrong */
2359 return;
2360 }
2361 /* XXX have submitter do this */
2362 /* copy answer into caller's supplied buffer */
2363 bcopy(hdr+1, cmd->odata, sizeof(uint32_t));
2364 cmd->olen = sizeof(uint32_t);
2365 wakeup_one(cmd); /* wake up caller */
2366 break;
2367
2368 case WDCMSG_SEND_COMPLETE:
2369 /* this notification is sent when UATH_TX_NOTIFY is set */
2370 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2371 "%s: received Tx notification\n", __func__);
2372 break;
2373
2374 case WDCMSG_TARGET_GET_STATS:
2375 DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
2376 "%s: received device statistics\n", __func__);
2377 callout_reset(&sc->stat_ch, hz, uath_stat, sc);
2378 break;
2379 }
2380}
2381
2382static void
2383uath_intr_rx_callback(struct usb2_xfer *xfer)
2384{
2385 struct uath_softc *sc = xfer->priv_sc;
2386 struct uath_cmd *cmd;
2387
2388 UATH_ASSERT_LOCKED(sc);
2389
2390 switch (USB_GET_STATE(xfer)) {
2391 case USB_ST_TRANSFERRED:
2392 cmd = STAILQ_FIRST(&sc->sc_cmd_waiting);
2393 if (cmd == NULL)
2394 goto setup;
2395 STAILQ_REMOVE_HEAD(&sc->sc_cmd_waiting, next);
2396 UATH_STAT_DEC(sc, st_cmd_waiting);
2397 STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
2398 UATH_STAT_INC(sc, st_cmd_inactive);
2399
2400 KASSERT(xfer->actlen >= sizeof(struct uath_cmd_hdr),
2401 ("short xfer error"));
2402 usb2_copy_out(xfer->frbuffers, 0, cmd->buf, xfer->actlen);
2403 uath_cmdeof(sc, cmd);
2404 case USB_ST_SETUP:
2405setup:
2406 xfer->frlengths[0] = xfer->max_data_length;
2407 usb2_start_hardware(xfer);
2408 break;
2409 default:
2410 if (xfer->error != USB_ERR_CANCELLED) {
2411 xfer->flags.stall_pipe = 1;
2412 goto setup;
2413 }
2414 break;
2415 }
2416}
2417
2418static void
2419uath_intr_tx_callback(struct usb2_xfer *xfer)
2420{
2421 struct uath_softc *sc = xfer->priv_sc;
2422 struct uath_cmd *cmd;
2423
2424 UATH_ASSERT_LOCKED(sc);
2425
2426 switch (USB_GET_STATE(xfer)) {
2427 case USB_ST_TRANSFERRED:
2428 cmd = STAILQ_FIRST(&sc->sc_cmd_active);
2429 if (cmd == NULL)
2430 goto setup;
2431 STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next);
2432 UATH_STAT_DEC(sc, st_cmd_active);
2433 STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ?
2434 &sc->sc_cmd_waiting : &sc->sc_cmd_inactive, cmd, next);
2435 if (cmd->flags & UATH_CMD_FLAG_READ)
2436 UATH_STAT_INC(sc, st_cmd_waiting);
2437 else
2438 UATH_STAT_INC(sc, st_cmd_inactive);
2439 /* FALLTHROUGH */
2440 case USB_ST_SETUP:
2441setup:
2442 cmd = STAILQ_FIRST(&sc->sc_cmd_pending);
2443 if (cmd == NULL) {
2444 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
2445 __func__);
2446 return;
2447 }
2448 STAILQ_REMOVE_HEAD(&sc->sc_cmd_pending, next);
2449 UATH_STAT_DEC(sc, st_cmd_pending);
2450 STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_ASYNC) ?
2451 &sc->sc_cmd_inactive : &sc->sc_cmd_active, cmd, next);
2452 if (cmd->flags & UATH_CMD_FLAG_ASYNC)
2453 UATH_STAT_INC(sc, st_cmd_inactive);
2454 else
2455 UATH_STAT_INC(sc, st_cmd_active);
2456
2457 usb2_set_frame_data(xfer, cmd->buf, 0);
2458 xfer->frlengths[0] = cmd->buflen;
2459 usb2_start_hardware(xfer);
2460 break;
2461 default:
2462 if (xfer->error != USB_ERR_CANCELLED) {
2463 xfer->flags.stall_pipe = 1;
2464 goto setup;
2465 }
2466 break;
2467 }
2468}
2469
2470static void
2471uath_update_rxstat(struct uath_softc *sc, uint32_t status)
2472{
2473
2474 switch (status) {
2475 case UATH_STATUS_STOP_IN_PROGRESS:
2476 UATH_STAT_INC(sc, st_stopinprogress);
2477 break;
2478 case UATH_STATUS_CRC_ERR:
2479 UATH_STAT_INC(sc, st_crcerr);
2480 break;
2481 case UATH_STATUS_PHY_ERR:
2482 UATH_STAT_INC(sc, st_phyerr);
2483 break;
2484 case UATH_STATUS_DECRYPT_CRC_ERR:
2485 UATH_STAT_INC(sc, st_decrypt_crcerr);
2486 break;
2487 case UATH_STATUS_DECRYPT_MIC_ERR:
2488 UATH_STAT_INC(sc, st_decrypt_micerr);
2489 break;
2490 case UATH_STATUS_DECOMP_ERR:
2491 UATH_STAT_INC(sc, st_decomperr);
2492 break;
2493 case UATH_STATUS_KEY_ERR:
2494 UATH_STAT_INC(sc, st_keyerr);
2495 break;
2496 case UATH_STATUS_ERR:
2497 UATH_STAT_INC(sc, st_err);
2498 break;
2499 default:
2500 break;
2501 }
2502}
2503
2504static struct mbuf *
2505uath_data_rxeof(struct usb2_xfer *xfer, struct uath_data *data,
2506 struct uath_rx_desc **pdesc)
2507{
2508 struct uath_softc *sc = xfer->priv_sc;
2509 struct ifnet *ifp = sc->sc_ifp;
2510 struct ieee80211com *ic = ifp->if_l2com;
2511 struct uath_chunk *chunk;
2512 struct uath_rx_desc *desc;
2513 struct mbuf *m = data->m, *mnew, *mp;
2514 uint16_t chunklen;
2515
2516 if (xfer->actlen < UATH_MIN_RXBUFSZ) {
2517 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2518 "%s: wrong xfer size (len=%d)\n", __func__, xfer->actlen);
2519 ifp->if_ierrors++;
2520 return (NULL);
2521 }
2522
2523 chunk = (struct uath_chunk *)data->buf;
2524 if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
2525 device_printf(sc->sc_dev, "%s: strange response\n", __func__);
2526 ifp->if_ierrors++;
2527 UATH_RESET_INTRX(sc);
2528 return (NULL);
2529 }
2530
2531 if (chunk->seqnum != sc->sc_intrx_nextnum) {
2532 DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
2533 chunk->seqnum, sc->sc_intrx_nextnum);
2534 UATH_STAT_INC(sc, st_badchunkseqnum);
2535 if (sc->sc_intrx_head != NULL)
2536 m_freem(sc->sc_intrx_head);
2537 UATH_RESET_INTRX(sc);
2538 return (NULL);
2539 }
2540
2541 /* check multi-chunk frames */
2542 if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) ||
2543 (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) ||
2544 chunk->flags & UATH_CFLAGS_RXMSG)
2545 UATH_STAT_INC(sc, st_multichunk);
2546
2547 chunklen = be16toh(chunk->length);
2548 if (chunk->flags & UATH_CFLAGS_FINAL)
2549 chunklen -= sizeof(struct uath_rx_desc);
2550
2551 if (chunklen > 0 &&
2552 (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
2553 /* we should use intermediate RX buffer */
2554 if (chunk->seqnum == 0)
2555 UATH_RESET_INTRX(sc);
2556 if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
2557 chunklen) > UATH_MAX_INTRX_SIZE) {
2558 UATH_STAT_INC(sc, st_invalidlen);
2559 ifp->if_iqdrops++;
2560 if (sc->sc_intrx_head != NULL)
2561 m_freem(sc->sc_intrx_head);
2562 UATH_RESET_INTRX(sc);
2563 return (NULL);
2564 }
2565
2566 m->m_len = chunklen;
2567 m->m_data += sizeof(struct uath_chunk);
2568
2569 if (sc->sc_intrx_head == NULL) {
2570 sc->sc_intrx_head = m;
2571 sc->sc_intrx_tail = m;
2572 } else {
2573 m->m_flags &= ~M_PKTHDR;
2574 sc->sc_intrx_tail->m_next = m;
2575 sc->sc_intrx_tail = m;
2576 }
2577 }
2578 sc->sc_intrx_len += chunklen;
2579
2580 mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2581 if (mnew == NULL) {
2582 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2583 "%s: can't get new mbuf, drop frame\n", __func__);
2584 ifp->if_ierrors++;
2585 if (sc->sc_intrx_head != NULL)
2586 m_freem(sc->sc_intrx_head);
2587 UATH_RESET_INTRX(sc);
2588 return (NULL);
2589 }
2590
2591 data->m = mnew;
2592 data->buf = mtod(mnew, uint8_t *);
2593
2594 /* if the frame is not final continue the transfer */
2595 if (!(chunk->flags & UATH_CFLAGS_FINAL)) {
2596 sc->sc_intrx_nextnum++;
2597 UATH_RESET_INTRX(sc);
2598 return (NULL);
2599 }
2600
2601 /*
2602 * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is
2603 * located at the end, 32-bit aligned
2604 */
2605 desc = (chunk->flags & UATH_CFLAGS_RXMSG) ?
2606 (struct uath_rx_desc *)(chunk + 1) :
2607 (struct uath_rx_desc *)(((uint8_t *)chunk) +
2608 sizeof(struct uath_chunk) + be16toh(chunk->length) -
2609 sizeof(struct uath_rx_desc));
2610 *pdesc = desc;
2611
2612 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2613 "%s: frame len %u code %u status %u rate %u antenna %u "
2614 "rssi %d channel %u phyerror %u connix %u decrypterror %u "
2615 "keycachemiss %u\n", __func__, be32toh(desc->framelen)
2616 , be32toh(desc->code), be32toh(desc->status), be32toh(desc->rate)
2617 , be32toh(desc->antenna), be32toh(desc->rssi), be32toh(desc->channel)
2618 , be32toh(desc->phyerror), be32toh(desc->connix)
2619 , be32toh(desc->decrypterror), be32toh(desc->keycachemiss));
2620
2621 if (be32toh(desc->len) > MCLBYTES) {
2622 DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
2623 "%s: bad descriptor (len=%d)\n", __func__,
2624 be32toh(desc->len));
2625 ifp->if_iqdrops++;
2626 UATH_STAT_INC(sc, st_toobigrxpkt);
2627 if (sc->sc_intrx_head != NULL)
2628 m_freem(sc->sc_intrx_head);
2629 UATH_RESET_INTRX(sc);
2630 return (NULL);
2631 }
2632
2633 uath_update_rxstat(sc, be32toh(desc->status));
2634
2635 /* finalize mbuf */
2636 if (sc->sc_intrx_head == NULL) {
2637 m->m_pkthdr.rcvif = ifp;
2638 m->m_pkthdr.len = m->m_len =
2639 be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
2640 m->m_data += sizeof(struct uath_chunk);
2641 } else {
2642 mp = sc->sc_intrx_head;
2643 mp->m_pkthdr.rcvif = ifp;
2644 mp->m_flags |= M_PKTHDR;
2645 mp->m_pkthdr.len = sc->sc_intrx_len;
2646 m = mp;
2647 }
2648
2649 /* there are a lot more fields in the RX descriptor */
2650 if (ieee80211_radiotap_active(ic)) {
2651 struct uath_rx_radiotap_header *tap = &sc->sc_rxtap;
2652 uint32_t tsf_hi = be32toh(desc->tstamp_high);
2653 uint32_t tsf_lo = be32toh(desc->tstamp_low);
2654
2655 /* XXX only get low order 24bits of tsf from h/w */
2656 tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
2657 tap->wr_flags = 0;
2658 if (be32toh(desc->status) == UATH_STATUS_CRC_ERR)
2659 tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
2660 /* XXX map other status to BADFCS? */
2661 /* XXX ath h/w rate code, need to map */
2662 tap->wr_rate = be32toh(desc->rate);
2663 tap->wr_antenna = be32toh(desc->antenna);
2664 tap->wr_antsignal = -95 + be32toh(desc->rssi);
2665 tap->wr_antnoise = -95;
2666 }
2667
2668 ifp->if_ipackets++;
2669 UATH_RESET_INTRX(sc);
2670
2671 return (m);
2672}
2673
2674static void
2675uath_bulk_rx_callback(struct usb2_xfer *xfer)
2676{
2677 struct uath_softc *sc = xfer->priv_sc;
2678 struct ifnet *ifp = sc->sc_ifp;
2679 struct ieee80211com *ic = ifp->if_l2com;
2680 struct ieee80211_frame *wh;
2681 struct ieee80211_node *ni;
2682 struct mbuf *m = NULL;
2683 struct uath_data *data;
2684 struct uath_rx_desc *desc = NULL;
2685 int8_t nf;
2686
2687 UATH_ASSERT_LOCKED(sc);
2688
2689 switch (USB_GET_STATE(xfer)) {
2690 case USB_ST_TRANSFERRED:
2691 data = STAILQ_FIRST(&sc->sc_rx_active);
2692 if (data == NULL)
2693 goto setup;
2694 STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
2695 UATH_STAT_DEC(sc, st_rx_active);
2696 m = uath_data_rxeof(xfer, data, &desc);
2697 STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
2698 UATH_STAT_INC(sc, st_rx_inactive);
2699 /* FALLTHROUGH */
2700 case USB_ST_SETUP:
2701setup:
2702 data = STAILQ_FIRST(&sc->sc_rx_inactive);
2703 if (data == NULL)
2704 return;
2705 STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
2706 UATH_STAT_DEC(sc, st_rx_inactive);
2707 STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
2708 UATH_STAT_INC(sc, st_rx_active);
2709 usb2_set_frame_data(xfer, data->buf, 0);
2710 xfer->frlengths[0] = xfer->max_data_length;
2711 usb2_start_hardware(xfer);
2712
2713 /*
2714 * To avoid LOR we should unlock our private mutex here to call
2715 * ieee80211_input() because here is at the end of a USB
2716 * callback and safe to unlock.
2717 */
2718 UATH_UNLOCK(sc);
2719 if (m != NULL && desc != NULL) {
2720 wh = mtod(m, struct ieee80211_frame *);
2721 ni = ieee80211_find_rxnode(ic,
2722 (struct ieee80211_frame_min *)wh);
2723 nf = -95; /* XXX */
2724 if (ni != NULL) {
2725 (void) ieee80211_input(ni, m,
2726 (int)be32toh(desc->rssi), nf);
2727 /* node is no longer needed */
2728 ieee80211_free_node(ni);
2729 } else
2730 (void) ieee80211_input_all(ic, m,
2731 (int)be32toh(desc->rssi), nf);
2732 m = NULL;
2733 desc = NULL;
2734 }
2735 UATH_LOCK(sc);
2736 break;
2737 default:
2738 /* needs it to the inactive queue due to a error. */
2739 data = STAILQ_FIRST(&sc->sc_rx_active);
2740 if (data != NULL) {
2741 STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
2742 UATH_STAT_DEC(sc, st_rx_active);
2743 STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
2744 UATH_STAT_INC(sc, st_rx_inactive);
2745 }
2746 if (xfer->error != USB_ERR_CANCELLED) {
2747 xfer->flags.stall_pipe = 1;
2748 ifp->if_ierrors++;
2749 goto setup;
2750 }
2751 break;
2752 }
2753}
2754
2755static void
2756uath_data_txeof(struct usb2_xfer *xfer, struct uath_data *data)
2757{
2758 struct uath_softc *sc = xfer->priv_sc;
2759 struct ifnet *ifp = sc->sc_ifp;
2760 struct mbuf *m;
2761
2762 UATH_ASSERT_LOCKED(sc);
2763
2764 /*
2765 * Do any tx complete callback. Note this must be done before releasing
2766 * the node reference.
2767 */
2768 if (data->m) {
2769 m = data->m;
2770 if (m->m_flags & M_TXCB) {
2771 /* XXX status? */
2772 ieee80211_process_callback(data->ni, m, 0);
2773 }
2774 m_freem(m);
2775 data->m = NULL;
2776 }
2777 if (data->ni) {
2778 ieee80211_free_node(data->ni);
2779 data->ni = NULL;
2780 }
2781 sc->sc_tx_timer = 0;
2782 ifp->if_opackets++;
2783 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2784}
2785
2786static void
2787uath_bulk_tx_callback(struct usb2_xfer *xfer)
2788{
2789 struct uath_softc *sc = xfer->priv_sc;
2790 struct ifnet *ifp = sc->sc_ifp;
2791 struct uath_data *data;
2792
2793 UATH_ASSERT_LOCKED(sc);
2794
2795 switch (USB_GET_STATE(xfer)) {
2796 case USB_ST_TRANSFERRED:
2797 data = STAILQ_FIRST(&sc->sc_tx_active);
2798 if (data == NULL)
2799 goto setup;
2800 STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next);
2801 UATH_STAT_DEC(sc, st_tx_active);
2802 uath_data_txeof(xfer, data);
2803 STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
2804 UATH_STAT_INC(sc, st_tx_inactive);
2805 /* FALLTHROUGH */
2806 case USB_ST_SETUP:
2807setup:
2808 data = STAILQ_FIRST(&sc->sc_tx_pending);
2809 if (data == NULL) {
2810 DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
2811 __func__);
2812 return;
2813 }
2814 STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
2815 UATH_STAT_DEC(sc, st_tx_pending);
2816 STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
2817 UATH_STAT_INC(sc, st_tx_active);
2818
2819 usb2_set_frame_data(xfer, data->buf, 0);
2820 xfer->frlengths[0] = data->buflen;
2821 usb2_start_hardware(xfer);
2822
2823 UATH_UNLOCK(sc);
2824 uath_start(ifp);
2825 UATH_LOCK(sc);
2826 break;
2827 default:
2828 data = STAILQ_FIRST(&sc->sc_tx_active);
2829 if (data == NULL)
2830 goto setup;
2831 if (data->ni != NULL) {
2832 ieee80211_free_node(data->ni);
2833 data->ni = NULL;
2834 ifp->if_oerrors++;
2835 }
2836 if (xfer->error != USB_ERR_CANCELLED) {
2837 xfer->flags.stall_pipe = 1;
2838 goto setup;
2839 }
2840 break;
2841 }
2842}
2843
2844static device_method_t uath_methods[] = {
2845 DEVMETHOD(device_probe, uath_match),
2846 DEVMETHOD(device_attach, uath_attach),
2847 DEVMETHOD(device_detach, uath_detach),
2848 { 0, 0 }
2849};
2850static driver_t uath_driver = {
2851 "uath",
2852 uath_methods,
2853 sizeof(struct uath_softc)
2854};
2855static devclass_t uath_devclass;
2856
2857DRIVER_MODULE(uath, uhub, uath_driver, uath_devclass, NULL, 0);
2858MODULE_DEPEND(uath, wlan, 1, 1, 1);
2859MODULE_DEPEND(uath, usb, 1, 1, 1);