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