Bug Summary

File:dev/ic/acx.c
Warning:line 972, column 4
Value stored to 'eh' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name acx.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/ic/acx.c
1/* $OpenBSD: acx.c,v 1.126 2022/01/09 05:42:38 jsg Exp $ */
2
3/*
4 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
21 *
22 * This code is derived from software contributed to The DragonFly Project
23 * by Sepherosa Ziehau <sepherosa@gmail.com>
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 *
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in
33 * the documentation and/or other materials provided with the
34 * distribution.
35 * 3. Neither the name of The DragonFly Project nor the names of its
36 * contributors may be used to endorse or promote products derived
37 * from this software without specific, prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
42 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
43 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
44 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
45 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
47 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 */
52
53/*
54 * Copyright (c) 2003-2004 wlan.kewl.org Project
55 * All rights reserved.
56 *
57 * Redistribution and use in source and binary forms, with or without
58 * modification, are permitted provided that the following conditions
59 * are met:
60 *
61 * 1. Redistributions of source code must retain the above copyright
62 * notice, this list of conditions and the following disclaimer.
63 *
64 * 2. Redistributions in binary form must reproduce the above copyright
65 * notice, this list of conditions and the following disclaimer in the
66 * documentation and/or other materials provided with the distribution.
67 *
68 * 3. All advertising materials mentioning features or use of this software
69 * must display the following acknowledgement:
70 *
71 * This product includes software developed by the wlan.kewl.org Project.
72 *
73 * 4. Neither the name of the wlan.kewl.org Project nor the names of its
74 * contributors may be used to endorse or promote products derived from
75 * this software without specific prior written permission.
76 *
77 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
78 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
79 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
80 * THE wlan.kewl.org Project BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
81 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
82 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
83 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
84 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
85 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
86 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
87 */
88
89#include "bpfilter.h"
90
91#include <sys/param.h>
92#include <sys/systm.h>
93#include <sys/kernel.h>
94#include <sys/malloc.h>
95#include <sys/mbuf.h>
96#include <sys/socket.h>
97#include <sys/sockio.h>
98#include <sys/ioctl.h>
99#include <sys/errno.h>
100#include <sys/device.h>
101#include <sys/endian.h>
102
103#include <machine/bus.h>
104#include <machine/intr.h>
105
106#include <net/if.h>
107#include <net/if_media.h>
108
109#if NBPFILTER1 > 0
110#include <net/bpf.h>
111#endif
112
113#include <netinet/in.h>
114#include <netinet/if_ether.h>
115
116#include <net80211/ieee80211_var.h>
117#include <net80211/ieee80211_amrr.h>
118#include <net80211/ieee80211_radiotap.h>
119
120#include <dev/ic/acxvar.h>
121#include <dev/ic/acxreg.h>
122
123#ifdef ACX_DEBUG
124int acxdebug = 0;
125#endif
126
127int acx_attach(struct acx_softc *);
128int acx_detach(void *);
129
130int acx_init(struct ifnet *);
131int acx_stop(struct acx_softc *);
132void acx_init_info_reg(struct acx_softc *);
133int acx_config(struct acx_softc *);
134int acx_read_config(struct acx_softc *, struct acx_config *);
135int acx_write_config(struct acx_softc *, struct acx_config *);
136int acx_rx_config(struct acx_softc *);
137int acx_set_crypt_keys(struct acx_softc *);
138void acx_next_scan(void *);
139
140void acx_start(struct ifnet *);
141void acx_watchdog(struct ifnet *);
142
143int acx_ioctl(struct ifnet *, u_long, caddr_t);
144
145int acx_intr(void *);
146void acx_disable_intr(struct acx_softc *);
147void acx_enable_intr(struct acx_softc *);
148void acx_txeof(struct acx_softc *);
149void acx_txerr(struct acx_softc *, uint8_t);
150void acx_rxeof(struct acx_softc *);
151
152int acx_dma_alloc(struct acx_softc *);
153void acx_dma_free(struct acx_softc *);
154void acx_init_tx_ring(struct acx_softc *);
155int acx_init_rx_ring(struct acx_softc *);
156int acx_newbuf(struct acx_softc *, struct acx_rxbuf *, int);
157int acx_encap(struct acx_softc *, struct acx_txbuf *,
158 struct mbuf *, struct ieee80211_node *, int);
159
160int acx_reset(struct acx_softc *);
161
162int acx_set_null_tmplt(struct acx_softc *);
163int acx_set_probe_req_tmplt(struct acx_softc *, const char *, int);
164#ifndef IEEE80211_STA_ONLY
165int acx_set_probe_resp_tmplt(struct acx_softc *, struct ieee80211_node *);
166int acx_beacon_locate(struct mbuf *, u_int8_t);
167int acx_set_beacon_tmplt(struct acx_softc *, struct ieee80211_node *);
168#endif
169
170int acx_read_eeprom(struct acx_softc *, uint32_t, uint8_t *);
171int acx_read_phyreg(struct acx_softc *, uint32_t, uint8_t *);
172const char * acx_get_rf(int);
173int acx_get_maxrssi(int);
174
175int acx_load_firmware(struct acx_softc *, uint32_t,
176 const uint8_t *, int);
177int acx_load_radio_firmware(struct acx_softc *, const char *);
178int acx_load_base_firmware(struct acx_softc *, const char *);
179
180struct ieee80211_node
181 *acx_node_alloc(struct ieee80211com *);
182int acx_newstate(struct ieee80211com *, enum ieee80211_state, int);
183
184void acx_init_cmd_reg(struct acx_softc *);
185int acx_join_bss(struct acx_softc *, uint8_t, struct ieee80211_node *);
186int acx_set_channel(struct acx_softc *, uint8_t);
187int acx_init_radio(struct acx_softc *, uint32_t, uint32_t);
188
189void acx_iter_func(void *, struct ieee80211_node *);
190void acx_amrr_timeout(void *);
191void acx_newassoc(struct ieee80211com *, struct ieee80211_node *, int);
192#ifndef IEEE80211_STA_ONLY
193void acx_set_tim(struct ieee80211com *, int, int);
194#endif
195
196int acx_beacon_intvl = 100; /* 100 TU */
197
198/*
199 * Possible values for the second parameter of acx_join_bss()
200 */
201#define ACX_MODE_ADHOC0 0
202#define ACX_MODE_UNUSED1 1
203#define ACX_MODE_STA2 2
204#define ACX_MODE_AP3 3
205
206struct cfdriver acx_cd = {
207 NULL((void *)0), "acx", DV_IFNET
208};
209
210int
211acx_attach(struct acx_softc *sc)
212{
213 struct ieee80211com *ic = &sc->sc_ic;
214 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
215 int i, error;
216
217 /* Initialize channel scanning timer */
218 timeout_set(&sc->sc_chanscan_timer, acx_next_scan, sc);
219
220 /* Allocate busdma stuffs */
221 error = acx_dma_alloc(sc);
222 if (error) {
223 printf("%s: attach failed, could not allocate DMA!\n",
224 sc->sc_dev.dv_xname);
225 return (error);
226 }
227
228 /* Reset Hardware */
229 error = acx_reset(sc);
230 if (error) {
231 printf("%s: attach failed, could not reset device!\n",
232 sc->sc_dev.dv_xname);
233 return (error);
234 }
235
236 /* Disable interrupts before firmware is loaded */
237 acx_disable_intr(sc);
238
239 /* Get radio type and form factor */
240#define EEINFO_RETRY_MAX 50
241 for (i = 0; i < EEINFO_RETRY_MAX; ++i) {
242 uint16_t ee_info;
243
244 ee_info = CSR_READ_2(sc, ACXREG_EEPROM_INFO)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(18)])))
;
245 if (ACX_EEINFO_HAS_RADIO_TYPE(ee_info)((ee_info) & (0xff << 8))) {
246 sc->sc_form_factor = ACX_EEINFO_FORM_FACTOR(ee_info)((ee_info) & 0xff);
247 sc->sc_radio_type = ACX_EEINFO_RADIO_TYPE(ee_info)((ee_info) >> 8);
248 break;
249 }
250 DELAY(10000)(*delay_func)(10000);
251 }
252 if (i == EEINFO_RETRY_MAX) {
253 printf("%s: attach failed, could not get radio type!\n",
254 sc->sc_dev.dv_xname);
255 return (ENXIO6);
256 }
257#undef EEINFO_RETRY_MAX
258
259#ifdef DUMP_EEPROM
260 for (i = 0; i < 0x40; ++i) {
261 uint8_t val;
262
263 error = acx_read_eeprom(sc, i, &val);
264 if (error)
265 return (error);
266 if (i % 10 == 0)
267 printf("\n");
268 printf("%02x ", val);
269 }
270 printf("\n");
271#endif /* DUMP_EEPROM */
272
273 /* Get EEPROM version */
274 error = acx_read_eeprom(sc, ACX_EE_VERSION_OFS0x05, &sc->sc_eeprom_ver);
275 if (error) {
276 printf("%s: attach failed, could not get EEPROM version!\n",
277 sc->sc_dev.dv_xname);
278 return (error);
279 }
280
281 ifp->if_softc = sc;
282 ifp->if_ioctl = acx_ioctl;
283 ifp->if_start = acx_start;
284 ifp->if_watchdog = acx_watchdog;
285 ifp->if_flags = IFF_SIMPLEX0x800 | IFF_BROADCAST0x2 | IFF_MULTICAST0x8000;
286 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ16);
287 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN)((&ifp->if_snd)->ifq_maxlen = (256));
288
289 /* Set channels */
290 for (i = 1; i <= 14; ++i) {
291 ic->ic_channels[i].ic_freq =
292 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080);
293 ic->ic_channels[i].ic_flags = sc->chip_chan_flags;
294 }
295
296 ic->ic_opmode = IEEE80211_M_STA;
297 ic->ic_state = IEEE80211_S_INIT;
298
299 /*
300 * NOTE: Don't overwrite ic_caps set by chip specific code
301 */
302 ic->ic_caps =
303 IEEE80211_C_WEP0x00000001 | /* WEP */
304 IEEE80211_C_MONITOR0x00000200 | /* Monitor mode */
305#ifndef IEEE80211_STA_ONLY
306 IEEE80211_C_IBSS0x00000002 | /* IBSS mode */
307 IEEE80211_C_HOSTAP0x00000008 | /* Access Point */
308 IEEE80211_C_APPMGT0x00000020 | /* AP Power Mgmt */
309#endif
310 IEEE80211_C_SHPREAMBLE0x00000100; /* Short preamble */
311
312 /* Get station id */
313 for (i = 0; i < IEEE80211_ADDR_LEN6; ++i) {
314 error = acx_read_eeprom(sc, sc->chip_ee_eaddr_ofs - i,
315 &ic->ic_myaddr[i]);
316 if (error) {
317 printf("%s: attach failed, could not get station id\n",
318 sc->sc_dev.dv_xname);
319 return error;
320 }
321 }
322
323 printf("%s: %s, radio %s (0x%02x), EEPROM ver %u, address %s\n",
324 sc->sc_dev.dv_xname,
325 (sc->sc_flags & ACX_FLAG_ACX1110x02) ? "ACX111" : "ACX100",
326 acx_get_rf(sc->sc_radio_type), sc->sc_radio_type,
327 sc->sc_eeprom_ver, ether_sprintf(ic->ic_myaddr));
328
329 if_attach(ifp);
330 ieee80211_ifattach(ifp);
331
332 /* Override node alloc */
333 ic->ic_node_alloc = acx_node_alloc;
334 ic->ic_newassoc = acx_newassoc;
335
336#ifndef IEEE80211_STA_ONLY
337 /* Override set TIM */
338 ic->ic_set_tim = acx_set_tim;
339#endif
340
341 /* Override newstate */
342 sc->sc_newstate = ic->ic_newstate;
343 ic->ic_newstate = acx_newstate;
344
345 /* Set maximal rssi */
346 ic->ic_max_rssi = acx_get_maxrssi(sc->sc_radio_type);
347
348 ieee80211_media_init(ifp, ieee80211_media_change,
349 ieee80211_media_status);
350
351 /* AMRR rate control */
352 sc->amrr.amrr_min_success_threshold = 1;
353 sc->amrr.amrr_max_success_threshold = 15;
354 timeout_set(&sc->amrr_ch, acx_amrr_timeout, sc);
355
356 sc->sc_long_retry_limit = 4;
357 sc->sc_short_retry_limit = 7;
358 sc->sc_msdu_lifetime = 4096;
359
360#if NBPFILTER1 > 0
361 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
362 sizeof(struct ieee80211_frame) + 64);
363
364 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
365 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
366 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(ACX_RX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_RSSI
))))
;
367
368 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
369 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
370 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(ACX_TX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL
))))
;
371#endif
372
373 return (0);
374}
375
376int
377acx_detach(void *xsc)
378{
379 struct acx_softc *sc = xsc;
380 struct ieee80211com *ic = &sc->sc_ic;
381 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
382
383 acx_stop(sc);
384 ieee80211_ifdetach(ifp);
385 if_detach(ifp);
386
387 acx_dma_free(sc);
388
389 return (0);
390}
391
392int
393acx_init(struct ifnet *ifp)
394{
395 struct acx_softc *sc = ifp->if_softc;
396 struct ieee80211com *ic = &sc->sc_ic;
397 char fname[] = "tiacx111c16";
398 int error, combined = 0;
399
400 error = acx_stop(sc);
401 if (error)
402 return (EIO5);
403
404 /* enable card if possible */
405 if (sc->sc_enable != NULL((void *)0)) {
406 error = (*sc->sc_enable)(sc);
407 if (error)
408 return (EIO5);
409 }
410
411 acx_init_tx_ring(sc);
412
413 error = acx_init_rx_ring(sc);
414 if (error) {
415 printf("%s: can't initialize RX ring\n",
416 sc->sc_dev.dv_xname);
417 goto back;
418 }
419
420 if (sc->sc_flags & ACX_FLAG_ACX1110x02) {
421 snprintf(fname, sizeof(fname), "tiacx111c%02X",
422 sc->sc_radio_type);
423 error = acx_load_base_firmware(sc, fname);
424
425 if (!error)
426 combined = 1;
427 }
428
429 if (!combined) {
430 snprintf(fname, sizeof(fname), "tiacx%s",
431 (sc->sc_flags & ACX_FLAG_ACX1110x02) ? "111" : "100");
432 error = acx_load_base_firmware(sc, fname);
433 }
434
435 if (error)
436 goto back;
437
438 /*
439 * Initialize command and information registers
440 * NOTE: This should be done after base firmware is loaded
441 */
442 acx_init_cmd_reg(sc);
443 acx_init_info_reg(sc);
444
445 sc->sc_flags |= ACX_FLAG_FW_LOADED0x01;
446
447 if (!combined) {
448 snprintf(fname, sizeof(fname), "tiacx%sr%02X",
449 (sc->sc_flags & ACX_FLAG_ACX1110x02) ? "111" : "100",
450 sc->sc_radio_type);
451 error = acx_load_radio_firmware(sc, fname);
452
453 if (error)
454 goto back;
455 }
456
457 error = sc->chip_init(sc);
458 if (error)
459 goto back;
460
461 /* Get and set device various configuration */
462 error = acx_config(sc);
463 if (error)
464 goto back;
465
466 /* Setup crypto stuffs */
467 if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON0x00000100) {
468 error = acx_set_crypt_keys(sc);
469 if (error)
470 goto back;
471 }
472
473 /* Turn on power led */
474 CSR_CLRB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled)((((sc))->sc_mem1_bt)->write_2((((sc))->sc_mem1_bh),
(((sc))->chip_ioreg[((23))]), (((((sc))->sc_mem1_bt)->
read_2((((sc))->sc_mem1_bh), (((sc))->chip_ioreg[((23))
]))) & (~(sc->chip_gpio_pled)))))
;
475
476 acx_enable_intr(sc);
477
478 ifp->if_flags |= IFF_RUNNING0x40;
479 ifq_clr_oactive(&ifp->if_snd);
480
481 if (ic->ic_opmode != IEEE80211_M_MONITOR)
482 /* start background scanning */
483 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
484 else
485 /* in monitor mode change directly into run state */
486 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
487
488 return (0);
489back:
490 acx_stop(sc);
491 return (error);
492}
493
494void
495acx_init_info_reg(struct acx_softc *sc)
496{
497 sc->sc_info = CSR_READ_4(sc, ACXREG_INFO_REG_OFFSET)(((sc)->sc_mem1_bt)->read_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(25)])))
;
498 sc->sc_info_param = sc->sc_info + ACX_INFO_REG_SIZE4;
499}
500
501int
502acx_set_crypt_keys(struct acx_softc *sc)
503{
504 struct ieee80211com *ic = &sc->sc_ic;
505 struct acx_conf_wep_txkey wep_txkey;
506 int i, error, got_wk = 0;
507
508 for (i = 0; i < IEEE80211_WEP_NKID4; ++i) {
509 struct ieee80211_key *k = &ic->ic_nw_keys[i];
510
511 if (k->k_len == 0)
512 continue;
513
514 if (sc->chip_hw_crypt) {
515 error = sc->chip_set_wepkey(sc, k, i);
516 if (error)
517 return (error);
518 got_wk = 1;
519 }
520 }
521
522 if (!got_wk)
523 return (0);
524
525 /* Set current WEP key index */
526 wep_txkey.wep_txkey = ic->ic_wep_txkeyic_def_txkey;
527 if (acx_set_conf(sc, ACX_CONF_WEP_TXKEY0x1010, &wep_txkey,
528 sizeof(wep_txkey)) != 0) {
529 printf("%s: set WEP txkey failed\n", sc->sc_dev.dv_xname);
530 return (ENXIO6);
531 }
532
533 return (0);
534}
535
536void
537acx_next_scan(void *arg)
538{
539 struct acx_softc *sc = arg;
540 struct ieee80211com *ic = &sc->sc_ic;
541 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
542
543 if (ic->ic_state == IEEE80211_S_SCAN)
544 ieee80211_next_scan(ifp);
545}
546
547int
548acx_stop(struct acx_softc *sc)
549{
550 struct ieee80211com *ic = &sc->sc_ic;
551 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
552 struct acx_buf_data *bd = &sc->sc_buf_data;
553 struct acx_ring_data *rd = &sc->sc_ring_data;
554 int i, error;
555
556 sc->sc_firmware_ver = 0;
557 sc->sc_hardware_id = 0;
558
559 /* Reset hardware */
560 error = acx_reset(sc);
561 if (error)
562 return (error);
563
564 /* Firmware no longer functions after hardware reset */
565 sc->sc_flags &= ~ACX_FLAG_FW_LOADED0x01;
566
567 acx_disable_intr(sc);
568
569 /* Stop background scanning */
570 timeout_del(&sc->sc_chanscan_timer);
571
572 /* Turn off power led */
573 CSR_SETB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled)((((sc))->sc_mem1_bt)->write_2((((sc))->sc_mem1_bh),
(((sc))->chip_ioreg[((23))]), (((((sc))->sc_mem1_bt)->
read_2((((sc))->sc_mem1_bh), (((sc))->chip_ioreg[((23))
]))) | (sc->chip_gpio_pled))))
;
574
575 /* Free TX mbuf */
576 for (i = 0; i < ACX_TX_DESC_CNT16; ++i) {
577 struct acx_txbuf *buf;
578 struct ieee80211_node *ni;
579
580 buf = &bd->tx_buf[i];
581
582 if (buf->tb_mbuf != NULL((void *)0)) {
583 bus_dmamap_unload(sc->sc_dmat, buf->tb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (buf
->tb_mbuf_dmamap))
;
584 m_freem(buf->tb_mbuf);
585 buf->tb_mbuf = NULL((void *)0);
586 }
587
588 ni = (struct ieee80211_node *)buf->tb_node;
589 if (ni != NULL((void *)0))
590 ieee80211_release_node(ic, ni);
591 buf->tb_node = NULL((void *)0);
592 }
593
594 /* Clear TX host descriptors */
595 bzero(rd->tx_ring, ACX_TX_RING_SIZE)__builtin_bzero((rd->tx_ring), ((2 * 16 * sizeof(struct acx_host_desc
))))
;
596
597 /* Free RX mbuf */
598 for (i = 0; i < ACX_RX_DESC_CNT16; ++i) {
599 if (bd->rx_buf[i].rb_mbuf != NULL((void *)0)) {
600 bus_dmamap_unload(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
rx_buf[i].rb_mbuf_dmamap))
601 bd->rx_buf[i].rb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
rx_buf[i].rb_mbuf_dmamap))
;
602 m_freem(bd->rx_buf[i].rb_mbuf);
603 bd->rx_buf[i].rb_mbuf = NULL((void *)0);
604 }
605 }
606
607 /* Clear RX host descriptors */
608 bzero(rd->rx_ring, ACX_RX_RING_SIZE)__builtin_bzero((rd->rx_ring), ((16 * sizeof(struct acx_host_desc
))))
;
609
610 sc->sc_txtimer = 0;
611 ifp->if_timer = 0;
612 ifp->if_flags &= ~IFF_RUNNING0x40;
613 ifq_clr_oactive(&ifp->if_snd);
614 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1)(((&sc->sc_ic)->ic_newstate)((&sc->sc_ic), (
IEEE80211_S_INIT), (-1)))
;
615
616 /* disable card if possible */
617 if (sc->sc_disable != NULL((void *)0))
618 (*sc->sc_disable)(sc);
619
620 return (0);
621}
622
623int
624acx_config(struct acx_softc *sc)
625{
626 struct acx_config conf;
627 int error;
628
629 error = acx_read_config(sc, &conf);
630 if (error)
631 return (error);
632
633 error = acx_write_config(sc, &conf);
634 if (error)
635 return (error);
636
637 error = acx_rx_config(sc);
638 if (error)
639 return (error);
640
641 if (acx_set_probe_req_tmplt(sc, "", 0) != 0) {
642 printf("%s: can't set probe req template "
643 "(empty ssid)\n", sc->sc_dev.dv_xname);
644 return (ENXIO6);
645 }
646
647 /* XXX for PM?? */
648 if (acx_set_null_tmplt(sc) != 0) {
649 printf("%s: can't set null data template\n",
650 sc->sc_dev.dv_xname);
651 return (ENXIO6);
652 }
653
654 return (0);
655}
656
657int
658acx_read_config(struct acx_softc *sc, struct acx_config *conf)
659{
660 struct acx_conf_regdom reg_dom;
661 struct acx_conf_antenna ant;
662 struct acx_conf_fwrev fw_rev;
663 uint32_t fw_rev_no;
664 uint8_t sen;
665 int error;
666
667 /* Get region domain */
668 if (acx_get_conf(sc, ACX_CONF_REGDOM0x100a, &reg_dom, sizeof(reg_dom)) != 0) {
669 printf("%s: can't get region domain\n", sc->sc_dev.dv_xname);
670 return (ENXIO6);
671 }
672 conf->regdom = reg_dom.regdom;
673 DPRINTF(("%s: regdom %02x\n", sc->sc_dev.dv_xname, reg_dom.regdom));
674
675 /* Get antenna */
676 if (acx_get_conf(sc, ACX_CONF_ANTENNA0x100b, &ant, sizeof(ant)) != 0) {
677 printf("%s: can't get antenna\n", sc->sc_dev.dv_xname);
678 return (ENXIO6);
679 }
680 conf->antenna = ant.antenna;
681 DPRINTF(("%s: antenna %02x\n", sc->sc_dev.dv_xname, ant.antenna));
682
683 /* Get sensitivity XXX not used */
684 if (sc->sc_radio_type == ACX_RADIO_TYPE_MAXIM0x0d ||
685 sc->sc_radio_type == ACX_RADIO_TYPE_RFMD0x11 ||
686 sc->sc_radio_type == ACX_RADIO_TYPE_RALINK0x15) {
687 error = acx_read_phyreg(sc, ACXRV_PHYREG_SENSITIVITY0x30, &sen);
688 if (error) {
689 printf("%s: can't get sensitivity\n",
690 sc->sc_dev.dv_xname);
691 return (error);
692 }
693 } else
694 sen = 0;
695 DPRINTF(("%s: sensitivity %02x\n", sc->sc_dev.dv_xname, sen));
696
697 /* Get firmware revision */
698 if (acx_get_conf(sc, ACX_CONF_FWREV0x000d, &fw_rev, sizeof(fw_rev)) != 0) {
699 printf("%s: can't get firmware revision\n",
700 sc->sc_dev.dv_xname);
701 return (ENXIO6);
702 }
703
704 if (strncmp(fw_rev.fw_rev, "Rev ", 4) != 0) {
705 printf("%s: strange revision string -- %s\n",
706 sc->sc_dev.dv_xname, fw_rev.fw_rev);
707 fw_rev_no = 0x01090407;
708 } else {
709 /*
710 * 01234
711 * "Rev xx.xx.xx.xx"
712 * ^ Start from here
713 */
714 fw_rev_no = fw_rev.fw_rev[0] << 24;
715 fw_rev_no |= fw_rev.fw_rev[1] << 16;
716 fw_rev_no |= fw_rev.fw_rev[2] << 8;
717 fw_rev_no |= fw_rev.fw_rev[3];
718 }
719 sc->sc_firmware_ver = fw_rev_no;
720 sc->sc_hardware_id = letoh32(fw_rev.hw_id)((__uint32_t)(fw_rev.hw_id));
721 DPRINTF(("%s: fw rev %08x, hw id %08x\n",
722 sc->sc_dev.dv_xname, sc->sc_firmware_ver, sc->sc_hardware_id));
723
724 if (sc->chip_read_config != NULL((void *)0)) {
725 error = sc->chip_read_config(sc, conf);
726 if (error)
727 return (error);
728 }
729
730 return (0);
731}
732
733int
734acx_write_config(struct acx_softc *sc, struct acx_config *conf)
735{
736 struct acx_conf_nretry_short sretry;
737 struct acx_conf_nretry_long lretry;
738 struct acx_conf_msdu_lifetime msdu_lifetime;
739 struct acx_conf_rate_fallback rate_fb;
740 struct acx_conf_antenna ant;
741 struct acx_conf_regdom reg_dom;
742 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
743 int error;
744
745 /* Set number of long/short retry */
746 sretry.nretry = sc->sc_short_retry_limit;
747 if (acx_set_conf(sc, ACX_CONF_NRETRY_SHORT0x1005, &sretry,
748 sizeof(sretry)) != 0) {
749 printf("%s: can't set short retry limit\n", ifp->if_xname);
750 return (ENXIO6);
751 }
752
753 lretry.nretry = sc->sc_long_retry_limit;
754 if (acx_set_conf(sc, ACX_CONF_NRETRY_LONG0x1006, &lretry,
755 sizeof(lretry)) != 0) {
756 printf("%s: can't set long retry limit\n", ifp->if_xname);
757 return (ENXIO6);
758 }
759
760 /* Set MSDU lifetime */
761 msdu_lifetime.lifetime = htole32(sc->sc_msdu_lifetime)((__uint32_t)(sc->sc_msdu_lifetime));
762 if (acx_set_conf(sc, ACX_CONF_MSDU_LIFETIME0x1008, &msdu_lifetime,
763 sizeof(msdu_lifetime)) != 0) {
764 printf("%s: can't set MSDU lifetime\n", ifp->if_xname);
765 return (ENXIO6);
766 }
767
768 /* Enable rate fallback */
769 rate_fb.ratefb_enable = 1;
770 if (acx_set_conf(sc, ACX_CONF_RATE_FALLBACK0x0006, &rate_fb,
771 sizeof(rate_fb)) != 0) {
772 printf("%s: can't enable rate fallback\n", ifp->if_xname);
773 return (ENXIO6);
774 }
775
776 /* Set antenna */
777 ant.antenna = conf->antenna;
778 if (acx_set_conf(sc, ACX_CONF_ANTENNA0x100b, &ant, sizeof(ant)) != 0) {
779 printf("%s: can't set antenna\n", ifp->if_xname);
780 return (ENXIO6);
781 }
782
783 /* Set region domain */
784 reg_dom.regdom = conf->regdom;
785 if (acx_set_conf(sc, ACX_CONF_REGDOM0x100a, &reg_dom, sizeof(reg_dom)) != 0) {
786 printf("%s: can't set region domain\n", ifp->if_xname);
787 return (ENXIO6);
788 }
789
790 if (sc->chip_write_config != NULL((void *)0)) {
791 error = sc->chip_write_config(sc, conf);
792 if (error)
793 return (error);
794 }
795
796 return (0);
797}
798
799int
800acx_rx_config(struct acx_softc *sc)
801{
802 struct ieee80211com *ic = &sc->sc_ic;
803 struct acx_conf_rxopt rx_opt;
804
805 /* tell the RX receiver what frames we want to have */
806 rx_opt.opt1 = htole16(RXOPT1_INCL_RXBUF_HDR)((__uint16_t)(0x2000));
807 rx_opt.opt2 = htole16(((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
808 RXOPT2_RECV_ASSOC_REQ |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
809 RXOPT2_RECV_AUTH |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
810 RXOPT2_RECV_BEACON |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
811 RXOPT2_RECV_CF |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
812 RXOPT2_RECV_CTRL |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
813 RXOPT2_RECV_DATA |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
814 RXOPT2_RECV_MGMT |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
815 RXOPT2_RECV_PROBE_REQ |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
816 RXOPT2_RECV_PROBE_RESP |((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
817 RXOPT2_RECV_OTHER)((__uint16_t)(0x0800 | 0x0400 | 0x0200 | 0x0100 | 0x0080 | 0x0040
| 0x0010 | 0x0008 | 0x0004 | 0x0001))
;
818
819 /* in monitor mode go promiscuous */
820 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
821 rx_opt.opt1 |= RXOPT1_PROMISC0x0008;
822 rx_opt.opt2 |= RXOPT2_RECV_BROKEN0x0020 | RXOPT2_RECV_ACK0x0002;
823 } else
824 rx_opt.opt1 |= RXOPT1_FILT_FDEST0x0010;
825
826 /* finally set the RX options */
827 if (acx_set_conf(sc, ACX_CONF_RXOPT0x0010, &rx_opt, sizeof(rx_opt)) != 0) {
828 printf("%s: can not set RX options!\n", sc->sc_dev.dv_xname);
829 return (ENXIO6);
830 }
831
832 return (0);
833}
834
835int
836acx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
837{
838 struct acx_softc *sc = ifp->if_softc;
839 struct ieee80211com *ic = &sc->sc_ic;
840 int s, error = 0;
841 uint8_t chan;
842
843 s = splnet()splraise(0x7);
844
845 switch (cmd) {
846 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
847 ifp->if_flags |= IFF_UP0x1;
848 /* FALLTHROUGH */
849 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
850 if (ifp->if_flags & IFF_UP0x1) {
851 if ((ifp->if_flags & IFF_RUNNING0x40) == 0)
852 error = acx_init(ifp);
853 } else {
854 if (ifp->if_flags & IFF_RUNNING0x40)
855 error = acx_stop(sc);
856 }
857 break;
858 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
859 /* allow fast channel switching in monitor mode */
860 error = ieee80211_ioctl(ifp, cmd, data);
861 if (error == ENETRESET52 &&
862 ic->ic_opmode == IEEE80211_M_MONITOR) {
863 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
864 (IFF_UP0x1 | IFF_RUNNING0x40)) {
865 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
866 chan = ieee80211_chan2ieee(ic,
867 ic->ic_bss->ni_chan);
868 (void)acx_set_channel(sc, chan);
869 }
870 error = 0;
871 }
872 break;
873 default:
874 error = ieee80211_ioctl(ifp, cmd, data);
875 break;
876 }
877
878 if (error == ENETRESET52) {
879 if ((ifp->if_flags & (IFF_RUNNING0x40 | IFF_UP0x1)) ==
880 (IFF_RUNNING0x40 | IFF_UP0x1))
881 error = acx_init(ifp);
882 else
883 error = 0;
884 }
885
886 splx(s)spllower(s);
887
888 return (error);
889}
890
891void
892acx_start(struct ifnet *ifp)
893{
894 struct acx_softc *sc = ifp->if_softc;
895 struct ieee80211com *ic = &sc->sc_ic;
896 struct acx_buf_data *bd = &sc->sc_buf_data;
897 struct acx_txbuf *buf;
898 int trans, idx;
899
900 if ((sc->sc_flags & ACX_FLAG_FW_LOADED0x01) == 0 ||
901 (ifp->if_flags & IFF_RUNNING0x40) == 0 ||
902 ifq_is_oactive(&ifp->if_snd))
903 return;
904
905 /*
906 * NOTE:
907 * We can't start from a random position that TX descriptor
908 * is free, since hardware will be confused by that.
909 * We have to follow the order of the TX ring.
910 */
911 idx = bd->tx_free_start;
912 trans = 0;
913 for (buf = &bd->tx_buf[idx]; buf->tb_mbuf == NULL((void *)0);
914 buf = &bd->tx_buf[idx]) {
915 struct ieee80211_frame *wh;
916 struct ieee80211_node *ni = NULL((void *)0);
917 struct mbuf *m;
918 int rate;
919
920 m = mq_dequeue(&ic->ic_mgtq);
921 /* first dequeue management frames */
922 if (m != NULL((void *)0)) {
923 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
924
925 /*
926 * probe response mgmt frames are handled by the
927 * firmware already. So, don't send them twice.
928 */
929 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
930 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK0xf0) ==
931 IEEE80211_FC0_SUBTYPE_PROBE_RESP0x50) {
932 if (ni != NULL((void *)0))
933 ieee80211_release_node(ic, ni);
934 m_freem(m);
935 continue;
936 }
937
938 /*
939 * mgmt frames are sent at the lowest available
940 * bit-rate.
941 */
942 rate = ni->ni_rates.rs_rates[0];
943 rate &= IEEE80211_RATE_VAL0x7f;
944 } else {
945 struct ether_header *eh;
946
947 /* then dequeue packets on the powersave queue */
948 m = mq_dequeue(&ic->ic_pwrsaveq);
949 if (m != NULL((void *)0)) {
950 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
951 goto encapped;
952 } else {
953 m = ifq_dequeue(&ifp->if_snd);
954 if (m == NULL((void *)0))
955 break;
956 }
957 if (ic->ic_state != IEEE80211_S_RUN) {
958 DPRINTF(("%s: data packet dropped due to "
959 "not RUN. Current state %d\n",
960 ifp->if_xname, ic->ic_state));
961 m_freem(m);
962 break;
963 }
964
965 if (m->m_lenm_hdr.mh_len < sizeof(struct ether_header)) {
966 m = m_pullup(m, sizeof(struct ether_header));
967 if (m == NULL((void *)0)) {
968 ifp->if_oerrorsif_data.ifi_oerrors++;
969 continue;
970 }
971 }
972 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
Value stored to 'eh' is never read
973
974 /* TODO power save */
975
976#if NBPFILTER1 > 0
977 if (ifp->if_bpf != NULL((void *)0))
978 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
979#endif
980
981 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0)) {
982 ifp->if_oerrorsif_data.ifi_oerrors++;
983 continue;
984 }
985encapped:
986 if (ic->ic_fixed_rate != -1) {
987 rate = ic->ic_sup_rates[ic->ic_curmode].
988 rs_rates[ic->ic_fixed_rate];
989 } else
990 rate = ni->ni_rates.rs_rates[ni->ni_txrate];
991 rate &= IEEE80211_RATE_VAL0x7f;
992 }
993
994#if NBPFILTER1 > 0
995 if (ic->ic_rawbpf != NULL((void *)0))
996 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
997#endif
998
999 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1000 if ((wh->i_fc[1] & IEEE80211_FC1_WEP0x40) && !sc->chip_hw_crypt) {
1001 struct ieee80211_key *k;
1002
1003 k = ieee80211_get_txkey(ic, wh, ni);
1004 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0)) {
1005 ieee80211_release_node(ic, ni);
1006 ifp->if_oerrorsif_data.ifi_oerrors++;
1007 continue;
1008 }
1009 }
1010
1011#if NBPFILTER1 > 0
1012 if (sc->sc_drvbpf != NULL((void *)0)) {
1013 struct mbuf mb;
1014 struct acx_tx_radiotap_hdr *tap = &sc->sc_txtapsc_txtapu.th;
1015
1016 tap->wt_flags = 0;
1017 tap->wt_rate = rate;
1018 tap->wt_chan_freq =
1019 htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1020 tap->wt_chan_flags =
1021 htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1022
1023 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1024 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1025 mb.m_nextm_hdr.mh_next = m;
1026 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1027 mb.m_typem_hdr.mh_type = 0;
1028 mb.m_flagsm_hdr.mh_flags = 0;
1029 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1030 }
1031#endif
1032
1033 if (acx_encap(sc, buf, m, ni, rate) != 0) {
1034 /*
1035 * NOTE: `m' will be freed in acx_encap()
1036 * if we reach here.
1037 */
1038 if (ni != NULL((void *)0))
1039 ieee80211_release_node(ic, ni);
1040 ifp->if_oerrorsif_data.ifi_oerrors++;
1041 continue;
1042 }
1043
1044 /*
1045 * NOTE:
1046 * 1) `m' should not be touched after acx_encap()
1047 * 2) `node' will be used to do TX rate control during
1048 * acx_txeof(), so it is not freed here. acx_txeof()
1049 * will free it for us
1050 */
1051 trans++;
1052 bd->tx_used_count++;
1053 idx = (idx + 1) % ACX_TX_DESC_CNT16;
1054 }
1055 bd->tx_free_start = idx;
1056
1057 if (bd->tx_used_count == ACX_TX_DESC_CNT16)
1058 ifq_set_oactive(&ifp->if_snd);
1059
1060 if (trans && sc->sc_txtimer == 0)
1061 sc->sc_txtimer = 5;
1062 ifp->if_timer = 1;
1063}
1064
1065void
1066acx_watchdog(struct ifnet *ifp)
1067{
1068 struct acx_softc *sc = ifp->if_softc;
1069
1070 ifp->if_timer = 0;
1071
1072 if ((ifp->if_flags & IFF_RUNNING0x40) == 0)
1073 return;
1074
1075 if (sc->sc_txtimer) {
1076 if (--sc->sc_txtimer == 0) {
1077 printf("%s: watchdog timeout\n", ifp->if_xname);
1078 acx_init(ifp);
1079 ifp->if_oerrorsif_data.ifi_oerrors++;
1080 return;
1081 } else
1082 ifp->if_timer = 1;
1083 }
1084
1085 ieee80211_watchdog(ifp);
1086}
1087
1088int
1089acx_intr(void *arg)
1090{
1091 struct acx_softc *sc = arg;
1092 uint16_t intr_status;
1093
1094 if ((sc->sc_flags & ACX_FLAG_FW_LOADED0x01) == 0)
1095 return (0);
1096
1097 intr_status = CSR_READ_2(sc, ACXREG_INTR_STATUS_CLR)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(9)])))
;
1098 if (intr_status == ACXRV_INTR_ALL0xffff) {
1099 /* not our interrupt */
1100 return (0);
1101 }
1102
1103 /* Acknowledge all interrupts */
1104 CSR_WRITE_2(sc, ACXREG_INTR_ACK, intr_status)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(10)]), (intr_status)))
;
1105
1106 intr_status &= sc->chip_intr_enable;
1107 if (intr_status == 0) {
1108 /* not interrupts we care about */
1109 return (1);
1110 }
1111
1112#ifndef IEEE80211_STA_ONLY
1113 if (intr_status & ACXRV_INTR_DTIM0x0010)
1114 ieee80211_notify_dtim(&sc->sc_ic);
1115#endif
1116
1117 if (intr_status & ACXRV_INTR_TX_FINI0x0002)
1118 acx_txeof(sc);
1119
1120 if (intr_status & ACXRV_INTR_RX_FINI0x0008)
1121 acx_rxeof(sc);
1122
1123 return (1);
1124}
1125
1126void
1127acx_disable_intr(struct acx_softc *sc)
1128{
1129 CSR_WRITE_2(sc, ACXREG_INTR_MASK, sc->chip_intr_disable)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(7)]), (sc->chip_intr_disable)))
;
1130 CSR_WRITE_2(sc, ACXREG_EVENT_MASK, 0)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(5)]), (0)))
;
1131}
1132
1133void
1134acx_enable_intr(struct acx_softc *sc)
1135{
1136 /* Mask out interrupts that are not in the enable set */
1137 CSR_WRITE_2(sc, ACXREG_INTR_MASK, ~sc->chip_intr_enable)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(7)]), (~sc->chip_intr_enable)))
;
1138 CSR_WRITE_2(sc, ACXREG_EVENT_MASK, ACXRV_EVENT_DISABLE)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(5)]), (0x8000)))
;
1139}
1140
1141void
1142acx_txeof(struct acx_softc *sc)
1143{
1144 struct acx_buf_data *bd;
1145 struct acx_txbuf *buf;
1146 struct ifnet *ifp;
1147 int idx;
1148
1149 ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1150
1151 bd = &sc->sc_buf_data;
1152 idx = bd->tx_used_start;
1153 for (buf = &bd->tx_buf[idx]; buf->tb_mbuf != NULL((void *)0);
1154 buf = &bd->tx_buf[idx]) {
1155 uint8_t ctrl, error;
1156
1157 ctrl = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_ctrl)(((sc)->sc_mem2_bt)->read_1(((sc)->sc_mem2_bh), ((buf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ctrl))))
;
1158 if ((ctrl & (DESC_CTRL_HOSTOWN0x80 | DESC_CTRL_ACXDONE0x40)) !=
1159 (DESC_CTRL_HOSTOWN0x80 | DESC_CTRL_ACXDONE0x40))
1160 break;
1161
1162 bus_dmamap_unload(sc->sc_dmat, buf->tb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (buf
->tb_mbuf_dmamap))
;
1163 m_freem(buf->tb_mbuf);
1164 buf->tb_mbuf = NULL((void *)0);
1165
1166 error = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_error)(((sc)->sc_mem2_bt)->read_1(((sc)->sc_mem2_bh), ((buf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_error))))
;
1167 if (error) {
1168 acx_txerr(sc, error);
1169 ifp->if_oerrorsif_data.ifi_oerrors++;
1170 }
1171
1172 /* Update rate control statistics for the node */
1173 if (buf->tb_node != NULL((void *)0)) {
1174 struct ieee80211com *ic;
1175 struct ieee80211_node *ni;
1176 struct acx_node *wn;
1177 int ntries;
1178
1179 ic = &sc->sc_ic;
1180 ni = (struct ieee80211_node *)buf->tb_node;
1181 wn = (struct acx_node *)ni;
1182 ntries = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_rts_fail)(((sc)->sc_mem2_bt)->read_1(((sc)->sc_mem2_bh), ((buf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_rts_fail))))
+
1183 FW_TXDESC_GETFIELD_1(sc, buf, f_tx_ack_fail)(((sc)->sc_mem2_bt)->read_1(((sc)->sc_mem2_bh), ((buf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ack_fail))))
;
1184
1185 wn->amn.amn_txcnt++;
1186 if (ntries > 0) {
1187 DPRINTFN(2, ("%s: tx intr ntries %d\n",
1188 sc->sc_dev.dv_xname, ntries));
1189 wn->amn.amn_retrycnt++;
1190 }
1191
1192 ieee80211_release_node(ic, ni);
1193 buf->tb_node = NULL((void *)0);
1194 }
1195
1196 FW_TXDESC_SETFIELD_1(sc, buf, f_tx_ctrl, DESC_CTRL_HOSTOWN)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((buf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ctrl)), ((0x80))))
;
1197
1198 bd->tx_used_count--;
1199
1200 idx = (idx + 1) % ACX_TX_DESC_CNT16;
1201 }
1202 bd->tx_used_start = idx;
1203
1204 sc->sc_txtimer = bd->tx_used_count == 0 ? 0 : 5;
1205
1206 if (bd->tx_used_count != ACX_TX_DESC_CNT16) {
1207 ifq_clr_oactive(&ifp->if_snd);
1208 acx_start(ifp);
1209 }
1210}
1211
1212void
1213acx_txerr(struct acx_softc *sc, uint8_t err)
1214{
1215 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1216 struct acx_stats *stats = &sc->sc_stats;
1217
1218 if (err == DESC_ERR_EXCESSIVE_RETRY0x20) {
1219 /*
1220 * This a common error (see comment below),
1221 * so print it using DPRINTF().
1222 */
1223 DPRINTF(("%s: TX failed -- excessive retry\n",
1224 sc->sc_dev.dv_xname));
1225 } else
1226 printf("%s: TX failed -- ", ifp->if_xname);
1227
1228 /*
1229 * Although `err' looks like bitmask, it never
1230 * has multiple bits set.
1231 */
1232 switch (err) {
1233#if 0
1234 case DESC_ERR_OTHER_FRAG0x01:
1235 /* XXX what's this */
1236 printf("error in other fragment\n");
1237 stats->err_oth_frag++;
1238 break;
1239#endif
1240 case DESC_ERR_ABORT0x02:
1241 printf("aborted\n");
1242 stats->err_abort++;
1243 break;
1244 case DESC_ERR_PARAM0x04:
1245 printf("wrong parameters in descriptor\n");
1246 stats->err_param++;
1247 break;
1248 case DESC_ERR_NO_WEPKEY0x08:
1249 printf("WEP key missing\n");
1250 stats->err_no_wepkey++;
1251 break;
1252 case DESC_ERR_MSDU_TIMEOUT0x10:
1253 printf("MSDU life timeout\n");
1254 stats->err_msdu_timeout++;
1255 break;
1256 case DESC_ERR_EXCESSIVE_RETRY0x20:
1257 /*
1258 * Possible causes:
1259 * 1) Distance is too long
1260 * 2) Transmit failed (e.g. no MAC level ACK)
1261 * 3) Chip overheated (this should be rare)
1262 */
1263 stats->err_ex_retry++;
1264 break;
1265 case DESC_ERR_BUF_OVERFLOW0x40:
1266 printf("buffer overflow\n");
1267 stats->err_buf_oflow++;
1268 break;
1269 case DESC_ERR_DMA0x80:
1270 printf("DMA error\n");
1271 stats->err_dma++;
1272 break;
1273 default:
1274 printf("unknown error %d\n", err);
1275 stats->err_unkn++;
1276 break;
1277 }
1278}
1279
1280void
1281acx_rxeof(struct acx_softc *sc)
1282{
1283 struct ieee80211com *ic = &sc->sc_ic;
1284 struct acx_ring_data *rd = &sc->sc_ring_data;
1285 struct acx_buf_data *bd = &sc->sc_buf_data;
1286 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1287 int idx, ready;
1288
1289 bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x02))
1290 rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x02))
;
1291
1292 /*
1293 * Locate first "ready" rx buffer,
1294 * start from last stopped position.
1295 */
1296 idx = bd->rx_scan_start;
1297 ready = 0;
1298 do {
1299 struct acx_rxbuf *buf;
1300
1301 buf = &bd->rx_buf[idx];
1302 if ((buf->rb_desc->h_ctrl & htole16(DESC_CTRL_HOSTOWN)((__uint16_t)(0x80))) &&
1303 (buf->rb_desc->h_status & htole32(DESC_STATUS_FULL)((__uint32_t)(0x80000000)))) {
1304 ready = 1;
1305 break;
1306 }
1307 idx = (idx + 1) % ACX_RX_DESC_CNT16;
1308 } while (idx != bd->rx_scan_start);
1309
1310 if (!ready)
1311 return;
1312
1313 /*
1314 * NOTE: don't mess up `idx' here, it will
1315 * be used in the following code.
1316 */
1317 do {
1318 struct acx_rxbuf_hdr *head;
1319 struct acx_rxbuf *buf;
1320 struct mbuf *m;
1321 struct ieee80211_rxinfo rxi;
1322 uint32_t desc_status;
1323 uint16_t desc_ctrl;
1324 int len, error;
1325
1326 buf = &bd->rx_buf[idx];
1327
1328 desc_ctrl = letoh16(buf->rb_desc->h_ctrl)((__uint16_t)(buf->rb_desc->h_ctrl));
1329 desc_status = letoh32(buf->rb_desc->h_status)((__uint32_t)(buf->rb_desc->h_status));
1330 if (!(desc_ctrl & DESC_CTRL_HOSTOWN0x80) ||
1331 !(desc_status & DESC_STATUS_FULL0x80000000))
1332 break;
1333
1334 bus_dmamap_sync(sc->sc_dmat, buf->rb_mbuf_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (buf->
rb_mbuf_dmamap), (0), (buf->rb_mbuf_dmamap->dm_mapsize)
, (0x02))
1335 buf->rb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (buf->
rb_mbuf_dmamap), (0), (buf->rb_mbuf_dmamap->dm_mapsize)
, (0x02))
;
1336
1337 m = buf->rb_mbuf;
1338
1339 error = acx_newbuf(sc, buf, 0);
1340 if (error) {
1341 ifp->if_ierrorsif_data.ifi_ierrors++;
1342 goto next;
1343 }
1344
1345 head = mtod(m, struct acx_rxbuf_hdr *)((struct acx_rxbuf_hdr *)((m)->m_hdr.mh_data));
1346
1347 len = letoh16(head->rbh_len)((__uint16_t)(head->rbh_len)) & ACX_RXBUF_LEN_MASK0xfff;
1348 if (len >= sizeof(struct ieee80211_frame_min) &&
1349 len < MCLBYTES(1 << 11)) {
1350 struct ieee80211_frame *wh;
1351 struct ieee80211_node *ni;
1352
1353 m_adj(m, sizeof(struct acx_rxbuf_hdr) +
1354 sc->chip_rxbuf_exhdr);
1355 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1356
1357 rxi.rxi_flags = 0;
1358 if ((wh->i_fc[1] & IEEE80211_FC1_WEP0x40) &&
1359 sc->chip_hw_crypt) {
1360 /* Short circuit software WEP */
1361 wh->i_fc[1] &= ~IEEE80211_FC1_WEP0x40;
1362
1363 /* Do chip specific RX buffer processing */
1364 if (sc->chip_proc_wep_rxbuf != NULL((void *)0)) {
1365 sc->chip_proc_wep_rxbuf(sc, m, &len);
1366 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1367 }
1368 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
1369 }
1370
1371 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = len;
1372
1373#if NBPFILTER1 > 0
1374 if (sc->sc_drvbpf != NULL((void *)0)) {
1375 struct mbuf mb;
1376 struct acx_rx_radiotap_hdr *tap = &sc->sc_rxtapsc_rxtapu.th;
1377
1378 tap->wr_flags = 0;
1379 tap->wr_chan_freq =
1380 htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1381 tap->wr_chan_flags =
1382 htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1383 tap->wr_rssi = head->rbh_level;
1384 tap->wr_max_rssi = ic->ic_max_rssi;
1385
1386 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1387 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1388 mb.m_nextm_hdr.mh_next = m;
1389 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1390 mb.m_typem_hdr.mh_type = 0;
1391 mb.m_flagsm_hdr.mh_flags = 0;
1392 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1393 }
1394#endif
1395
1396 ni = ieee80211_find_rxnode(ic, wh);
1397
1398 rxi.rxi_rssi = head->rbh_level;
1399 rxi.rxi_tstamp = letoh32(head->rbh_time)((__uint32_t)(head->rbh_time));
1400 ieee80211_input(ifp, m, ni, &rxi);
1401
1402 ieee80211_release_node(ic, ni);
1403 } else {
1404 m_freem(m);
1405 ifp->if_ierrorsif_data.ifi_ierrors++;
1406 }
1407
1408next:
1409 buf->rb_desc->h_ctrl = htole16(desc_ctrl & ~DESC_CTRL_HOSTOWN)((__uint16_t)(desc_ctrl & ~0x80));
1410 buf->rb_desc->h_status = 0;
1411 bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x04))
1412 rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x04))
;
1413
1414 idx = (idx + 1) % ACX_RX_DESC_CNT16;
1415 } while (idx != bd->rx_scan_start);
1416
1417 /*
1418 * Record the position so that next
1419 * time we can start from it.
1420 */
1421 bd->rx_scan_start = idx;
1422}
1423
1424int
1425acx_reset(struct acx_softc *sc)
1426{
1427 uint16_t reg;
1428
1429 /* Halt ECPU */
1430 CSR_SETB_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_HALT)((((sc))->sc_mem1_bt)->write_2((((sc))->sc_mem1_bh),
(((sc))->chip_ioreg[((27))]), (((((sc))->sc_mem1_bt)->
read_2((((sc))->sc_mem1_bh), (((sc))->chip_ioreg[((27))
]))) | (0x1))))
;
1431
1432 /* Software reset */
1433 reg = CSR_READ_2(sc, ACXREG_SOFT_RESET)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(0)])))
;
1434 CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg | ACXRV_SOFT_RESET)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(0)]), (reg | 0x1)))
;
1435 DELAY(100)(*delay_func)(100);
1436 CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(0)]), (reg)))
;
1437
1438 /* Initialize EEPROM */
1439 CSR_SETB_2(sc, ACXREG_EEPROM_INIT, ACXRV_EEPROM_INIT)((((sc))->sc_mem1_bt)->write_2((((sc))->sc_mem1_bh),
(((sc))->chip_ioreg[((13))]), (((((sc))->sc_mem1_bt)->
read_2((((sc))->sc_mem1_bh), (((sc))->chip_ioreg[((13))
]))) | (0x1))))
;
1440 DELAY(50000)(*delay_func)(50000);
1441
1442 /* Test whether ECPU is stopped */
1443 reg = CSR_READ_2(sc, ACXREG_ECPU_CTRL)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(27)])))
;
1444 if (!(reg & ACXRV_ECPU_HALT0x1)) {
1445 printf("%s: can't halt ECPU\n", sc->sc_dev.dv_xname);
1446 return (ENXIO6);
1447 }
1448
1449 return (0);
1450}
1451
1452int
1453acx_read_eeprom(struct acx_softc *sc, uint32_t offset, uint8_t *val)
1454{
1455 int i;
1456
1457 CSR_WRITE_4(sc, ACXREG_EEPROM_CONF, 0)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(17)]), (0)))
;
1458 CSR_WRITE_4(sc, ACXREG_EEPROM_ADDR, offset)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(15)]), (offset)))
;
1459 CSR_WRITE_4(sc, ACXREG_EEPROM_CTRL, ACXRV_EEPROM_READ)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(14)]), (0x2)))
;
1460
1461#define EE_READ_RETRY_MAX 100
1462 for (i = 0; i < EE_READ_RETRY_MAX; ++i) {
1463 if (CSR_READ_2(sc, ACXREG_EEPROM_CTRL)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(14)])))
== 0)
1464 break;
1465 DELAY(10000)(*delay_func)(10000);
1466 }
1467 if (i == EE_READ_RETRY_MAX) {
1468 printf("%s: can't read EEPROM offset %x (timeout)\n",
1469 sc->sc_dev.dv_xname, offset);
1470 return (ETIMEDOUT60);
1471 }
1472#undef EE_READ_RETRY_MAX
1473
1474 *val = CSR_READ_1(sc, ACXREG_EEPROM_DATA)(((sc)->sc_mem1_bt)->read_1(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(16)])))
;
1475
1476 return (0);
1477}
1478
1479int
1480acx_read_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t *val)
1481{
1482 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1483 int i;
1484
1485 CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(19)]), (reg)))
;
1486 CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_READ)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(21)]), (0x2)))
;
1487
1488#define PHY_READ_RETRY_MAX 100
1489 for (i = 0; i < PHY_READ_RETRY_MAX; ++i) {
1490 if (CSR_READ_4(sc, ACXREG_PHY_CTRL)(((sc)->sc_mem1_bt)->read_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(21)])))
== 0)
1491 break;
1492 DELAY(10000)(*delay_func)(10000);
1493 }
1494 if (i == PHY_READ_RETRY_MAX) {
1495 printf("%s: can't read phy reg %x (timeout)\n",
1496 ifp->if_xname, reg);
1497 return (ETIMEDOUT60);
1498 }
1499#undef PHY_READ_RETRY_MAX
1500
1501 *val = CSR_READ_1(sc, ACXREG_PHY_DATA)(((sc)->sc_mem1_bt)->read_1(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(20)])))
;
1502
1503 return (0);
1504}
1505
1506void
1507acx_write_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t val)
1508{
1509 CSR_WRITE_4(sc, ACXREG_PHY_DATA, val)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(20)]), (val)))
;
1510 CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(19)]), (reg)))
;
1511 CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_WRITE)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(21)]), (0x1)))
;
1512}
1513
1514int
1515acx_load_base_firmware(struct acx_softc *sc, const char *name)
1516{
1517 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1518 int i, error;
1519 uint8_t *ucode;
1520 size_t size;
1521
1522 error = loadfirmware(name, &ucode, &size);
1523
1524 if (error != 0) {
1525 printf("%s: error %d, could not read firmware %s\n",
1526 ifp->if_xname, error, name);
1527 return (EIO5);
1528 }
1529
1530 /* Load base firmware */
1531 error = acx_load_firmware(sc, 0, ucode, size);
1532
1533 free(ucode, M_DEVBUF2, size);
1534
1535 if (error) {
1536 printf("%s: can't load base firmware\n", ifp->if_xname);
1537 return error;
1538 }
1539 DPRINTF(("%s: base firmware loaded\n", sc->sc_dev.dv_xname));
1540
1541 /* Start ECPU */
1542 CSR_WRITE_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_START)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(27)]), (0x0)))
;
1543
1544 /* Wait for ECPU to be up */
1545 for (i = 0; i < 500; ++i) {
1546 uint16_t reg;
1547
1548 reg = CSR_READ_2(sc, ACXREG_INTR_STATUS)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(8)])))
;
1549 if (reg & ACXRV_INTR_FCS_THRESH0x4000) {
1550 CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_FCS_THRESH)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(10)]), (0x4000)))
;
1551 return (0);
1552 }
1553 DELAY(10000)(*delay_func)(10000);
1554 }
1555
1556 printf("%s: can't initialize ECPU (timeout)\n", ifp->if_xname);
1557
1558 return (ENXIO6);
1559}
1560
1561int
1562acx_load_radio_firmware(struct acx_softc *sc, const char *name)
1563{
1564 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1565 struct acx_conf_mmap mem_map;
1566 uint32_t radio_fw_ofs;
1567 int error;
1568 uint8_t *ucode;
1569 size_t size;
1570
1571 error = loadfirmware(name, &ucode, &size);
1572
1573 if (error != 0) {
1574 printf("%s: error %d, could not read firmware %s\n",
1575 ifp->if_xname, error, name);
1576 return (EIO5);
1577 }
1578
1579 /*
1580 * Get the position, where base firmware is loaded, so that
1581 * radio firmware can be loaded after it.
1582 */
1583 if (acx_get_conf(sc, ACX_CONF_MMAP0x0008, &mem_map, sizeof(mem_map)) != 0) {
1584 free(ucode, M_DEVBUF2, size);
1585 return (ENXIO6);
1586 }
1587 radio_fw_ofs = letoh32(mem_map.code_end)((__uint32_t)(mem_map.code_end));
1588
1589 /* Put ECPU into sleeping state, before loading radio firmware */
1590 if (acx_exec_command(sc, ACXCMD_SLEEP0x0f, NULL((void *)0), 0, NULL((void *)0), 0) != 0) {
1591 free(ucode, M_DEVBUF2, size);
1592 return (ENXIO6);
1593 }
1594
1595 /* Load radio firmware */
1596 error = acx_load_firmware(sc, radio_fw_ofs, ucode, size);
1597
1598 free(ucode, M_DEVBUF2, size);
1599
1600 if (error) {
1601 printf("%s: can't load radio firmware\n", ifp->if_xname);
1602 return (ENXIO6);
1603 }
1604 DPRINTF(("%s: radio firmware loaded\n", sc->sc_dev.dv_xname));
1605
1606 /* Wake up sleeping ECPU, after radio firmware is loaded */
1607 if (acx_exec_command(sc, ACXCMD_WAKEUP0x10, NULL((void *)0), 0, NULL((void *)0), 0) != 0)
1608 return (ENXIO6);
1609
1610 /* Initialize radio */
1611 if (acx_init_radio(sc, radio_fw_ofs, size) != 0)
1612 return (ENXIO6);
1613
1614 /* Verify radio firmware's loading position */
1615 if (acx_get_conf(sc, ACX_CONF_MMAP0x0008, &mem_map, sizeof(mem_map)) != 0)
1616 return (ENXIO6);
1617
1618 if (letoh32(mem_map.code_end)((__uint32_t)(mem_map.code_end)) != radio_fw_ofs + size) {
1619 printf("%s: loaded radio firmware position mismatch\n",
1620 ifp->if_xname);
1621 return (ENXIO6);
1622 }
1623
1624 DPRINTF(("%s: radio firmware initialized\n", sc->sc_dev.dv_xname));
1625
1626 return (0);
1627}
1628
1629int
1630acx_load_firmware(struct acx_softc *sc, uint32_t offset, const uint8_t *data,
1631 int data_len)
1632{
1633 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1634 const uint32_t *fw;
1635 u_int32_t csum = 0;
1636 int i, fw_len;
1637
1638 for (i = 4; i < data_len; i++)
1639 csum += data[i];
1640
1641 fw = (const uint32_t *)data;
1642
1643 if (*fw != htole32(csum)((__uint32_t)(csum))) {
1644 printf("%s: firmware checksum 0x%x does not match 0x%x!\n",
1645 ifp->if_xname, *fw, htole32(csum)((__uint32_t)(csum)));
1646 return (ENXIO6);
1647 }
1648
1649 /* skip csum + length */
1650 data += 8;
1651 data_len -= 8;
1652
1653 fw = (const uint32_t *)data;
1654 fw_len = data_len / sizeof(uint32_t);
1655
1656 /*
1657 * LOADFW_AUTO_INC only works with some older firmware:
1658 * 1) acx100's firmware
1659 * 2) acx111's firmware whose rev is 0x00010011
1660 */
1661
1662 /* Load firmware */
1663 CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(4)]), (0x0)))
;
1664#ifndef LOADFW_AUTO_INC
1665 CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(3)]), (0)))
;
1666#else
1667 CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(3)]), (0x10000)))
;
1668 CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(1)]), (offset)))
;
1669#endif
1670
1671 for (i = 0; i < fw_len; ++i) {
1672#ifndef LOADFW_AUTO_INC
1673 CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4))(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(1)]), (offset + (i * 4))))
;
1674#endif
1675 CSR_WRITE_4(sc, ACXREG_FWMEM_DATA, betoh32(fw[i]))(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(2)]), ((__uint32_t)(__builtin_constant_p(fw
[i]) ? (__uint32_t)(((__uint32_t)(fw[i]) & 0xff) <<
24 | ((__uint32_t)(fw[i]) & 0xff00) << 8 | ((__uint32_t
)(fw[i]) & 0xff0000) >> 8 | ((__uint32_t)(fw[i]) &
0xff000000) >> 24) : __swap32md(fw[i])))))
;
1676 }
1677
1678 /* Verify firmware */
1679 CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(4)]), (0x0)))
;
1680#ifndef LOADFW_AUTO_INC
1681 CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(3)]), (0)))
;
1682#else
1683 CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(3)]), (0x10000)))
;
1684 CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset)(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(1)]), (offset)))
;
1685#endif
1686
1687 for (i = 0; i < fw_len; ++i) {
1688 uint32_t val;
1689
1690#ifndef LOADFW_AUTO_INC
1691 CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4))(((sc)->sc_mem1_bt)->write_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(1)]), (offset + (i * 4))))
;
1692#endif
1693 val = CSR_READ_4(sc, ACXREG_FWMEM_DATA)(((sc)->sc_mem1_bt)->read_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(2)])))
;
1694 if (betoh32(fw[i])(__uint32_t)(__builtin_constant_p(fw[i]) ? (__uint32_t)(((__uint32_t
)(fw[i]) & 0xff) << 24 | ((__uint32_t)(fw[i]) &
0xff00) << 8 | ((__uint32_t)(fw[i]) & 0xff0000) >>
8 | ((__uint32_t)(fw[i]) & 0xff000000) >> 24) : __swap32md
(fw[i]))
!= val) {
1695 printf("%s: firmware mismatch fw %08x loaded %08x\n",
1696 ifp->if_xname, fw[i], val);
1697 return (ENXIO6);
1698 }
1699 }
1700
1701 return (0);
1702}
1703
1704struct ieee80211_node *
1705acx_node_alloc(struct ieee80211com *ic)
1706{
1707 struct acx_node *wn;
1708
1709 wn = malloc(sizeof(*wn), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
1710 if (wn == NULL((void *)0))
1711 return (NULL((void *)0));
1712
1713 return ((struct ieee80211_node *)wn);
1714}
1715
1716int
1717acx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1718{
1719 struct acx_softc *sc = ic->ic_ific_ac.ac_if.if_softc;
1720 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1721 int error = 0;
1722
1723 timeout_del(&sc->amrr_ch);
1724
1725 switch (nstate) {
1726 case IEEE80211_S_INIT:
1727 break;
1728 case IEEE80211_S_SCAN: {
1729 uint8_t chan;
1730
1731 chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1732 if (acx_set_channel(sc, chan) != 0) {
1733 error = 1;
1734 goto back;
1735 }
1736
1737 /* 200ms => 5 channels per second */
1738 timeout_add_msec(&sc->sc_chanscan_timer, 200);
1739 }
1740 break;
1741 case IEEE80211_S_AUTH:
1742 if (ic->ic_opmode == IEEE80211_M_STA) {
1743 struct ieee80211_node *ni;
1744#ifdef ACX_DEBUG
1745 int i;
1746#endif
1747
1748 ni = ic->ic_bss;
1749
1750 if (acx_join_bss(sc, ACX_MODE_STA2, ni) != 0) {
1751 printf("%s: join BSS failed\n", ifp->if_xname);
1752 error = 1;
1753 goto back;
1754 }
1755
1756 DPRINTF(("%s: join BSS\n", sc->sc_dev.dv_xname));
1757 if (ic->ic_state == IEEE80211_S_ASSOC) {
1758 DPRINTF(("%s: change from assoc to run\n",
1759 sc->sc_dev.dv_xname));
1760 ic->ic_state = IEEE80211_S_RUN;
1761 }
1762
1763#ifdef ACX_DEBUG
1764 printf("%s: AP rates: ", sc->sc_dev.dv_xname);
1765 for (i = 0; i < ni->ni_rates.rs_nrates; ++i)
1766 printf("%d ", ni->ni_rates.rs_rates[i]);
1767 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
1768 printf(" %s\n", ether_sprintf(ni->ni_bssid));
1769#endif
1770 }
1771 break;
1772 case IEEE80211_S_RUN:
1773#ifndef IEEE80211_STA_ONLY
1774 if (ic->ic_opmode == IEEE80211_M_IBSS ||
1775 ic->ic_opmode == IEEE80211_M_HOSTAP) {
1776 struct ieee80211_node *ni;
1777 uint8_t chan;
1778
1779 ni = ic->ic_bss;
1780 chan = ieee80211_chan2ieee(ic, ni->ni_chan);
1781
1782 error = 1;
1783
1784 if (acx_set_channel(sc, chan) != 0)
1785 goto back;
1786
1787 if (acx_set_beacon_tmplt(sc, ni) != 0) {
1788 printf("%s: set beacon template failed\n",
1789 ifp->if_xname);
1790 goto back;
1791 }
1792
1793 if (acx_set_probe_resp_tmplt(sc, ni) != 0) {
1794 printf("%s: set probe response template "
1795 "failed\n", ifp->if_xname);
1796 goto back;
1797 }
1798
1799 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1800 if (acx_join_bss(sc, ACX_MODE_ADHOC0, ni) != 0) {
1801 printf("%s: join IBSS failed\n",
1802 ifp->if_xname);
1803 goto back;
1804 }
1805 } else {
1806 if (acx_join_bss(sc, ACX_MODE_AP3, ni) != 0) {
1807 printf("%s: join HOSTAP failed\n",
1808 ifp->if_xname);
1809 goto back;
1810 }
1811 }
1812
1813 DPRINTF(("%s: join IBSS\n", sc->sc_dev.dv_xname));
1814 error = 0;
1815 }
1816#endif
1817 /* fake a join to init the tx rate */
1818 if (ic->ic_opmode == IEEE80211_M_STA)
1819 acx_newassoc(ic, ic->ic_bss, 1);
1820
1821 /* start automatic rate control timer */
1822 if (ic->ic_fixed_rate == -1)
1823 timeout_add_msec(&sc->amrr_ch, 500);
1824 break;
1825 default:
1826 break;
1827 }
1828
1829back:
1830 if (error) {
1831 /* XXX */
1832 nstate = IEEE80211_S_INIT;
1833 arg = -1;
1834 }
1835
1836 return (sc->sc_newstate(ic, nstate, arg));
1837}
1838
1839int
1840acx_init_tmplt_ordered(struct acx_softc *sc)
1841{
1842 union {
1843 struct acx_tmplt_beacon beacon;
1844 struct acx_tmplt_null_data null;
1845 struct acx_tmplt_probe_req preq;
1846 struct acx_tmplt_probe_resp presp;
1847 struct acx_tmplt_tim tim;
1848 } data;
1849
1850 bzero(&data, sizeof(data))__builtin_bzero((&data), (sizeof(data)));
1851 /*
1852 * NOTE:
1853 * Order of templates initialization:
1854 * 1) Probe request
1855 * 2) NULL data
1856 * 3) Beacon
1857 * 4) TIM
1858 * 5) Probe response
1859 * Above order is critical to get a correct memory map.
1860 */
1861 if (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_REQ0x16, &data.preq,
1862 sizeof(data.preq)) != 0)
1863 return (1);
1864
1865 if (acx_set_tmplt(sc, ACXCMD_TMPLT_NULL_DATA0x15, &data.null,
1866 sizeof(data.null)) != 0)
1867 return (1);
1868
1869 if (acx_set_tmplt(sc, ACXCMD_TMPLT_BEACON0x13, &data.beacon,
1870 sizeof(data.beacon)) != 0)
1871 return (1);
1872
1873 if (acx_set_tmplt(sc, ACXCMD_TMPLT_TIM0x0a, &data.tim,
1874 sizeof(data.tim)) != 0)
1875 return (1);
1876
1877 if (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_RESP0x14, &data.presp,
1878 sizeof(data.presp)) != 0)
1879 return (1);
1880
1881 return (0);
1882}
1883
1884int
1885acx_dma_alloc(struct acx_softc *sc)
1886{
1887 struct acx_ring_data *rd = &sc->sc_ring_data;
1888 struct acx_buf_data *bd = &sc->sc_buf_data;
1889 int i, error, nsegs;
1890
1891 /* Allocate DMA stuffs for RX descriptors */
1892 error = bus_dmamap_create(sc->sc_dmat, ACX_RX_RING_SIZE, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((16
* sizeof(struct acx_host_desc))), (1), ((16 * sizeof(struct acx_host_desc
))), (0), (0x0001), (&rd->rx_ring_dmamap))
1893 ACX_RX_RING_SIZE, 0, BUS_DMA_NOWAIT, &rd->rx_ring_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((16
* sizeof(struct acx_host_desc))), (1), ((16 * sizeof(struct acx_host_desc
))), (0), (0x0001), (&rd->rx_ring_dmamap))
;
1894
1895 if (error) {
1896 printf("%s: can't create rx ring dma tag\n",
1897 sc->sc_dev.dv_xname);
1898 return (error);
1899 }
1900
1901 error = bus_dmamem_alloc(sc->sc_dmat, ACX_RX_RING_SIZE, PAGE_SIZE,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((16 *
sizeof(struct acx_host_desc))), ((1 << 12)), (0), (&
rd->rx_ring_seg), (1), (&nsegs), (0x0001))
1902 0, &rd->rx_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((16 *
sizeof(struct acx_host_desc))), ((1 << 12)), (0), (&
rd->rx_ring_seg), (1), (&nsegs), (0x0001))
;
1903
1904 if (error != 0) {
1905 printf("%s: can't allocate rx ring dma memory\n",
1906 sc->sc_dev.dv_xname);
1907 return (error);
1908 }
1909
1910 error = bus_dmamem_map(sc->sc_dmat, &rd->rx_ring_seg, nsegs,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rd
->rx_ring_seg), (nsegs), ((16 * sizeof(struct acx_host_desc
))), ((caddr_t *)&rd->rx_ring), (0x0001))
1911 ACX_RX_RING_SIZE, (caddr_t *)&rd->rx_ring,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rd
->rx_ring_seg), (nsegs), ((16 * sizeof(struct acx_host_desc
))), ((caddr_t *)&rd->rx_ring), (0x0001))
1912 BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rd
->rx_ring_seg), (nsegs), ((16 * sizeof(struct acx_host_desc
))), ((caddr_t *)&rd->rx_ring), (0x0001))
;
1913
1914 if (error != 0) {
1915 printf("%s: can't map rx desc DMA memory\n",
1916 sc->sc_dev.dv_xname);
1917 return (error);
1918 }
1919
1920 error = bus_dmamap_load(sc->sc_dmat, rd->rx_ring_dmamap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd->
rx_ring_dmamap), (rd->rx_ring), ((16 * sizeof(struct acx_host_desc
))), (((void *)0)), (0x0000))
1921 rd->rx_ring, ACX_RX_RING_SIZE, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd->
rx_ring_dmamap), (rd->rx_ring), ((16 * sizeof(struct acx_host_desc
))), (((void *)0)), (0x0000))
;
1922
1923 if (error) {
1924 printf("%s: can't get rx ring dma address\n",
1925 sc->sc_dev.dv_xname);
1926 bus_dmamem_free(sc->sc_dmat, &rd->rx_ring_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rd->rx_ring_seg), (1))
;
1927 return (error);
1928 }
1929
1930 rd->rx_ring_paddr = rd->rx_ring_dmamap->dm_segs[0].ds_addr;
1931
1932 /* Allocate DMA stuffs for TX descriptors */
1933 error = bus_dmamap_create(sc->sc_dmat, ACX_TX_RING_SIZE, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((2 *
16 * sizeof(struct acx_host_desc))), (1), ((2 * 16 * sizeof(
struct acx_host_desc))), (0), (0x0001), (&rd->tx_ring_dmamap
))
1934 ACX_TX_RING_SIZE, 0, BUS_DMA_NOWAIT, &rd->tx_ring_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((2 *
16 * sizeof(struct acx_host_desc))), (1), ((2 * 16 * sizeof(
struct acx_host_desc))), (0), (0x0001), (&rd->tx_ring_dmamap
))
;
1935
1936 if (error) {
1937 printf("%s: can't create tx ring dma tag\n",
1938 sc->sc_dev.dv_xname);
1939 return (error);
1940 }
1941
1942 error = bus_dmamem_alloc(sc->sc_dmat, ACX_TX_RING_SIZE, PAGE_SIZE,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((2 *
16 * sizeof(struct acx_host_desc))), ((1 << 12)), (0),
(&rd->tx_ring_seg), (1), (&nsegs), (0x0001))
1943 0, &rd->tx_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), ((2 *
16 * sizeof(struct acx_host_desc))), ((1 << 12)), (0),
(&rd->tx_ring_seg), (1), (&nsegs), (0x0001))
;
1944
1945 if (error) {
1946 printf("%s: can't allocate tx ring dma memory\n",
1947 sc->sc_dev.dv_xname);
1948 return (error);
1949 }
1950
1951 error = bus_dmamem_map(sc->sc_dmat, &rd->tx_ring_seg, nsegs,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rd
->tx_ring_seg), (nsegs), ((2 * 16 * sizeof(struct acx_host_desc
))), ((caddr_t *)&rd->tx_ring), (0x0001))
1952 ACX_TX_RING_SIZE, (caddr_t *)&rd->tx_ring, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&rd
->tx_ring_seg), (nsegs), ((2 * 16 * sizeof(struct acx_host_desc
))), ((caddr_t *)&rd->tx_ring), (0x0001))
;
1953
1954 if (error != 0) {
1955 printf("%s: can't map tx desc DMA memory\n",
1956 sc->sc_dev.dv_xname);
1957 return (error);
1958 }
1959
1960 error = bus_dmamap_load(sc->sc_dmat, rd->tx_ring_dmamap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd->
tx_ring_dmamap), (rd->tx_ring), ((2 * 16 * sizeof(struct acx_host_desc
))), (((void *)0)), (0x0000))
1961 rd->tx_ring, ACX_TX_RING_SIZE, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd->
tx_ring_dmamap), (rd->tx_ring), ((2 * 16 * sizeof(struct acx_host_desc
))), (((void *)0)), (0x0000))
;
1962
1963 if (error) {
1964 printf("%s: can't get tx ring dma address\n",
1965 sc->sc_dev.dv_xname);
1966 bus_dmamem_free(sc->sc_dmat, &rd->tx_ring_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rd->tx_ring_seg), (1))
;
1967 return (error);
1968 }
1969
1970 rd->tx_ring_paddr = rd->tx_ring_dmamap->dm_segs[0].ds_addr;
1971
1972 /* Create a spare RX DMA map */
1973 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->mbuf_tmp_dmamap
))
1974 0, 0, &bd->mbuf_tmp_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->mbuf_tmp_dmamap
))
;
1975
1976 if (error) {
1977 printf("%s: can't create tmp mbuf dma map\n",
1978 sc->sc_dev.dv_xname);
1979 return (error);
1980 }
1981
1982 /* Create DMA map for RX mbufs */
1983 for (i = 0; i < ACX_RX_DESC_CNT16; ++i) {
1984 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->rx_buf[
i].rb_mbuf_dmamap))
1985 MCLBYTES, 0, 0, &bd->rx_buf[i].rb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->rx_buf[
i].rb_mbuf_dmamap))
;
1986 if (error) {
1987 printf("%s: can't create rx mbuf dma map (%d)\n",
1988 sc->sc_dev.dv_xname, i);
1989 return (error);
1990 }
1991 bd->rx_buf[i].rb_desc = &rd->rx_ring[i];
1992 }
1993
1994 /* Create DMA map for TX mbufs */
1995 for (i = 0; i < ACX_TX_DESC_CNT16; ++i) {
1996 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->tx_buf[
i].tb_mbuf_dmamap))
1997 MCLBYTES, 0, 0, &bd->tx_buf[i].tb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 <<
11)), (1), ((1 << 11)), (0), (0), (&bd->tx_buf[
i].tb_mbuf_dmamap))
;
1998 if (error) {
1999 printf("%s: can't create tx mbuf dma map (%d)\n",
2000 sc->sc_dev.dv_xname, i);
2001 return (error);
2002 }
2003 bd->tx_buf[i].tb_desc1 = &rd->tx_ring[i * 2];
2004 bd->tx_buf[i].tb_desc2 = &rd->tx_ring[(i * 2) + 1];
2005 }
2006
2007 return (0);
2008}
2009
2010void
2011acx_dma_free(struct acx_softc *sc)
2012{
2013 struct acx_ring_data *rd = &sc->sc_ring_data;
2014 struct acx_buf_data *bd = &sc->sc_buf_data;
2015 int i;
2016
2017 if (rd->rx_ring != NULL((void *)0)) {
2018 bus_dmamap_unload(sc->sc_dmat, rd->rx_ring_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rd->
rx_ring_dmamap))
;
2019 bus_dmamem_free(sc->sc_dmat, &rd->rx_ring_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rd->rx_ring_seg), (1))
;
2020 }
2021
2022 if (rd->tx_ring != NULL((void *)0)) {
2023 bus_dmamap_unload(sc->sc_dmat, rd->tx_ring_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rd->
tx_ring_dmamap))
;
2024 bus_dmamem_free(sc->sc_dmat, &rd->tx_ring_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
rd->tx_ring_seg), (1))
;
2025 }
2026
2027 for (i = 0; i < ACX_RX_DESC_CNT16; ++i) {
2028 if (bd->rx_buf[i].rb_desc != NULL((void *)0)) {
2029 if (bd->rx_buf[i].rb_mbuf != NULL((void *)0)) {
2030 bus_dmamap_unload(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
rx_buf[i].rb_mbuf_dmamap))
2031 bd->rx_buf[i].rb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
rx_buf[i].rb_mbuf_dmamap))
;
2032 m_freem(bd->rx_buf[i].rb_mbuf);
2033 }
2034 bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bd
->rx_buf[i].rb_mbuf_dmamap))
2035 bd->rx_buf[i].rb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bd
->rx_buf[i].rb_mbuf_dmamap))
;
2036 }
2037 }
2038
2039 for (i = 0; i < ACX_TX_DESC_CNT16; ++i) {
2040 if (bd->tx_buf[i].tb_desc1 != NULL((void *)0)) {
2041 if (bd->tx_buf[i].tb_mbuf != NULL((void *)0)) {
2042 bus_dmamap_unload(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
tx_buf[i].tb_mbuf_dmamap))
2043 bd->tx_buf[i].tb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (bd->
tx_buf[i].tb_mbuf_dmamap))
;
2044 m_freem(bd->tx_buf[i].tb_mbuf);
2045 }
2046 bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bd
->tx_buf[i].tb_mbuf_dmamap))
2047 bd->tx_buf[i].tb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bd
->tx_buf[i].tb_mbuf_dmamap))
;
2048 }
2049 }
2050
2051 if (bd->mbuf_tmp_dmamap != NULL((void *)0))
2052 bus_dmamap_destroy(sc->sc_dmat, bd->mbuf_tmp_dmamap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (bd
->mbuf_tmp_dmamap))
;
2053}
2054
2055void
2056acx_init_tx_ring(struct acx_softc *sc)
2057{
2058 struct acx_ring_data *rd;
2059 struct acx_buf_data *bd;
2060 uint32_t paddr;
2061 int i;
2062
2063 rd = &sc->sc_ring_data;
2064 paddr = rd->tx_ring_paddr;
2065 for (i = 0; i < (ACX_TX_DESC_CNT16 * 2) - 1; ++i) {
2066 paddr += sizeof(struct acx_host_desc);
2067
2068 bzero(&rd->tx_ring[i], sizeof(struct acx_host_desc))__builtin_bzero((&rd->tx_ring[i]), (sizeof(struct acx_host_desc
)))
;
2069 rd->tx_ring[i].h_ctrl = htole16(DESC_CTRL_HOSTOWN)((__uint16_t)(0x80));
2070
2071 if (i == (ACX_TX_DESC_CNT16 * 2) - 1)
2072 rd->tx_ring[i].h_next_desc = htole32(rd->tx_ring_paddr)((__uint32_t)(rd->tx_ring_paddr));
2073 else
2074 rd->tx_ring[i].h_next_desc = htole32(paddr)((__uint32_t)(paddr));
2075 }
2076
2077 bus_dmamap_sync(sc->sc_dmat, rd->tx_ring_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
tx_ring_dmamap), (0), (rd->tx_ring_dmamap->dm_mapsize),
(0x04))
2078 rd->tx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
tx_ring_dmamap), (0), (rd->tx_ring_dmamap->dm_mapsize),
(0x04))
;
2079
2080 bd = &sc->sc_buf_data;
2081 bd->tx_free_start = 0;
2082 bd->tx_used_start = 0;
2083 bd->tx_used_count = 0;
2084}
2085
2086int
2087acx_init_rx_ring(struct acx_softc *sc)
2088{
2089 struct acx_ring_data *rd;
2090 struct acx_buf_data *bd;
2091 uint32_t paddr;
2092 int i;
2093
2094 bd = &sc->sc_buf_data;
2095 rd = &sc->sc_ring_data;
2096 paddr = rd->rx_ring_paddr;
2097
2098 for (i = 0; i < ACX_RX_DESC_CNT16; ++i) {
2099 int error;
2100
2101 paddr += sizeof(struct acx_host_desc);
2102 bzero(&rd->rx_ring[i], sizeof(struct acx_host_desc))__builtin_bzero((&rd->rx_ring[i]), (sizeof(struct acx_host_desc
)))
;
2103
2104 error = acx_newbuf(sc, &bd->rx_buf[i], 1);
2105 if (error)
2106 return (error);
2107
2108 if (i == ACX_RX_DESC_CNT16 - 1)
2109 rd->rx_ring[i].h_next_desc = htole32(rd->rx_ring_paddr)((__uint32_t)(rd->rx_ring_paddr));
2110 else
2111 rd->rx_ring[i].h_next_desc = htole32(paddr)((__uint32_t)(paddr));
2112 }
2113
2114 bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x04))
2115 rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
rx_ring_dmamap), (0), (rd->rx_ring_dmamap->dm_mapsize),
(0x04))
;
2116
2117 bd->rx_scan_start = 0;
2118
2119 return (0);
2120}
2121
2122int
2123acx_newbuf(struct acx_softc *sc, struct acx_rxbuf *rb, int wait)
2124{
2125 struct acx_buf_data *bd;
2126 struct mbuf *m;
2127 bus_dmamap_t map;
2128 uint32_t paddr;
2129 int error;
2130
2131 bd = &sc->sc_buf_data;
2132
2133 MGETHDR(m, wait ? M_WAITOK : M_DONTWAIT, MT_DATA)m = m_gethdr((wait ? 0x0001 : 0x0002), (1));
2134 if (m == NULL((void *)0))
2135 return (ENOBUFS55);
2136
2137 MCLGET(m, wait ? M_WAITOK : M_DONTWAIT)(void) m_clget((m), (wait ? 0x0001 : 0x0002), (1 << 11)
)
;
2138 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
2139 m_freem(m);
2140 return (ENOBUFS55);
2141 }
2142
2143 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
2144
2145 error = bus_dmamap_load_mbuf(sc->sc_dmat, bd->mbuf_tmp_dmamap, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
bd->mbuf_tmp_dmamap), (m), (wait ? 0x0000 : 0x0001))
2146 wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
bd->mbuf_tmp_dmamap), (m), (wait ? 0x0000 : 0x0001))
;
2147 if (error) {
2148 m_freem(m);
2149 printf("%s: can't map rx mbuf %d\n",
2150 sc->sc_dev.dv_xname, error);
2151 return (error);
2152 }
2153
2154 /* Unload originally mapped mbuf */
2155 if (rb->rb_mbuf != NULL((void *)0))
2156 bus_dmamap_unload(sc->sc_dmat, rb->rb_mbuf_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rb->
rb_mbuf_dmamap))
;
2157
2158 /* Swap this dmamap with tmp dmamap */
2159 map = rb->rb_mbuf_dmamap;
2160 rb->rb_mbuf_dmamap = bd->mbuf_tmp_dmamap;
2161 bd->mbuf_tmp_dmamap = map;
2162 paddr = rb->rb_mbuf_dmamap->dm_segs[0].ds_addr;
2163
2164 rb->rb_mbuf = m;
2165 rb->rb_desc->h_data_paddr = htole32(paddr)((__uint32_t)(paddr));
2166 rb->rb_desc->h_data_len = htole16(m->m_len)((__uint16_t)(m->m_hdr.mh_len));
2167
2168 bus_dmamap_sync(sc->sc_dmat, rb->rb_mbuf_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb->
rb_mbuf_dmamap), (0), (rb->rb_mbuf_dmamap->dm_mapsize),
(0x01))
2169 rb->rb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb->
rb_mbuf_dmamap), (0), (rb->rb_mbuf_dmamap->dm_mapsize),
(0x01))
;
2170
2171 return (0);
2172}
2173
2174int
2175acx_encap(struct acx_softc *sc, struct acx_txbuf *txbuf, struct mbuf *m,
2176 struct ieee80211_node *ni, int rate)
2177{
2178 struct acx_ring_data *rd = &sc->sc_ring_data;
2179 struct acx_node *node = (struct acx_node *)ni;
2180 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2181 uint32_t paddr;
2182 uint8_t ctrl;
2183 int error;
2184
2185 if (txbuf->tb_mbuf != NULL((void *)0))
2186 panic("free TX buf has mbuf installed");
2187
2188 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len > MCLBYTES(1 << 11)) {
2189 printf("%s: mbuf too big\n", ifp->if_xname);
2190 error = E2BIG7;
2191 goto back;
2192 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < ACX_FRAME_HDRLENsizeof(struct ieee80211_frame)) {
2193 printf("%s: mbuf too small\n", ifp->if_xname);
2194 error = EINVAL22;
2195 goto back;
2196 }
2197
2198 error = bus_dmamap_load_mbuf(sc->sc_dmat, txbuf->tb_mbuf_dmamap, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txbuf->tb_mbuf_dmamap), (m), (0x0001))
2199 BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txbuf->tb_mbuf_dmamap), (m), (0x0001))
;
2200
2201 if (error && error != EFBIG27) {
2202 printf("%s: can't map tx mbuf1 %d\n",
2203 sc->sc_dev.dv_xname, error);
2204 goto back;
2205 }
2206
2207 if (error) { /* error == EFBIG */
2208 /* too many fragments, linearize */
2209 if (m_defrag(m, M_DONTWAIT0x0002)) {
2210 printf("%s: can't defrag tx mbuf\n", ifp->if_xname);
2211 goto back;
2212 }
2213 error = bus_dmamap_load_mbuf(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txbuf->tb_mbuf_dmamap), (m), (0x0001))
2214 txbuf->tb_mbuf_dmamap, m, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
txbuf->tb_mbuf_dmamap), (m), (0x0001))
;
2215 if (error) {
2216 printf("%s: can't map tx mbuf2 %d\n",
2217 sc->sc_dev.dv_xname, error);
2218 goto back;
2219 }
2220 }
2221
2222 error = 0;
2223
2224 bus_dmamap_sync(sc->sc_dmat, txbuf->tb_mbuf_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txbuf
->tb_mbuf_dmamap), (0), (txbuf->tb_mbuf_dmamap->dm_mapsize
), (0x04))
2225 txbuf->tb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (txbuf
->tb_mbuf_dmamap), (0), (txbuf->tb_mbuf_dmamap->dm_mapsize
), (0x04))
;
2226
2227 txbuf->tb_mbuf = m;
2228 txbuf->tb_node = node;
2229 txbuf->tb_rate = rate;
2230
2231 /*
2232 * TX buffers are accessed in following way:
2233 * acx_fw_txdesc -> acx_host_desc -> buffer
2234 *
2235 * It is quite strange that acx also queries acx_host_desc next to
2236 * the one we have assigned to acx_fw_txdesc even if first one's
2237 * acx_host_desc.h_data_len == acx_fw_txdesc.f_tx_len
2238 *
2239 * So we allocate two acx_host_desc for one acx_fw_txdesc and
2240 * assign the first acx_host_desc to acx_fw_txdesc
2241 *
2242 * For acx111
2243 * host_desc1.h_data_len = buffer_len
2244 * host_desc2.h_data_len = buffer_len - mac_header_len
2245 *
2246 * For acx100
2247 * host_desc1.h_data_len = mac_header_len
2248 * host_desc2.h_data_len = buffer_len - mac_header_len
2249 */
2250 paddr = txbuf->tb_mbuf_dmamap->dm_segs[0].ds_addr;
2251 txbuf->tb_desc1->h_data_paddr = htole32(paddr)((__uint32_t)(paddr));
2252 txbuf->tb_desc2->h_data_paddr = htole32(paddr + ACX_FRAME_HDRLEN)((__uint32_t)(paddr + sizeof(struct ieee80211_frame)));
2253
2254 txbuf->tb_desc1->h_data_len =
2255 htole16(sc->chip_txdesc1_len ? sc->chip_txdesc1_len((__uint16_t)(sc->chip_txdesc1_len ? sc->chip_txdesc1_len
: m->M_dat.MH.MH_pkthdr.len))
2256 : m->m_pkthdr.len)((__uint16_t)(sc->chip_txdesc1_len ? sc->chip_txdesc1_len
: m->M_dat.MH.MH_pkthdr.len))
;
2257 txbuf->tb_desc2->h_data_len =
2258 htole16(m->m_pkthdr.len - ACX_FRAME_HDRLEN)((__uint16_t)(m->M_dat.MH.MH_pkthdr.len - sizeof(struct ieee80211_frame
)))
;
2259
2260 /*
2261 * NOTE:
2262 * We can't simply assign f_tx_ctrl, we will first read it back
2263 * and change it bit by bit
2264 */
2265 ctrl = FW_TXDESC_GETFIELD_1(sc, txbuf, f_tx_ctrl)(((sc)->sc_mem2_bt)->read_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ctrl))))
;
2266 ctrl |= sc->chip_fw_txdesc_ctrl; /* extra chip specific flags */
2267 ctrl &= ~(DESC_CTRL_HOSTOWN0x80 | DESC_CTRL_ACXDONE0x40);
2268
2269 FW_TXDESC_SETFIELD_2(sc, txbuf, f_tx_len, m->m_pkthdr.len)(((sc)->sc_mem2_bt)->write_2(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_len)), ((m->M_dat.MH.MH_pkthdr.len))))
;
2270 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_error, 0)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_error)), ((0))))
;
2271 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ack_fail, 0)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ack_fail)), ((0))))
;
2272 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_fail, 0)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_rts_fail)), ((0))))
;
2273 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_ok, 0)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_rts_ok)), ((0))))
;
2274 sc->chip_set_fw_txdesc_rate(sc, txbuf, rate);
2275
2276 txbuf->tb_desc1->h_ctrl = 0;
2277 txbuf->tb_desc2->h_ctrl = 0;
2278 bus_dmamap_sync(sc->sc_dmat, rd->tx_ring_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
tx_ring_dmamap), (0), (rd->tx_ring_dmamap->dm_mapsize),
(0x04))
2279 rd->tx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd->
tx_ring_dmamap), (0), (rd->tx_ring_dmamap->dm_mapsize),
(0x04))
;
2280
2281 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl2, 0)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ctrl2)), ((0))))
;
2282 FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl, ctrl)(((sc)->sc_mem2_bt)->write_1(((sc)->sc_mem2_bh), ((txbuf
)->tb_fwdesc_ofs + __builtin_offsetof(struct acx_fw_txdesc
, f_tx_ctrl)), ((ctrl))))
;
2283
2284 /* Tell chip to inform us about TX completion */
2285 CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_TX_FINI)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(6)]), (0x0004)))
;
2286back:
2287 if (error)
2288 m_freem(m);
2289
2290 return (error);
2291}
2292
2293int
2294acx_set_null_tmplt(struct acx_softc *sc)
2295{
2296 struct ieee80211com *ic = &sc->sc_ic;
2297 struct acx_tmplt_null_data n;
2298 struct ieee80211_frame *wh;
2299
2300 bzero(&n, sizeof(n))__builtin_bzero((&n), (sizeof(n)));
2301
2302 wh = &n.data;
2303 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_DATA0x08 |
2304 IEEE80211_FC0_SUBTYPE_NODATA0x40;
2305 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
2306 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
2307 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr)__builtin_memcpy((wh->i_addr2), (ic->ic_myaddr), (6));
2308 IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr)__builtin_memcpy((wh->i_addr3), (etherbroadcastaddr), (6));
2309
2310 return (acx_set_tmplt(sc, ACXCMD_TMPLT_NULL_DATA0x15, &n, sizeof(n)));
2311}
2312
2313int
2314acx_set_probe_req_tmplt(struct acx_softc *sc, const char *ssid, int ssid_len)
2315{
2316 struct ieee80211com *ic = &sc->sc_ic;
2317 struct acx_tmplt_probe_req req;
2318 struct ieee80211_frame *wh;
2319 struct ieee80211_rateset *rs;
2320 uint8_t *frm;
2321 int len;
2322
2323 bzero(&req, sizeof(req))__builtin_bzero((&req), (sizeof(req)));
2324
2325 wh = &req.data.u_data.f;
2326 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
2327 IEEE80211_FC0_SUBTYPE_PROBE_REQ0x40;
2328 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
2329 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
2330 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr)__builtin_memcpy((wh->i_addr2), (ic->ic_myaddr), (6));
2331 IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr)__builtin_memcpy((wh->i_addr3), (etherbroadcastaddr), (6));
2332
2333 frm = req.data.u_data.var;
2334 frm = ieee80211_add_ssid(frm, ssid, ssid_len);
2335 rs = &ic->ic_sup_rates[sc->chip_phymode];
2336 frm = ieee80211_add_rates(frm, rs);
2337 if (rs->rs_nrates > IEEE80211_RATE_SIZE8)
2338 frm = ieee80211_add_xrates(frm, rs);
2339 len = frm - req.data.u_data.var;
2340
2341 return (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_REQ0x16, &req,
2342 ACX_TMPLT_PROBE_REQ_SIZ(len)(sizeof(uint16_t) + sizeof(struct ieee80211_frame) + (len))));
2343}
2344
2345#ifndef IEEE80211_STA_ONLY
2346struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
2347 struct ieee80211_node *);
2348
2349int
2350acx_set_probe_resp_tmplt(struct acx_softc *sc, struct ieee80211_node *ni)
2351{
2352 struct ieee80211com *ic = &sc->sc_ic;
2353 struct acx_tmplt_probe_resp resp;
2354 struct ieee80211_frame *wh;
2355 struct mbuf *m;
2356 int len;
2357
2358 bzero(&resp, sizeof(resp))__builtin_bzero((&resp), (sizeof(resp)));
2359
2360 m = ieee80211_get_probe_resp(ic, ni);
2361 if (m == NULL((void *)0))
2362 return (1);
2363 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT)(m) = m_prepend((m), (sizeof(struct ieee80211_frame)), (0x0002
))
;
2364 if (m == NULL((void *)0))
2365 return (1);
2366 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2367 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
2368 IEEE80211_FC0_SUBTYPE_PROBE_RESP0x50;
2369 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
2370 *(u_int16_t *)&wh->i_dur[0] = 0;
2371 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr)__builtin_memcpy((wh->i_addr1), (ni->ni_macaddr), (6));
2372 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr)__builtin_memcpy((wh->i_addr2), (ic->ic_myaddr), (6));
2373 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid)__builtin_memcpy((wh->i_addr3), (ni->ni_bssid), (6));
2374 *(u_int16_t *)wh->i_seq = 0;
2375
2376 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &resp.data);
2377 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len + sizeof(resp.size);
2378 m_freem(m);
2379
2380 return (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_RESP0x14, &resp, len));
2381}
2382
2383int
2384acx_beacon_locate(struct mbuf *m, u_int8_t type)
2385{
2386 int off;
2387 u_int8_t *frm;
2388 /*
2389 * beacon frame format
2390 * [8] time stamp
2391 * [2] beacon interval
2392 * [2] capability information
2393 * from here on [tlv] values
2394 */
2395
2396 if (m->m_lenm_hdr.mh_len != m->m_pkthdrM_dat.MH.MH_pkthdr.len)
2397 panic("beacon not in contiguous mbuf");
2398
2399 off = sizeof(struct ieee80211_frame) + 8 + 2 + 2;
2400 frm = mtod(m, u_int8_t *)((u_int8_t *)((m)->m_hdr.mh_data));
2401 for (; off + 1 < m->m_lenm_hdr.mh_len; off += frm[off + 1] + 2) {
2402 if (frm[off] == type)
2403 return (off);
2404 }
2405 return (-1);
2406}
2407
2408int
2409acx_set_beacon_tmplt(struct acx_softc *sc, struct ieee80211_node *ni)
2410{
2411 struct ieee80211com *ic = &sc->sc_ic;
2412 struct acx_tmplt_beacon beacon;
2413 struct acx_tmplt_tim tim;
2414 struct mbuf *m;
2415 int len, off;
2416
2417 bzero(&beacon, sizeof(beacon))__builtin_bzero((&beacon), (sizeof(beacon)));
2418 bzero(&tim, sizeof(tim))__builtin_bzero((&tim), (sizeof(tim)));
2419
2420 m = ieee80211_beacon_alloc(ic, ni);
2421 if (m == NULL((void *)0))
2422 return (1);
2423
2424 off = acx_beacon_locate(m, IEEE80211_ELEMID_TIM);
2425 if (off < 0) {
2426 m_free(m);
2427 return (1);
2428 }
2429
2430 m_copydata(m, 0, off, &beacon.data);
2431 len = off + sizeof(beacon.size);
2432
2433 if (acx_set_tmplt(sc, ACXCMD_TMPLT_BEACON0x13, &beacon, len) != 0) {
2434 m_freem(m);
2435 return (1);
2436 }
2437
2438 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len - off;
2439 if (len == 0) {
2440 /* no TIM field */
2441 m_freem(m);
2442 return (0);
2443 }
2444
2445 m_copydata(m, off, len, &tim.data);
2446 len += sizeof(beacon.size);
2447 m_freem(m);
2448
2449 return (acx_set_tmplt(sc, ACXCMD_TMPLT_TIM0x0a, &tim, len));
2450}
2451#endif /* IEEE80211_STA_ONLY */
2452
2453void
2454acx_init_cmd_reg(struct acx_softc *sc)
2455{
2456 sc->sc_cmd = CSR_READ_4(sc, ACXREG_CMD_REG_OFFSET)(((sc)->sc_mem1_bt)->read_4(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(24)])))
;
2457 sc->sc_cmd_param = sc->sc_cmd + ACX_CMD_REG_SIZE4;
2458
2459 /* Clear command & status */
2460 CMD_WRITE_4(sc, 0)(((sc)->sc_mem2_bt)->write_4(((sc)->sc_mem2_bh), ((sc
)->sc_cmd), ((0))))
;
2461}
2462
2463int
2464acx_join_bss(struct acx_softc *sc, uint8_t mode, struct ieee80211_node *node)
2465{
2466 uint8_t bj_buf[BSS_JOIN_BUFLEN(sizeof(struct bss_join_hdr) + 32 - 1)];
2467 struct bss_join_hdr *bj;
2468 int i, dtim_intvl;
2469
2470 bzero(bj_buf, sizeof(bj_buf))__builtin_bzero((bj_buf), (sizeof(bj_buf)));
2471 bj = (struct bss_join_hdr *)bj_buf;
2472
2473 for (i = 0; i < IEEE80211_ADDR_LEN6; ++i)
2474 bj->bssid[i] = node->ni_bssid[IEEE80211_ADDR_LEN6 - i - 1];
2475
2476 bj->beacon_intvl = htole16(acx_beacon_intvl)((__uint16_t)(acx_beacon_intvl));
2477
2478 /* TODO tunable */
2479#ifndef IEEE80211_STA_ONLY
2480 if (sc->sc_ic.ic_opmode == IEEE80211_M_IBSS)
2481 dtim_intvl = 1;
2482 else
2483#endif
2484 dtim_intvl = 10;
2485 sc->chip_set_bss_join_param(sc, bj->chip_spec, dtim_intvl);
2486
2487 bj->ndata_txrate = ACX_NDATA_TXRATE_110;
2488 bj->ndata_txopt = 0;
2489 bj->mode = mode;
2490 bj->channel = ieee80211_chan2ieee(&sc->sc_ic, node->ni_chan);
2491 bj->esslen = node->ni_esslen;
2492 bcopy(node->ni_essid, bj->essid, node->ni_esslen);
2493
2494 DPRINTF(("%s: join BSS/IBSS on channel %d\n", sc->sc_dev.dv_xname,
2495 bj->channel));
2496 return (acx_exec_command(sc, ACXCMD_JOIN_BSS0x0b,
2497 bj, BSS_JOIN_PARAM_SIZE(bj)(sizeof(struct bss_join_hdr) + (bj)->esslen - 1), NULL((void *)0), 0));
2498}
2499
2500int
2501acx_set_channel(struct acx_softc *sc, uint8_t chan)
2502{
2503 if (acx_exec_command(sc, ACXCMD_ENABLE_TXCHAN0x04, &chan, sizeof(chan),
2504 NULL((void *)0), 0) != 0) {
2505 DPRINTF(("%s: setting TX channel %d failed\n",
2506 sc->sc_dev.dv_xname, chan));
2507 return (ENXIO6);
2508 }
2509
2510 if (acx_exec_command(sc, ACXCMD_ENABLE_RXCHAN0x03, &chan, sizeof(chan),
2511 NULL((void *)0), 0) != 0) {
2512 DPRINTF(("%s: setting RX channel %d failed\n",
2513 sc->sc_dev.dv_xname, chan));
2514 return (ENXIO6);
2515 }
2516
2517 return (0);
2518}
2519
2520int
2521acx_get_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
2522 uint16_t conf_len)
2523{
2524 struct acx_conf *confcom;
2525
2526 if (conf_len < sizeof(*confcom)) {
2527 printf("%s: %s configure data is too short\n",
2528 sc->sc_dev.dv_xname, __func__);
2529 return (1);
2530 }
2531
2532 confcom = conf;
2533 confcom->conf_id = htole16(conf_id)((__uint16_t)(conf_id));
2534 confcom->conf_data_len = htole16(conf_len - sizeof(*confcom))((__uint16_t)(conf_len - sizeof(*confcom)));
2535
2536 return (acx_exec_command(sc, ACXCMD_GET_CONF0x01, confcom, sizeof(*confcom),
2537 conf, conf_len));
2538}
2539
2540int
2541acx_set_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
2542 uint16_t conf_len)
2543{
2544 struct acx_conf *confcom;
2545
2546 if (conf_len < sizeof(*confcom)) {
2547 printf("%s: %s configure data is too short\n",
2548 sc->sc_dev.dv_xname, __func__);
2549 return (1);
2550 }
2551
2552 confcom = conf;
2553 confcom->conf_id = htole16(conf_id)((__uint16_t)(conf_id));
2554 confcom->conf_data_len = htole16(conf_len - sizeof(*confcom))((__uint16_t)(conf_len - sizeof(*confcom)));
2555
2556 return (acx_exec_command(sc, ACXCMD_SET_CONF0x02, conf, conf_len, NULL((void *)0), 0));
2557}
2558
2559int
2560acx_set_tmplt(struct acx_softc *sc, uint16_t cmd, void *tmplt,
2561 uint16_t tmplt_len)
2562{
2563 uint16_t *size;
2564
2565 if (tmplt_len < sizeof(*size)) {
2566 printf("%s: %s template is too short\n",
2567 sc->sc_dev.dv_xname, __func__);
2568 return (1);
2569 }
2570
2571 size = tmplt;
2572 *size = htole16(tmplt_len - sizeof(*size))((__uint16_t)(tmplt_len - sizeof(*size)));
2573
2574 return (acx_exec_command(sc, cmd, tmplt, tmplt_len, NULL((void *)0), 0));
2575}
2576
2577int
2578acx_init_radio(struct acx_softc *sc, uint32_t radio_ofs, uint32_t radio_len)
2579{
2580 struct radio_init r;
2581
2582 r.radio_ofs = htole32(radio_ofs)((__uint32_t)(radio_ofs));
2583 r.radio_len = htole32(radio_len)((__uint32_t)(radio_len));
2584
2585 return (acx_exec_command(sc, ACXCMD_INIT_RADIO0x18, &r, sizeof(r), NULL((void *)0),
2586 0));
2587}
2588
2589int
2590acx_exec_command(struct acx_softc *sc, uint16_t cmd, void *param,
2591 uint16_t param_len, void *result, uint16_t result_len)
2592{
2593 uint16_t status;
2594 int i, ret;
2595
2596 if ((sc->sc_flags & ACX_FLAG_FW_LOADED0x01) == 0) {
2597 printf("%s: cmd 0x%04x failed (base firmware not loaded)\n",
2598 sc->sc_dev.dv_xname, cmd);
2599 return (1);
2600 }
2601
2602 ret = 0;
2603
2604 if (param != NULL((void *)0) && param_len != 0) {
2605 /* Set command param */
2606 CMDPRM_WRITE_REGION_1(sc, param, param_len)(((sc)->sc_mem2_bt)->write_region_1(((sc)->sc_mem2_bh
), ((sc)->sc_cmd_param), ((const uint8_t *)(param)), ((param_len
))))
;
2607 }
2608
2609 /* Set command */
2610 CMD_WRITE_4(sc, cmd)(((sc)->sc_mem2_bt)->write_4(((sc)->sc_mem2_bh), ((sc
)->sc_cmd), ((cmd))))
;
2611
2612 /* Exec command */
2613 CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_CMD_FINI)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(6)]), (0x0001)))
;
2614 DELAY(50)(*delay_func)(50);
2615
2616 /* Wait for command to complete */
2617 if (cmd == ACXCMD_INIT_RADIO0x18) {
2618 /* radio initialization is extremely long */
2619 tsleep_nsec(&cmd, 0, "rdinit", MSEC_TO_NSEC(300));
2620 }
2621
2622#define CMDWAIT_RETRY_MAX 1000
2623 for (i = 0; i < CMDWAIT_RETRY_MAX; ++i) {
2624 uint16_t reg;
2625
2626 reg = CSR_READ_2(sc, ACXREG_INTR_STATUS)(((sc)->sc_mem1_bt)->read_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(8)])))
;
2627 if (reg & ACXRV_INTR_CMD_FINI0x0200) {
2628 CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_CMD_FINI)(((sc)->sc_mem1_bt)->write_2(((sc)->sc_mem1_bh), ((sc
)->chip_ioreg[(10)]), (0x0200)))
;
2629 break;
2630 }
2631 DELAY(50)(*delay_func)(50);
2632 }
2633 if (i == CMDWAIT_RETRY_MAX) {
2634 printf("%s: cmd %04x failed (timeout)\n",
2635 sc->sc_dev.dv_xname, cmd);
2636 ret = 1;
2637 goto back;
2638 }
2639#undef CMDWAIT_RETRY_MAX
2640
2641 /* Get command exec status */
2642 status = (CMD_READ_4(sc)(((sc)->sc_mem2_bt)->read_4(((sc)->sc_mem2_bh), ((sc
)->sc_cmd)))
>> ACX_CMD_STATUS_SHIFT16);
2643 if (status != ACX_CMD_STATUS_OK1) {
2644 DPRINTF(("%s: cmd %04x failed\n", sc->sc_dev.dv_xname, cmd));
2645 ret = 1;
2646 goto back;
2647 }
2648
2649 if (result != NULL((void *)0) && result_len != 0) {
2650 /* Get command result */
2651 CMDPRM_READ_REGION_1(sc, result, result_len)(((sc)->sc_mem2_bt)->read_region_1(((sc)->sc_mem2_bh
), ((sc)->sc_cmd_param), ((uint8_t *)(result)), ((result_len
))))
;
2652 }
2653
2654back:
2655 CMD_WRITE_4(sc, 0)(((sc)->sc_mem2_bt)->write_4(((sc)->sc_mem2_bh), ((sc
)->sc_cmd), ((0))))
;
2656
2657 return (ret);
2658}
2659
2660const char *
2661acx_get_rf(int rev)
2662{
2663 switch (rev) {
2664 case ACX_RADIO_TYPE_MAXIM0x0d: return "MAX2820";
2665 case ACX_RADIO_TYPE_RFMD0x11: return "RFMD";
2666 case ACX_RADIO_TYPE_RALINK0x15: return "Ralink";
2667 case ACX_RADIO_TYPE_RADIA0x16: return "Radia";
2668 default: return "unknown";
2669 }
2670}
2671
2672int
2673acx_get_maxrssi(int radio)
2674{
2675 switch (radio) {
2676 case ACX_RADIO_TYPE_MAXIM0x0d: return ACX_RADIO_RSSI_MAXIM120;
2677 case ACX_RADIO_TYPE_RFMD0x11: return ACX_RADIO_RSSI_RFMD215;
2678 case ACX_RADIO_TYPE_RALINK0x15: return ACX_RADIO_RSSI_RALINK0;
2679 case ACX_RADIO_TYPE_RADIA0x16: return ACX_RADIO_RSSI_RADIA78;
2680 default: return ACX_RADIO_RSSI_UNKN0;
2681 }
2682}
2683
2684void
2685acx_iter_func(void *arg, struct ieee80211_node *ni)
2686{
2687 struct acx_softc *sc = arg;
2688 struct acx_node *wn = (struct acx_node *)ni;
2689
2690 ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
2691}
2692
2693void
2694acx_amrr_timeout(void *arg)
2695{
2696 struct acx_softc *sc = arg;
2697 struct ieee80211com *ic = &sc->sc_ic;
2698
2699 if (ic->ic_opmode == IEEE80211_M_STA)
2700 acx_iter_func(sc, ic->ic_bss);
2701 else
2702 ieee80211_iterate_nodes(ic, acx_iter_func, sc);
2703
2704 timeout_add_msec(&sc->amrr_ch, 500);
2705}
2706
2707void
2708acx_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
2709{
2710 struct acx_softc *sc = ic->ic_ific_ac.ac_if.if_softc;
2711 int i;
2712
2713 ieee80211_amrr_node_init(&sc->amrr, &((struct acx_node *)ni)->amn);
2714
2715 /* set rate to some reasonable initial value */
2716 for (i = ni->ni_rates.rs_nrates - 1;
2717 i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL0x7f) > 72;
2718 i--);
2719 ni->ni_txrate = i;
2720}
2721
2722#ifndef IEEE80211_STA_ONLY
2723void
2724acx_set_tim(struct ieee80211com *ic, int aid, int set)
2725{
2726 struct acx_softc *sc = ic->ic_ific_ac.ac_if.if_softc;
2727 struct acx_tmplt_tim tim;
2728 u_int8_t *ep;
2729
2730 ieee80211_set_tim(ic, aid, set);
2731
2732 bzero(&tim, sizeof(tim))__builtin_bzero((&tim), (sizeof(tim)));
2733 ep = ieee80211_add_tim(tim.data.u_mem, ic);
2734
2735 acx_set_tmplt(sc, ACXCMD_TMPLT_TIM0x0a, &tim, ep - (u_int8_t *)&tim);
2736}
2737#endif