Annotation of sys/dev/ic/acx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acx.c,v 1.76 2007/08/05 22:40:38 claudio 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 <sys/cdefs.h>
90: #include "bpfilter.h"
91:
92: #include <sys/param.h>
93: #include <sys/systm.h>
94: #include <sys/kernel.h>
95: #include <sys/malloc.h>
96: #include <sys/mbuf.h>
97: #include <sys/proc.h>
98: #include <sys/socket.h>
99: #include <sys/sockio.h>
100: #include <sys/ioctl.h>
101: #include <sys/types.h>
102:
103: #include <machine/bus.h>
104: #include <machine/endian.h>
105: #include <machine/intr.h>
106:
107: #include <net/if.h>
108: #include <net/if_arp.h>
109: #include <net/if_dl.h>
110: #include <net/if_media.h>
111: #include <net/if_types.h>
112:
113: #if NBPFILTER > 0
114: #include <net/bpf.h>
115: #endif
116:
117: #ifdef INET
118: #include <netinet/in.h>
119: #include <netinet/in_systm.h>
120: #include <netinet/in_var.h>
121: #include <netinet/if_ether.h>
122: #include <netinet/ip.h>
123: #endif
124:
125: #include <net80211/ieee80211_var.h>
126: #include <net80211/ieee80211_amrr.h>
127: #include <net80211/ieee80211_radiotap.h>
128:
129: #include <dev/pci/pcireg.h>
130: #include <dev/pci/pcivar.h>
131: #include <dev/pci/pcidevs.h>
132:
133: #include <dev/ic/acxvar.h>
134: #include <dev/ic/acxreg.h>
135:
136: #ifdef ACX_DEBUG
137: int acxdebug = 0;
138: #endif
139:
140: int acx_attach(struct acx_softc *);
141: int acx_detach(void *);
142:
143: int acx_init(struct ifnet *);
144: int acx_stop(struct acx_softc *);
145: void acx_init_info_reg(struct acx_softc *);
146: int acx_config(struct acx_softc *);
147: int acx_read_config(struct acx_softc *, struct acx_config *);
148: int acx_write_config(struct acx_softc *, struct acx_config *);
149: int acx_rx_config(struct acx_softc *);
150: int acx_set_crypt_keys(struct acx_softc *);
151: void acx_next_scan(void *);
152:
153: void acx_start(struct ifnet *);
154: void acx_watchdog(struct ifnet *);
155:
156: int acx_ioctl(struct ifnet *, u_long, caddr_t);
157:
158: int acx_intr(void *);
159: void acx_disable_intr(struct acx_softc *);
160: void acx_enable_intr(struct acx_softc *);
161: void acx_txeof(struct acx_softc *);
162: void acx_txerr(struct acx_softc *, uint8_t);
163: void acx_rxeof(struct acx_softc *);
164:
165: int acx_dma_alloc(struct acx_softc *);
166: void acx_dma_free(struct acx_softc *);
167: int acx_init_tx_ring(struct acx_softc *);
168: int acx_init_rx_ring(struct acx_softc *);
169: int acx_newbuf(struct acx_softc *, struct acx_rxbuf *, int);
170: int acx_encap(struct acx_softc *, struct acx_txbuf *,
171: struct mbuf *, struct ieee80211_node *, int);
172:
173: int acx_reset(struct acx_softc *);
174:
175: int acx_set_null_tmplt(struct acx_softc *);
176: int acx_set_probe_req_tmplt(struct acx_softc *, const char *, int);
177: int acx_set_probe_resp_tmplt(struct acx_softc *, struct ieee80211_node *);
178: int acx_beacon_locate(struct mbuf *, u_int8_t);
179: int acx_set_beacon_tmplt(struct acx_softc *, struct ieee80211_node *);
180:
181: int acx_read_eeprom(struct acx_softc *, uint32_t, uint8_t *);
182: int acx_read_phyreg(struct acx_softc *, uint32_t, uint8_t *);
183: const char * acx_get_rf(int);
184: int acx_get_maxrssi(int);
185:
186: int acx_load_firmware(struct acx_softc *, uint32_t,
187: const uint8_t *, int);
188: int acx_load_radio_firmware(struct acx_softc *, const char *);
189: int acx_load_base_firmware(struct acx_softc *, const char *);
190:
191: struct ieee80211_node
192: *acx_node_alloc(struct ieee80211com *);
193: int acx_newstate(struct ieee80211com *, enum ieee80211_state, int);
194:
195: void acx_init_cmd_reg(struct acx_softc *);
196: int acx_join_bss(struct acx_softc *, uint8_t, struct ieee80211_node *);
197: int acx_set_channel(struct acx_softc *, uint8_t);
198: int acx_init_radio(struct acx_softc *, uint32_t, uint32_t);
199:
200: void acx_iter_func(void *, struct ieee80211_node *);
201: void acx_amrr_timeout(void *);
202: void acx_newassoc(struct ieee80211com *, struct ieee80211_node *, int);
203:
204: static int acx_chanscan_rate = 5; /* 5 channels per second */
205: int acx_beacon_intvl = 100; /* 100 TU */
206:
207: /*
208: * Possible values for the second parameter of acx_join_bss()
209: */
210: #define ACX_MODE_ADHOC 0
211: #define ACX_MODE_UNUSED 1
212: #define ACX_MODE_STA 2
213: #define ACX_MODE_AP 3
214:
215: struct cfdriver acx_cd = {
216: NULL, "acx", DV_IFNET
217: };
218:
219: int
220: acx_attach(struct acx_softc *sc)
221: {
222: struct ieee80211com *ic = &sc->sc_ic;
223: struct ifnet *ifp = &sc->sc_ic.ic_if;
224: int i, error;
225:
226: ifp->if_softc = sc;
227:
228: /* Initialize channel scanning timer */
229: timeout_set(&sc->sc_chanscan_timer, acx_next_scan, sc);
230:
231: /* Allocate busdma stuffs */
232: error = acx_dma_alloc(sc);
233: if (error)
234: return (error);
235:
236: /* Reset Hardware */
237: error = acx_reset(sc);
238: if (error)
239: return (error);
240:
241: /* Disable interrupts before firmware is loaded */
242: acx_disable_intr(sc);
243:
244: /* Get radio type and form factor */
245: #define EEINFO_RETRY_MAX 50
246: for (i = 0; i < EEINFO_RETRY_MAX; ++i) {
247: uint16_t ee_info;
248:
249: ee_info = CSR_READ_2(sc, ACXREG_EEPROM_INFO);
250: if (ACX_EEINFO_HAS_RADIO_TYPE(ee_info)) {
251: sc->sc_form_factor = ACX_EEINFO_FORM_FACTOR(ee_info);
252: sc->sc_radio_type = ACX_EEINFO_RADIO_TYPE(ee_info);
253: break;
254: }
255: DELAY(10000);
256: }
257: if (i == EEINFO_RETRY_MAX)
258: return (ENXIO);
259: #undef EEINFO_RETRY_MAX
260:
261: printf("%s: %s, radio %s (0x%02x)", sc->sc_dev.dv_xname,
262: (sc->sc_flags & ACX_FLAG_ACX111) ? "ACX111" : "ACX100",
263: acx_get_rf(sc->sc_radio_type), sc->sc_radio_type);
264:
265: #ifdef DUMP_EEPROM
266: for (i = 0; i < 0x40; ++i) {
267: uint8_t val;
268:
269: error = acx_read_eeprom(sc, i, &val);
270: if (i % 10 == 0)
271: printf("\n");
272: printf("%02x ", val);
273: }
274: printf("\n");
275: #endif /* DUMP_EEPROM */
276:
277: /* Get EEPROM version */
278: error = acx_read_eeprom(sc, ACX_EE_VERSION_OFS, &sc->sc_eeprom_ver);
279: if (error)
280: return (error);
281:
282: printf(", EEPROM ver %u", sc->sc_eeprom_ver);
283:
284: ifp->if_softc = sc;
285: ifp->if_init = acx_init;
286: ifp->if_ioctl = acx_ioctl;
287: ifp->if_start = acx_start;
288: ifp->if_watchdog = acx_watchdog;
289: ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
290: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
291: IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
292: IFQ_SET_READY(&ifp->if_snd);
293:
294: /* Set channels */
295: for (i = 1; i <= 14; ++i) {
296: ic->ic_channels[i].ic_freq =
297: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
298: ic->ic_channels[i].ic_flags = sc->chip_chan_flags;
299: }
300:
301: ic->ic_opmode = IEEE80211_M_STA;
302: ic->ic_state = IEEE80211_S_INIT;
303:
304: /*
305: * NOTE: Don't overwrite ic_caps set by chip specific code
306: */
307: ic->ic_caps =
308: IEEE80211_C_WEP | /* WEP */
309: IEEE80211_C_IBSS | /* IBSS mode */
310: IEEE80211_C_MONITOR | /* Monitor mode */
311: IEEE80211_C_HOSTAP | /* Access Point */
312: IEEE80211_C_SHPREAMBLE; /* Short preamble */
313:
314: /* Get station id */
315: for (i = 0; i < IEEE80211_ADDR_LEN; ++i) {
316: error = acx_read_eeprom(sc, sc->chip_ee_eaddr_ofs - i,
317: &ic->ic_myaddr[i]);
318: }
319:
320: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
321:
322: if_attach(ifp);
323: ieee80211_ifattach(ifp);
324:
325: /* Override node alloc */
326: ic->ic_node_alloc = acx_node_alloc;
327: ic->ic_newassoc = acx_newassoc;
328:
329: /* Override newstate */
330: sc->sc_newstate = ic->ic_newstate;
331: ic->ic_newstate = acx_newstate;
332:
333: /* Set maximal rssi */
334: ic->ic_max_rssi = acx_get_maxrssi(sc->sc_radio_type);
335:
336: ieee80211_media_init(ifp, ieee80211_media_change,
337: ieee80211_media_status);
338:
339: /* AMRR rate control */
340: sc->amrr.amrr_min_success_threshold = 1;
341: sc->amrr.amrr_max_success_threshold = 15;
342: timeout_set(&sc->amrr_ch, acx_amrr_timeout, sc);
343:
344: sc->sc_long_retry_limit = 4;
345: sc->sc_short_retry_limit = 7;
346: sc->sc_msdu_lifetime = 4096;
347:
348: #if NBPFILTER > 0
349: bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
350: sizeof(struct ieee80211_frame) + 64);
351:
352: sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
353: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
354: sc->sc_rxtap.wr_ihdr.it_present = htole32(ACX_RX_RADIOTAP_PRESENT);
355:
356: sc->sc_txtap_len = sizeof(sc->sc_txtapu);
357: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
358: sc->sc_txtap.wt_ihdr.it_present = htole32(ACX_TX_RADIOTAP_PRESENT);
359: #endif
360:
361: return (0);
362: }
363:
364: int
365: acx_detach(void *xsc)
366: {
367: struct acx_softc *sc = xsc;
368: struct ieee80211com *ic = &sc->sc_ic;
369: struct ifnet *ifp = &ic->ic_if;
370:
371: acx_stop(sc);
372: ieee80211_ifdetach(ifp);
373: if_detach(ifp);
374:
375: acx_dma_free(sc);
376:
377: return (0);
378: }
379:
380: int
381: acx_init(struct ifnet *ifp)
382: {
383: struct acx_softc *sc = ifp->if_softc;
384: struct ieee80211com *ic = &sc->sc_ic;
385: char fname[] = "tiacx111c16";
386: int error, combined = 0;
387:
388: error = acx_stop(sc);
389: if (error)
390: return (EIO);
391:
392: /* enable card if possible */
393: if (sc->sc_enable != NULL)
394: (*sc->sc_enable)(sc);
395:
396: error = acx_init_tx_ring(sc);
397: if (error) {
398: printf("%s: can't initialize TX ring\n",
399: sc->sc_dev.dv_xname);
400: goto back;
401: }
402:
403: error = acx_init_rx_ring(sc);
404: if (error) {
405: printf("%s: can't initialize RX ring\n",
406: sc->sc_dev.dv_xname);
407: goto back;
408: }
409:
410: if (sc->sc_flags & ACX_FLAG_ACX111) {
411: snprintf(fname, sizeof(fname), "tiacx111c%02X",
412: sc->sc_radio_type);
413: error = acx_load_base_firmware(sc, fname);
414:
415: if (!error)
416: combined = 1;
417: }
418:
419: if (!combined) {
420: snprintf(fname, sizeof(fname), "tiacx%s",
421: (sc->sc_flags & ACX_FLAG_ACX111) ? "111" : "100");
422: error = acx_load_base_firmware(sc, fname);
423: }
424:
425: if (error)
426: goto back;
427:
428: /*
429: * Initialize command and information registers
430: * NOTE: This should be done after base firmware is loaded
431: */
432: acx_init_cmd_reg(sc);
433: acx_init_info_reg(sc);
434:
435: sc->sc_flags |= ACX_FLAG_FW_LOADED;
436:
437: if (!combined) {
438: snprintf(fname, sizeof(fname), "tiacx%sr%02X",
439: (sc->sc_flags & ACX_FLAG_ACX111) ? "111" : "100",
440: sc->sc_radio_type);
441: error = acx_load_radio_firmware(sc, fname);
442:
443: if (error)
444: goto back;
445: }
446:
447: error = sc->chip_init(sc);
448: if (error)
449: goto back;
450:
451: /* Get and set device various configuration */
452: error = acx_config(sc);
453: if (error)
454: goto back;
455:
456: /* Setup crypto stuffs */
457: if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
458: error = acx_set_crypt_keys(sc);
459: if (error)
460: goto back;
461: }
462:
463: /* Turn on power led */
464: CSR_CLRB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled);
465:
466: acx_enable_intr(sc);
467:
468: ifp->if_flags |= IFF_RUNNING;
469: ifp->if_flags &= ~IFF_OACTIVE;
470:
471: if (ic->ic_opmode != IEEE80211_M_MONITOR)
472: /* start background scanning */
473: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
474: else
475: /* in monitor mode change directly into run state */
476: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
477:
478: back:
479: if (error)
480: acx_stop(sc);
481:
482: return (0);
483: }
484:
485: void
486: acx_init_info_reg(struct acx_softc *sc)
487: {
488: sc->sc_info = CSR_READ_4(sc, ACXREG_INFO_REG_OFFSET);
489: sc->sc_info_param = sc->sc_info + ACX_INFO_REG_SIZE;
490: }
491:
492: int
493: acx_set_crypt_keys(struct acx_softc *sc)
494: {
495: struct ieee80211com *ic = &sc->sc_ic;
496: struct acx_conf_wep_txkey wep_txkey;
497: int i, error, got_wk = 0;
498:
499: for (i = 0; i < IEEE80211_WEP_NKID; ++i) {
500: struct ieee80211_key *k = &ic->ic_nw_keys[i];
501:
502: if (k->k_len == 0)
503: continue;
504:
505: if (sc->chip_hw_crypt) {
506: error = sc->chip_set_wepkey(sc, k, i);
507: if (error)
508: return (error);
509: got_wk = 1;
510: }
511: }
512:
513: if (!got_wk)
514: return (0);
515:
516: /* Set current WEP key index */
517: wep_txkey.wep_txkey = ic->ic_wep_txkey;
518: if (acx_set_conf(sc, ACX_CONF_WEP_TXKEY, &wep_txkey,
519: sizeof(wep_txkey)) != 0) {
520: printf("%s: set WEP txkey failed\n", sc->sc_dev.dv_xname);
521: return (ENXIO);
522: }
523:
524: return (0);
525: }
526:
527: void
528: acx_next_scan(void *arg)
529: {
530: struct acx_softc *sc = arg;
531: struct ieee80211com *ic = &sc->sc_ic;
532: struct ifnet *ifp = &ic->ic_if;
533:
534: if (ic->ic_state == IEEE80211_S_SCAN)
535: ieee80211_next_scan(ifp);
536: }
537:
538: int
539: acx_stop(struct acx_softc *sc)
540: {
541: struct ieee80211com *ic = &sc->sc_ic;
542: struct ifnet *ifp = &ic->ic_if;
543: struct acx_buf_data *bd = &sc->sc_buf_data;
544: struct acx_ring_data *rd = &sc->sc_ring_data;
545: int i, error;
546:
547: sc->sc_firmware_ver = 0;
548: sc->sc_hardware_id = 0;
549:
550: /* Reset hardware */
551: error = acx_reset(sc);
552: if (error)
553: return (error);
554:
555: /* Firmware no longer functions after hardware reset */
556: sc->sc_flags &= ~ACX_FLAG_FW_LOADED;
557:
558: acx_disable_intr(sc);
559:
560: /* Stop backgroud scanning */
561: timeout_del(&sc->sc_chanscan_timer);
562:
563: /* Turn off power led */
564: CSR_SETB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled);
565:
566: /* Free TX mbuf */
567: for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
568: struct acx_txbuf *buf;
569: struct ieee80211_node *ni;
570:
571: buf = &bd->tx_buf[i];
572:
573: if (buf->tb_mbuf != NULL) {
574: bus_dmamap_unload(sc->sc_dmat, buf->tb_mbuf_dmamap);
575: m_freem(buf->tb_mbuf);
576: buf->tb_mbuf = NULL;
577: }
578:
579: ni = (struct ieee80211_node *)buf->tb_node;
580: if (ni != NULL)
581: ieee80211_release_node(ic, ni);
582: buf->tb_node = NULL;
583: }
584:
585: /* Clear TX host descriptors */
586: bzero(rd->tx_ring, ACX_TX_RING_SIZE);
587:
588: /* Free RX mbuf */
589: for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
590: if (bd->rx_buf[i].rb_mbuf != NULL) {
591: bus_dmamap_unload(sc->sc_dmat,
592: bd->rx_buf[i].rb_mbuf_dmamap);
593: m_freem(bd->rx_buf[i].rb_mbuf);
594: bd->rx_buf[i].rb_mbuf = NULL;
595: }
596: }
597:
598: /* Clear RX host descriptors */
599: bzero(rd->rx_ring, ACX_RX_RING_SIZE);
600:
601: ifp->if_timer = 0;
602: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
603: ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
604:
605: /* disable card if possible */
606: if (sc->sc_disable != NULL)
607: (*sc->sc_disable)(sc);
608:
609: return (0);
610: }
611:
612: int
613: acx_config(struct acx_softc *sc)
614: {
615: struct acx_config conf;
616: int error;
617:
618: error = acx_read_config(sc, &conf);
619: if (error)
620: return (error);
621:
622: error = acx_write_config(sc, &conf);
623: if (error)
624: return (error);
625:
626: error = acx_rx_config(sc);
627: if (error)
628: return (error);
629:
630: if (acx_set_probe_req_tmplt(sc, "", 0) != 0) {
631: printf("%s: can't set probe req template "
632: "(empty ssid)\n", sc->sc_dev.dv_xname);
633: return (ENXIO);
634: }
635:
636: /* XXX for PM?? */
637: if (acx_set_null_tmplt(sc) != 0) {
638: printf("%s: can't set null data template\n",
639: sc->sc_dev.dv_xname);
640: return (ENXIO);
641: }
642:
643: return (0);
644: }
645:
646: int
647: acx_read_config(struct acx_softc *sc, struct acx_config *conf)
648: {
649: struct acx_conf_regdom reg_dom;
650: struct acx_conf_antenna ant;
651: struct acx_conf_fwrev fw_rev;
652: uint32_t fw_rev_no;
653: uint8_t sen;
654: int error;
655:
656: /* Get region domain */
657: if (acx_get_conf(sc, ACX_CONF_REGDOM, ®_dom, sizeof(reg_dom)) != 0) {
658: printf("%s: can't get region domain\n", sc->sc_dev.dv_xname);
659: return (ENXIO);
660: }
661: conf->regdom = reg_dom.regdom;
662: DPRINTF(("%s: regdom %02x\n", sc->sc_dev.dv_xname, reg_dom.regdom));
663:
664: /* Get antenna */
665: if (acx_get_conf(sc, ACX_CONF_ANTENNA, &ant, sizeof(ant)) != 0) {
666: printf("%s: can't get antenna\n", sc->sc_dev.dv_xname);
667: return (ENXIO);
668: }
669: conf->antenna = ant.antenna;
670: DPRINTF(("%s: antenna %02x\n", sc->sc_dev.dv_xname, ant.antenna));
671:
672: /* Get sensitivity XXX not used */
673: if (sc->sc_radio_type == ACX_RADIO_TYPE_MAXIM ||
674: sc->sc_radio_type == ACX_RADIO_TYPE_RFMD ||
675: sc->sc_radio_type == ACX_RADIO_TYPE_RALINK) {
676: error = acx_read_phyreg(sc, ACXRV_PHYREG_SENSITIVITY, &sen);
677: if (error) {
678: printf("%s: can't get sensitivity\n",
679: sc->sc_dev.dv_xname);
680: return (error);
681: }
682: } else
683: sen = 0;
684: DPRINTF(("%s: sensitivity %02x\n", sc->sc_dev.dv_xname, sen));
685:
686: /* Get firmware revision */
687: if (acx_get_conf(sc, ACX_CONF_FWREV, &fw_rev, sizeof(fw_rev)) != 0) {
688: printf("%s: can't get firmware revision\n",
689: sc->sc_dev.dv_xname);
690: return (ENXIO);
691: }
692:
693: if (strncmp(fw_rev.fw_rev, "Rev ", 4) != 0) {
694: printf("%s: strange revision string -- %s\n",
695: sc->sc_dev.dv_xname, fw_rev.fw_rev);
696: fw_rev_no = 0x01090407;
697: } else {
698: /*
699: * 01234
700: * "Rev xx.xx.xx.xx"
701: * ^ Start from here
702: */
703: fw_rev_no = fw_rev.fw_rev[0] << 24;
704: fw_rev_no |= fw_rev.fw_rev[1] << 16;
705: fw_rev_no |= fw_rev.fw_rev[2] << 8;
706: fw_rev_no |= fw_rev.fw_rev[3];
707: }
708: sc->sc_firmware_ver = fw_rev_no;
709: sc->sc_hardware_id = letoh32(fw_rev.hw_id);
710: DPRINTF(("%s: fw rev %08x, hw id %08x\n",
711: sc->sc_dev.dv_xname, sc->sc_firmware_ver, sc->sc_hardware_id));
712:
713: if (sc->chip_read_config != NULL) {
714: error = sc->chip_read_config(sc, conf);
715: if (error)
716: return (error);
717: }
718:
719: return (0);
720: }
721:
722: int
723: acx_write_config(struct acx_softc *sc, struct acx_config *conf)
724: {
725: struct acx_conf_nretry_short sretry;
726: struct acx_conf_nretry_long lretry;
727: struct acx_conf_msdu_lifetime msdu_lifetime;
728: struct acx_conf_rate_fallback rate_fb;
729: struct acx_conf_antenna ant;
730: struct acx_conf_regdom reg_dom;
731: struct ifnet *ifp = &sc->sc_ic.ic_if;
732: int error;
733:
734: /* Set number of long/short retry */
735: sretry.nretry = sc->sc_short_retry_limit;
736: if (acx_set_conf(sc, ACX_CONF_NRETRY_SHORT, &sretry,
737: sizeof(sretry)) != 0) {
738: printf("%s: can't set short retry limit\n", ifp->if_xname);
739: return (ENXIO);
740: }
741:
742: lretry.nretry = sc->sc_long_retry_limit;
743: if (acx_set_conf(sc, ACX_CONF_NRETRY_LONG, &lretry,
744: sizeof(lretry)) != 0) {
745: printf("%s: can't set long retry limit\n", ifp->if_xname);
746: return (ENXIO);
747: }
748:
749: /* Set MSDU lifetime */
750: msdu_lifetime.lifetime = htole32(sc->sc_msdu_lifetime);
751: if (acx_set_conf(sc, ACX_CONF_MSDU_LIFETIME, &msdu_lifetime,
752: sizeof(msdu_lifetime)) != 0) {
753: printf("%s: can't set MSDU lifetime\n", ifp->if_xname);
754: return (ENXIO);
755: }
756:
757: /* Enable rate fallback */
758: rate_fb.ratefb_enable = 1;
759: if (acx_set_conf(sc, ACX_CONF_RATE_FALLBACK, &rate_fb,
760: sizeof(rate_fb)) != 0) {
761: printf("%s: can't enable rate fallback\n", ifp->if_xname);
762: return (ENXIO);
763: }
764:
765: /* Set antenna */
766: ant.antenna = conf->antenna;
767: if (acx_set_conf(sc, ACX_CONF_ANTENNA, &ant, sizeof(ant)) != 0) {
768: printf("%s: can't set antenna\n", ifp->if_xname);
769: return (ENXIO);
770: }
771:
772: /* Set region domain */
773: reg_dom.regdom = conf->regdom;
774: if (acx_set_conf(sc, ACX_CONF_REGDOM, ®_dom, sizeof(reg_dom)) != 0) {
775: printf("%s: can't set region domain\n", ifp->if_xname);
776: return (ENXIO);
777: }
778:
779: if (sc->chip_write_config != NULL) {
780: error = sc->chip_write_config(sc, conf);
781: if (error)
782: return (error);
783: }
784:
785: return (0);
786: }
787:
788: int
789: acx_rx_config(struct acx_softc *sc)
790: {
791: struct ieee80211com *ic = &sc->sc_ic;
792: struct acx_conf_rxopt rx_opt;
793:
794: /* tell the RX receiver what frames we want to have */
795: rx_opt.opt1 = htole16(RXOPT1_INCL_RXBUF_HDR);
796: rx_opt.opt2 = htole16(
797: RXOPT2_RECV_ASSOC_REQ |
798: RXOPT2_RECV_AUTH |
799: RXOPT2_RECV_BEACON |
800: RXOPT2_RECV_CF |
801: RXOPT2_RECV_CTRL |
802: RXOPT2_RECV_DATA |
803: RXOPT2_RECV_MGMT |
804: RXOPT2_RECV_PROBE_REQ |
805: RXOPT2_RECV_PROBE_RESP |
806: RXOPT2_RECV_OTHER);
807:
808: /* in monitor mode go promiscuous */
809: if (ic->ic_opmode == IEEE80211_M_MONITOR) {
810: rx_opt.opt1 |= RXOPT1_PROMISC;
811: rx_opt.opt2 |= RXOPT2_RECV_BROKEN | RXOPT2_RECV_ACK;
812: } else
813: rx_opt.opt1 |= RXOPT1_FILT_FDEST;
814:
815: /* finally set the RX options */
816: if (acx_set_conf(sc, ACX_CONF_RXOPT, &rx_opt, sizeof(rx_opt)) != 0) {
817: printf("%s: can not set RX options!\n", sc->sc_dev.dv_xname);
818: return (ENXIO);
819: }
820:
821: return (0);
822: }
823:
824: int
825: acx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
826: {
827: struct acx_softc *sc = ifp->if_softc;
828: struct ieee80211com *ic = &sc->sc_ic;
829: struct ifaddr *ifa;
830: struct ifreq *ifr;
831: int s, error = 0;
832: uint8_t chan;
833:
834: s = splnet();
835:
836: switch (cmd) {
837: case SIOCSIFADDR:
838: ifa = (struct ifaddr *)data;
839: ifp->if_flags |= IFF_UP;
840: #ifdef INET
841: if (ifa->ifa_addr->sa_family == AF_INET)
842: arp_ifinit(&ic->ic_ac, ifa);
843: #endif
844: /* FALLTHROUGH */
845: case SIOCSIFFLAGS:
846: if (ifp->if_flags & IFF_UP) {
847: if ((ifp->if_flags & IFF_RUNNING) == 0)
848: acx_init(ifp);
849: } else {
850: if (ifp->if_flags & IFF_RUNNING)
851: acx_stop(sc);
852: }
853: break;
854: case SIOCADDMULTI:
855: case SIOCDELMULTI:
856: ifr = (struct ifreq *)data;
857: error = (cmd == SIOCADDMULTI) ?
858: ether_addmulti(ifr, &ic->ic_ac) :
859: ether_delmulti(ifr, &ic->ic_ac);
860:
861: if (error == ENETRESET)
862: error = 0;
863: break;
864: case SIOCS80211CHANNEL:
865: /* allow fast channel switching in monitor mode */
866: error = ieee80211_ioctl(ifp, cmd, data);
867: if (error == ENETRESET &&
868: ic->ic_opmode == IEEE80211_M_MONITOR) {
869: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
870: (IFF_UP | IFF_RUNNING)) {
871: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
872: chan = ieee80211_chan2ieee(ic,
873: ic->ic_bss->ni_chan);
874: (void)acx_set_channel(sc, chan);
875: }
876: error = 0;
877: }
878: break;
879: default:
880: error = ieee80211_ioctl(ifp, cmd, data);
881: break;
882: }
883:
884: if (error == ENETRESET) {
885: if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) ==
886: (IFF_RUNNING | IFF_UP))
887: acx_init(ifp);
888: error = 0;
889: }
890:
891: splx(s);
892:
893: return (error);
894: }
895:
896: void
897: acx_start(struct ifnet *ifp)
898: {
899: struct acx_softc *sc = ifp->if_softc;
900: struct ieee80211com *ic = &sc->sc_ic;
901: struct acx_buf_data *bd = &sc->sc_buf_data;
902: struct acx_txbuf *buf;
903: int trans, idx;
904:
905: if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0 ||
906: (ifp->if_flags & IFF_RUNNING) == 0 ||
907: (ifp->if_flags & IFF_OACTIVE))
908: return;
909:
910: /*
911: * NOTE:
912: * We can't start from a random position that TX descriptor
913: * is free, since hardware will be confused by that.
914: * We have to follow the order of the TX ring.
915: */
916: idx = bd->tx_free_start;
917: trans = 0;
918: for (buf = &bd->tx_buf[idx]; buf->tb_mbuf == NULL;
919: buf = &bd->tx_buf[idx]) {
920: struct ieee80211_frame *wh;
921: struct ieee80211_node *ni = NULL;
922: struct mbuf *m;
923: int rate;
924:
925: IF_DEQUEUE(&ic->ic_mgtq, m);
926: if (m != NULL) {
927: ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
928: m->m_pkthdr.rcvif = NULL;
929:
930: /*
931: * probe response mgmt frames are handled by the
932: * firmware already. So, don't send them twice.
933: */
934: wh = mtod(m, struct ieee80211_frame *);
935: if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
936: IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
937: if (ni != NULL)
938: ieee80211_release_node(ic, ni);
939: m_freem(m);
940: continue;
941: }
942:
943: /*
944: * mgmt frames are sent at the lowest available
945: * bit-rate.
946: */
947: rate = ni->ni_rates.rs_rates[0];
948: rate &= IEEE80211_RATE_VAL;
949: } else if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
950: struct ether_header *eh;
951:
952: IFQ_DEQUEUE(&ifp->if_snd, m);
953: if (m == NULL)
954: break;
955:
956: if (ic->ic_state != IEEE80211_S_RUN) {
957: DPRINTF(("%s: data packet dropped due to "
958: "not RUN. Current state %d\n",
959: ifp->if_xname, ic->ic_state));
960: m_freem(m);
961: break;
962: }
963:
964: if (m->m_len < sizeof(struct ether_header)) {
965: m = m_pullup(m, sizeof(struct ether_header));
966: if (m == NULL) {
967: ifp->if_oerrors++;
968: continue;
969: }
970: }
971: eh = mtod(m, struct ether_header *);
972:
973: /* TODO power save */
974:
975: #if NBPFILTER > 0
976: if (ifp->if_bpf != NULL)
977: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
978: #endif
979:
980: if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) {
981: ifp->if_oerrors++;
982: continue;
983: }
984:
985: #if NBPFILTER > 0
986: if (ic->ic_rawbpf != NULL)
987: bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
988: #endif
989:
990: if (ic->ic_fixed_rate != -1) {
991: rate = ic->ic_sup_rates[ic->ic_curmode].
992: rs_rates[ic->ic_fixed_rate];
993: } else
994: rate = ni->ni_rates.rs_rates[ni->ni_txrate];
995: rate &= IEEE80211_RATE_VAL;
996: } else
997: break;
998:
999: wh = mtod(m, struct ieee80211_frame *);
1000: if ((wh->i_fc[1] & IEEE80211_FC1_WEP) && !sc->chip_hw_crypt) {
1001: m = ieee80211_wep_crypt(ifp, m, 1);
1002: if (m == NULL) {
1003: ieee80211_release_node(ic, ni);
1004: m_freem(m);
1005: ifp->if_oerrors++;
1006: continue;
1007: }
1008: }
1009:
1010: #if NBPFILTER > 0
1011: if (sc->sc_drvbpf != NULL) {
1012: struct mbuf mb;
1013: struct acx_tx_radiotap_hdr *tap = &sc->sc_txtap;
1014:
1015: tap->wt_flags = 0;
1016: tap->wt_rate = rate;
1017: tap->wt_chan_freq =
1018: htole16(ic->ic_bss->ni_chan->ic_freq);
1019: tap->wt_chan_flags =
1020: htole16(ic->ic_bss->ni_chan->ic_flags);
1021:
1022: mb.m_data = (caddr_t)tap;
1023: mb.m_len = sc->sc_txtap_len;
1024: mb.m_next = m;
1025: mb.m_nextpkt = NULL;
1026: mb.m_type = 0;
1027: mb.m_flags = 0;
1028: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
1029: }
1030: #endif
1031:
1032: if (acx_encap(sc, buf, m, ni, rate) != 0) {
1033: /*
1034: * NOTE: `m' will be freed in acx_encap()
1035: * if we reach here.
1036: */
1037: if (ni != NULL)
1038: ieee80211_release_node(ic, ni);
1039: ifp->if_oerrors++;
1040: continue;
1041: }
1042:
1043: /*
1044: * NOTE:
1045: * 1) `m' should not be touched after acx_encap()
1046: * 2) `node' will be used to do TX rate control during
1047: * acx_txeof(), so it is not freed here. acx_txeof()
1048: * will free it for us
1049: */
1050: trans = 1;
1051: bd->tx_used_count++;
1052: idx = (idx + 1) % ACX_TX_DESC_CNT;
1053: }
1054: bd->tx_free_start = idx;
1055:
1056: if (bd->tx_used_count == ACX_TX_DESC_CNT)
1057: ifp->if_flags |= IFF_OACTIVE;
1058:
1059: if (trans && ifp->if_timer == 0)
1060: ifp->if_timer = 5;
1061: sc->sc_txtimer = 5;
1062: }
1063:
1064: void
1065: acx_watchdog(struct ifnet *ifp)
1066: {
1067: struct acx_softc *sc = ifp->if_softc;
1068:
1069: ifp->if_timer = 0;
1070:
1071: if ((ifp->if_flags & IFF_RUNNING) == 0)
1072: return;
1073:
1074: if (sc->sc_txtimer) {
1075: if (--sc->sc_txtimer == 0) {
1076: printf("%s: watchdog timeout\n", ifp->if_xname);
1077: acx_txeof(ifp->if_softc);
1078: ifp->if_oerrors++;
1079: return;
1080: }
1081: ifp->if_timer = 5;
1082: }
1083:
1084: ieee80211_watchdog(ifp);
1085: }
1086:
1087: int
1088: acx_intr(void *arg)
1089: {
1090: struct acx_softc *sc = arg;
1091: uint16_t intr_status;
1092:
1093: if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0)
1094: return (0);
1095:
1096: intr_status = CSR_READ_2(sc, ACXREG_INTR_STATUS_CLR);
1097: if (intr_status == ACXRV_INTR_ALL) {
1098: /* not our interrupt */
1099: return (0);
1100: }
1101:
1102: intr_status &= sc->chip_intr_enable;
1103: if (intr_status == 0) {
1104: /* not interrupts we care about */
1105: return (1);
1106: }
1107:
1108: /* Acknowledge all interrupts */
1109: CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_ALL);
1110:
1111: if (intr_status & ACXRV_INTR_TX_FINI)
1112: acx_txeof(sc);
1113:
1114: if (intr_status & ACXRV_INTR_RX_FINI)
1115: acx_rxeof(sc);
1116:
1117: return (1);
1118: }
1119:
1120: void
1121: acx_disable_intr(struct acx_softc *sc)
1122: {
1123: CSR_WRITE_2(sc, ACXREG_INTR_MASK, sc->chip_intr_disable);
1124: CSR_WRITE_2(sc, ACXREG_EVENT_MASK, 0);
1125: }
1126:
1127: void
1128: acx_enable_intr(struct acx_softc *sc)
1129: {
1130: /* Mask out interrupts that are not in the enable set */
1131: CSR_WRITE_2(sc, ACXREG_INTR_MASK, ~sc->chip_intr_enable);
1132: CSR_WRITE_2(sc, ACXREG_EVENT_MASK, ACXRV_EVENT_DISABLE);
1133: }
1134:
1135: void
1136: acx_txeof(struct acx_softc *sc)
1137: {
1138: struct acx_buf_data *bd;
1139: struct acx_txbuf *buf;
1140: struct ifnet *ifp;
1141: int idx;
1142:
1143: ifp = &sc->sc_ic.ic_if;
1144:
1145: bd = &sc->sc_buf_data;
1146: idx = bd->tx_used_start;
1147: for (buf = &bd->tx_buf[idx]; buf->tb_mbuf != NULL;
1148: buf = &bd->tx_buf[idx]) {
1149: uint8_t ctrl, error;
1150:
1151: ctrl = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_ctrl);
1152: if ((ctrl & (DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE)) !=
1153: (DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE))
1154: break;
1155:
1156: bus_dmamap_unload(sc->sc_dmat, buf->tb_mbuf_dmamap);
1157: m_freem(buf->tb_mbuf);
1158: buf->tb_mbuf = NULL;
1159:
1160: error = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_error);
1161: if (error) {
1162: acx_txerr(sc, error);
1163: ifp->if_oerrors++;
1164: } else
1165: ifp->if_opackets++;
1166:
1167: /* Update rate control statistics for the node */
1168: if (buf->tb_node != NULL) {
1169: struct ieee80211com *ic;
1170: struct ieee80211_node *ni;
1171: struct acx_node *wn;
1172: int ntries;
1173:
1174: ic = &sc->sc_ic;
1175: ni = (struct ieee80211_node *)buf->tb_node;
1176: wn = (struct acx_node *)ni;
1177: ntries = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_rts_fail) +
1178: FW_TXDESC_GETFIELD_1(sc, buf, f_tx_ack_fail);
1179:
1180: wn->amn.amn_txcnt++;
1181: if (ntries > 0) {
1182: DPRINTFN(2, ("%s: tx intr ntries %d\n",
1183: sc->sc_dev.dv_xname, ntries));
1184: wn->amn.amn_retrycnt++;
1185: }
1186:
1187: ieee80211_release_node(ic, ni);
1188: buf->tb_node = NULL;
1189: }
1190:
1191: FW_TXDESC_SETFIELD_1(sc, buf, f_tx_ctrl, DESC_CTRL_HOSTOWN);
1192:
1193: bd->tx_used_count--;
1194:
1195: idx = (idx + 1) % ACX_TX_DESC_CNT;
1196: }
1197: bd->tx_used_start = idx;
1198:
1199: ifp->if_timer = bd->tx_used_count == 0 ? 0 : 5;
1200: sc->sc_txtimer = 0;
1201:
1202: if (bd->tx_used_count != ACX_TX_DESC_CNT) {
1203: ifp->if_flags &= ~IFF_OACTIVE;
1204: acx_start(ifp);
1205: }
1206: }
1207:
1208: void
1209: acx_txerr(struct acx_softc *sc, uint8_t err)
1210: {
1211: struct ifnet *ifp = &sc->sc_ic.ic_if;
1212: struct acx_stats *stats = &sc->sc_stats;
1213:
1214: if (err == DESC_ERR_EXCESSIVE_RETRY) {
1215: /*
1216: * This a common error (see comment below),
1217: * so print it using DPRINTF().
1218: */
1219: DPRINTF(("%s: TX failed -- excessive retry\n",
1220: sc->sc_dev.dv_xname));
1221: } else
1222: printf("%s: TX failed -- ", ifp->if_xname);
1223:
1224: /*
1225: * Although `err' looks like bitmask, it never
1226: * has multiple bits set.
1227: */
1228: switch (err) {
1229: #if 0
1230: case DESC_ERR_OTHER_FRAG:
1231: /* XXX what's this */
1232: printf("error in other fragment\n");
1233: stats->err_oth_frag++;
1234: break;
1235: #endif
1236: case DESC_ERR_ABORT:
1237: printf("aborted\n");
1238: stats->err_abort++;
1239: break;
1240: case DESC_ERR_PARAM:
1241: printf("wrong paramters in descriptor\n");
1242: stats->err_param++;
1243: break;
1244: case DESC_ERR_NO_WEPKEY:
1245: printf("WEP key missing\n");
1246: stats->err_no_wepkey++;
1247: break;
1248: case DESC_ERR_MSDU_TIMEOUT:
1249: printf("MSDU life timeout\n");
1250: stats->err_msdu_timeout++;
1251: break;
1252: case DESC_ERR_EXCESSIVE_RETRY:
1253: /*
1254: * Possible causes:
1255: * 1) Distance is too long
1256: * 2) Transmit failed (e.g. no MAC level ACK)
1257: * 3) Chip overheated (this should be rare)
1258: */
1259: stats->err_ex_retry++;
1260: break;
1261: case DESC_ERR_BUF_OVERFLOW:
1262: printf("buffer overflow\n");
1263: stats->err_buf_oflow++;
1264: break;
1265: case DESC_ERR_DMA:
1266: printf("DMA error\n");
1267: stats->err_dma++;
1268: break;
1269: default:
1270: printf("unknown error %d\n", err);
1271: stats->err_unkn++;
1272: break;
1273: }
1274: }
1275:
1276: void
1277: acx_rxeof(struct acx_softc *sc)
1278: {
1279: struct ieee80211com *ic = &sc->sc_ic;
1280: struct acx_ring_data *rd = &sc->sc_ring_data;
1281: struct acx_buf_data *bd = &sc->sc_buf_data;
1282: struct ifnet *ifp = &ic->ic_if;
1283: int idx, ready;
1284:
1285: bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,
1286: rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1287:
1288: /*
1289: * Locate first "ready" rx buffer,
1290: * start from last stopped position.
1291: */
1292: idx = bd->rx_scan_start;
1293: ready = 0;
1294: do {
1295: struct acx_rxbuf *buf;
1296:
1297: buf = &bd->rx_buf[idx];
1298: if ((buf->rb_desc->h_ctrl & htole16(DESC_CTRL_HOSTOWN)) &&
1299: (buf->rb_desc->h_status & htole32(DESC_STATUS_FULL))) {
1300: ready = 1;
1301: break;
1302: }
1303: idx = (idx + 1) % ACX_RX_DESC_CNT;
1304: } while (idx != bd->rx_scan_start);
1305:
1306: if (!ready)
1307: return;
1308:
1309: /*
1310: * NOTE: don't mess up `idx' here, it will
1311: * be used in the following code.
1312: */
1313: do {
1314: struct acx_rxbuf_hdr *head;
1315: struct acx_rxbuf *buf;
1316: struct mbuf *m;
1317: uint32_t desc_status;
1318: uint16_t desc_ctrl;
1319: int len, error;
1320:
1321: buf = &bd->rx_buf[idx];
1322:
1323: desc_ctrl = letoh16(buf->rb_desc->h_ctrl);
1324: desc_status = letoh32(buf->rb_desc->h_status);
1325: if (!(desc_ctrl & DESC_CTRL_HOSTOWN) ||
1326: !(desc_status & DESC_STATUS_FULL))
1327: break;
1328:
1329: bus_dmamap_sync(sc->sc_dmat, buf->rb_mbuf_dmamap, 0,
1330: buf->rb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1331:
1332: m = buf->rb_mbuf;
1333:
1334: error = acx_newbuf(sc, buf, 0);
1335: if (error) {
1336: ifp->if_ierrors++;
1337: goto next;
1338: }
1339:
1340: head = mtod(m, struct acx_rxbuf_hdr *);
1341:
1342: len = letoh16(head->rbh_len) & ACX_RXBUF_LEN_MASK;
1343: if (len >= sizeof(struct ieee80211_frame_min) &&
1344: len < MCLBYTES) {
1345: struct ieee80211_frame *wh;
1346: struct ieee80211_node *ni;
1347:
1348: m_adj(m, sizeof(struct acx_rxbuf_hdr) +
1349: sc->chip_rxbuf_exhdr);
1350: wh = mtod(m, struct ieee80211_frame *);
1351:
1352: if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
1353: sc->chip_hw_crypt) {
1354: /* Short circuit software WEP */
1355: wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1356:
1357: /* Do chip specific RX buffer processing */
1358: if (sc->chip_proc_wep_rxbuf != NULL) {
1359: sc->chip_proc_wep_rxbuf(sc, m, &len);
1360: wh = mtod(m, struct ieee80211_frame *);
1361: }
1362: }
1363:
1364: m->m_len = m->m_pkthdr.len = len;
1365: m->m_pkthdr.rcvif = &ic->ic_if;
1366:
1367: #if NBPFILTER > 0
1368: if (sc->sc_drvbpf != NULL) {
1369: struct mbuf mb;
1370: struct acx_rx_radiotap_hdr *tap = &sc->sc_rxtap;
1371:
1372: tap->wr_flags = 0;
1373: tap->wr_chan_freq =
1374: htole16(ic->ic_bss->ni_chan->ic_freq);
1375: tap->wr_chan_flags =
1376: htole16(ic->ic_bss->ni_chan->ic_flags);
1377: tap->wr_rssi = head->rbh_level;
1378: tap->wr_max_rssi = ic->ic_max_rssi;
1379:
1380: mb.m_data = (caddr_t)tap;
1381: mb.m_len = sc->sc_rxtap_len;
1382: mb.m_next = m;
1383: mb.m_nextpkt = NULL;
1384: mb.m_type = 0;
1385: mb.m_flags = 0;
1386: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
1387: }
1388: #endif
1389:
1390: ni = ieee80211_find_rxnode(ic, wh);
1391:
1392: ieee80211_input(ifp, m, ni, head->rbh_level,
1393: letoh32(head->rbh_time));
1394:
1395: ieee80211_release_node(ic, ni);
1396: ifp->if_ipackets++;
1397: } else {
1398: m_freem(m);
1399: ifp->if_ierrors++;
1400: }
1401:
1402: next:
1403: buf->rb_desc->h_ctrl = htole16(desc_ctrl & ~DESC_CTRL_HOSTOWN);
1404: buf->rb_desc->h_status = 0;
1405: bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,
1406: rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
1407:
1408: idx = (idx + 1) % ACX_RX_DESC_CNT;
1409: } while (idx != bd->rx_scan_start);
1410:
1411: /*
1412: * Record the position so that next
1413: * time we can start from it.
1414: */
1415: bd->rx_scan_start = idx;
1416:
1417: /*
1418: * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
1419: * without calling if_start().
1420: */
1421: if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
1422: (*ifp->if_start)(ifp);
1423: }
1424:
1425: int
1426: acx_reset(struct acx_softc *sc)
1427: {
1428: uint16_t reg;
1429:
1430: /* Halt ECPU */
1431: CSR_SETB_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_HALT);
1432:
1433: /* Software reset */
1434: reg = CSR_READ_2(sc, ACXREG_SOFT_RESET);
1435: CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg | ACXRV_SOFT_RESET);
1436: DELAY(100);
1437: CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg);
1438:
1439: /* Initialize EEPROM */
1440: CSR_SETB_2(sc, ACXREG_EEPROM_INIT, ACXRV_EEPROM_INIT);
1441: DELAY(50000);
1442:
1443: /* Test whether ECPU is stopped */
1444: reg = CSR_READ_2(sc, ACXREG_ECPU_CTRL);
1445: if (!(reg & ACXRV_ECPU_HALT)) {
1446: printf("%s: can't halt ECPU\n", sc->sc_dev.dv_xname);
1447: return (ENXIO);
1448: }
1449:
1450: return (0);
1451: }
1452:
1453: int
1454: acx_read_eeprom(struct acx_softc *sc, uint32_t offset, uint8_t *val)
1455: {
1456: int i;
1457: struct ifnet *ifp = &sc->sc_ic.ic_if;
1458:
1459: CSR_WRITE_4(sc, ACXREG_EEPROM_CONF, 0);
1460: CSR_WRITE_4(sc, ACXREG_EEPROM_ADDR, offset);
1461: CSR_WRITE_4(sc, ACXREG_EEPROM_CTRL, ACXRV_EEPROM_READ);
1462:
1463: #define EE_READ_RETRY_MAX 100
1464: for (i = 0; i < EE_READ_RETRY_MAX; ++i) {
1465: if (CSR_READ_2(sc, ACXREG_EEPROM_CTRL) == 0)
1466: break;
1467: DELAY(10000);
1468: }
1469: if (i == EE_READ_RETRY_MAX) {
1470: printf("%s: can't read EEPROM offset %x (timeout)\n",
1471: ifp->if_xname, offset);
1472: return (ETIMEDOUT);
1473: }
1474: #undef EE_READ_RETRY_MAX
1475:
1476: *val = CSR_READ_1(sc, ACXREG_EEPROM_DATA);
1477:
1478: return (0);
1479: }
1480:
1481: int
1482: acx_read_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t *val)
1483: {
1484: struct ifnet *ifp = &sc->sc_ic.ic_if;
1485: int i;
1486:
1487: CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg);
1488: CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_READ);
1489:
1490: #define PHY_READ_RETRY_MAX 100
1491: for (i = 0; i < PHY_READ_RETRY_MAX; ++i) {
1492: if (CSR_READ_4(sc, ACXREG_PHY_CTRL) == 0)
1493: break;
1494: DELAY(10000);
1495: }
1496: if (i == PHY_READ_RETRY_MAX) {
1497: printf("%s: can't read phy reg %x (timeout)\n",
1498: ifp->if_xname, reg);
1499: return (ETIMEDOUT);
1500: }
1501: #undef PHY_READ_RETRY_MAX
1502:
1503: *val = CSR_READ_1(sc, ACXREG_PHY_DATA);
1504:
1505: return (0);
1506: }
1507:
1508: void
1509: acx_write_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t val)
1510: {
1511: CSR_WRITE_4(sc, ACXREG_PHY_DATA, val);
1512: CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg);
1513: CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_WRITE);
1514: }
1515:
1516: int
1517: acx_load_base_firmware(struct acx_softc *sc, const char *name)
1518: {
1519: struct ifnet *ifp = &sc->sc_ic.ic_if;
1520: int i, error;
1521: uint8_t *ucode;
1522: size_t size;
1523:
1524: error = loadfirmware(name, &ucode, &size);
1525:
1526: if (error != 0) {
1527: printf("%s: error %d, could not read microcode %s!\n",
1528: ifp->if_xname, error, name);
1529: return (EIO);
1530: }
1531:
1532: /* Load base firmware */
1533: error = acx_load_firmware(sc, 0, ucode, size);
1534:
1535: free(ucode, M_DEVBUF);
1536:
1537: if (error) {
1538: printf("%s: can't load base firmware\n", ifp->if_xname);
1539: return error;
1540: }
1541: DPRINTF(("%s: base firmware loaded\n", sc->sc_dev.dv_xname));
1542:
1543: /* Start ECPU */
1544: CSR_WRITE_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_START);
1545:
1546: /* Wait for ECPU to be up */
1547: for (i = 0; i < 500; ++i) {
1548: uint16_t reg;
1549:
1550: reg = CSR_READ_2(sc, ACXREG_INTR_STATUS);
1551: if (reg & ACXRV_INTR_FCS_THRESH) {
1552: CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_FCS_THRESH);
1553: return (0);
1554: }
1555: DELAY(10000);
1556: }
1557:
1558: printf("%s: can't initialize ECPU (timeout)\n", ifp->if_xname);
1559:
1560: return (ENXIO);
1561: }
1562:
1563: int
1564: acx_load_radio_firmware(struct acx_softc *sc, const char *name)
1565: {
1566: struct ifnet *ifp = &sc->sc_ic.ic_if;
1567: struct acx_conf_mmap mem_map;
1568: uint32_t radio_fw_ofs;
1569: int error;
1570: uint8_t *ucode;
1571: size_t size;
1572:
1573: error = loadfirmware(name, &ucode, &size);
1574:
1575: if (error != 0) {
1576: printf("%s: error %d, could not read microcode %s!\n",
1577: ifp->if_xname, error, name);
1578: return (EIO);
1579: }
1580:
1581: /*
1582: * Get the position, where base firmware is loaded, so that
1583: * radio firmware can be loaded after it.
1584: */
1585: if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
1586: free(ucode, M_DEVBUF);
1587: return (ENXIO);
1588: }
1589: radio_fw_ofs = letoh32(mem_map.code_end);
1590:
1591: /* Put ECPU into sleeping state, before loading radio firmware */
1592: if (acx_exec_command(sc, ACXCMD_SLEEP, NULL, 0, NULL, 0) != 0) {
1593: free(ucode, M_DEVBUF);
1594: return (ENXIO);
1595: }
1596:
1597: /* Load radio firmware */
1598: error = acx_load_firmware(sc, radio_fw_ofs, ucode, size);
1599:
1600: free(ucode, M_DEVBUF);
1601:
1602: if (error) {
1603: printf("%s: can't load radio firmware\n", ifp->if_xname);
1604: return (ENXIO);
1605: }
1606: DPRINTF(("%s: radio firmware loaded\n", sc->sc_dev.dv_xname));
1607:
1608: /* Wake up sleeping ECPU, after radio firmware is loaded */
1609: if (acx_exec_command(sc, ACXCMD_WAKEUP, NULL, 0, NULL, 0) != 0)
1610: return (ENXIO);
1611:
1612: /* Initialize radio */
1613: if (acx_init_radio(sc, radio_fw_ofs, size) != 0)
1614: return (ENXIO);
1615:
1616: /* Verify radio firmware's loading position */
1617: if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0)
1618: return (ENXIO);
1619:
1620: if (letoh32(mem_map.code_end) != radio_fw_ofs + size) {
1621: printf("%s: loaded radio firmware position mismatch\n",
1622: ifp->if_xname);
1623: return (ENXIO);
1624: }
1625:
1626: DPRINTF(("%s: radio firmware initialized\n", sc->sc_dev.dv_xname));
1627:
1628: return (0);
1629: }
1630:
1631: int
1632: acx_load_firmware(struct acx_softc *sc, uint32_t offset, const uint8_t *data,
1633: int data_len)
1634: {
1635: struct ifnet *ifp = &sc->sc_ic.ic_if;
1636: const uint32_t *fw;
1637: u_int32_t csum = 0;
1638: int i, fw_len;
1639:
1640: for (i = 4; i < data_len; i++)
1641: csum += data[i];
1642:
1643: fw = (const uint32_t *)data;
1644:
1645: if (*fw != htole32(csum)) {
1646: printf("%s: firmware checksum 0x%x does not match 0x%x!\n",
1647: ifp->if_xname, *fw, htole32(csum));
1648: return (ENXIO);
1649: }
1650:
1651: /* skip csum + length */
1652: data += 8;
1653: data_len -= 8;
1654:
1655: fw = (const uint32_t *)data;
1656: fw_len = data_len / sizeof(uint32_t);
1657:
1658: /*
1659: * LOADFW_AUTO_INC only works with some older firmware:
1660: * 1) acx100's firmware
1661: * 2) acx111's firmware whose rev is 0x00010011
1662: */
1663:
1664: /* Load firmware */
1665: CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP);
1666: #ifndef LOADFW_AUTO_INC
1667: CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0);
1668: #else
1669: CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC);
1670: CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset);
1671: #endif
1672:
1673: for (i = 0; i < fw_len; ++i) {
1674: #ifndef LOADFW_AUTO_INC
1675: CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4));
1676: #endif
1677: CSR_WRITE_4(sc, ACXREG_FWMEM_DATA, betoh32(fw[i]));
1678: }
1679:
1680: /* Verify firmware */
1681: CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP);
1682: #ifndef LOADFW_AUTO_INC
1683: CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0);
1684: #else
1685: CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC);
1686: CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset);
1687: #endif
1688:
1689: for (i = 0; i < fw_len; ++i) {
1690: uint32_t val;
1691:
1692: #ifndef LOADFW_AUTO_INC
1693: CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4));
1694: #endif
1695: val = CSR_READ_4(sc, ACXREG_FWMEM_DATA);
1696: if (betoh32(fw[i]) != val) {
1697: printf("%s: firmware mismatch fw %08x loaded %08x\n",
1698: ifp->if_xname, fw[i], val);
1699: return (ENXIO);
1700: }
1701: }
1702:
1703: return (0);
1704: }
1705:
1706: struct ieee80211_node *
1707: acx_node_alloc(struct ieee80211com *ic)
1708: {
1709: struct acx_node *wn;
1710:
1711: wn = malloc(sizeof(struct acx_node), M_DEVBUF, M_NOWAIT);
1712: if (wn == NULL)
1713: return (NULL);
1714:
1715: bzero(wn, sizeof(struct acx_node));
1716:
1717: return ((struct ieee80211_node *)wn);
1718: }
1719:
1720: int
1721: acx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1722: {
1723: struct acx_softc *sc = ic->ic_if.if_softc;
1724: struct ifnet *ifp = &ic->ic_if;
1725: int error = 0;
1726:
1727: timeout_del(&sc->amrr_ch);
1728:
1729: switch (nstate) {
1730: case IEEE80211_S_INIT:
1731: break;
1732: case IEEE80211_S_SCAN: {
1733: uint8_t chan;
1734:
1735: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
1736: (void)acx_set_channel(sc, chan);
1737:
1738: timeout_add(&sc->sc_chanscan_timer,
1739: hz / acx_chanscan_rate);
1740: }
1741: break;
1742: case IEEE80211_S_AUTH:
1743: if (ic->ic_opmode == IEEE80211_M_STA) {
1744: struct ieee80211_node *ni;
1745: #ifdef ACX_DEBUG
1746: int i;
1747: #endif
1748:
1749: ni = ic->ic_bss;
1750:
1751: if (acx_join_bss(sc, ACX_MODE_STA, ni) != 0) {
1752: printf("%s: join BSS failed\n", ifp->if_xname);
1753: error = 1;
1754: goto back;
1755: }
1756:
1757: DPRINTF(("%s: join BSS\n", sc->sc_dev.dv_xname));
1758: if (ic->ic_state == IEEE80211_S_ASSOC) {
1759: DPRINTF(("%s: change from assoc to run\n",
1760: sc->sc_dev.dv_xname));
1761: ic->ic_state = IEEE80211_S_RUN;
1762: }
1763:
1764: #ifdef ACX_DEBUG
1765: printf("%s: AP rates: ", sc->sc_dev.dv_xname);
1766: for (i = 0; i < ni->ni_rates.rs_nrates; ++i)
1767: printf("%d ", ni->ni_rates.rs_rates[i]);
1768: ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
1769: printf(" %s\n", ether_sprintf(ni->ni_bssid));
1770: #endif
1771: }
1772: break;
1773: case IEEE80211_S_RUN:
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_ADHOC, 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_AP, 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:
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(&sc->amrr_ch, hz / 2);
1824: break;
1825: default:
1826: break;
1827: }
1828:
1829: back:
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:
1839: int
1840: acx_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));
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_REQ, &data.preq,
1862: sizeof(data.preq)) != 0)
1863: return (1);
1864:
1865: if (acx_set_tmplt(sc, ACXCMD_TMPLT_NULL_DATA, &data.null,
1866: sizeof(data.null)) != 0)
1867: return (1);
1868:
1869: if (acx_set_tmplt(sc, ACXCMD_TMPLT_BEACON, &data.beacon,
1870: sizeof(data.beacon)) != 0)
1871: return (1);
1872:
1873: if (acx_set_tmplt(sc, ACXCMD_TMPLT_TIM, &data.tim,
1874: sizeof(data.tim)) != 0)
1875: return (1);
1876:
1877: if (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_RESP, &data.presp,
1878: sizeof(data.presp)) != 0)
1879: return (1);
1880:
1881: return (0);
1882: }
1883:
1884: int
1885: acx_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: struct ifnet *ifp = &sc->sc_ic.ic_if;
1890: int i, error, nsegs;
1891:
1892: /* Allocate DMA stuffs for RX descriptors */
1893: error = bus_dmamap_create(sc->sc_dmat, ACX_RX_RING_SIZE, 1,
1894: ACX_RX_RING_SIZE, 0, BUS_DMA_NOWAIT, &rd->rx_ring_dmamap);
1895:
1896: if (error) {
1897: printf("%s: can't create rx ring dma tag\n",
1898: sc->sc_dev.dv_xname);
1899: return (error);
1900: }
1901:
1902: error = bus_dmamem_alloc(sc->sc_dmat, ACX_RX_RING_SIZE, PAGE_SIZE,
1903: 0, &rd->rx_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1904:
1905: if (error != 0) {
1906: printf("%s: can't allocate rx ring dma memory\n",
1907: sc->sc_dev.dv_xname);
1908: return (error);
1909: }
1910:
1911: error = bus_dmamem_map(sc->sc_dmat, &rd->rx_ring_seg, nsegs,
1912: ACX_RX_RING_SIZE, (caddr_t *)&rd->rx_ring,
1913: BUS_DMA_NOWAIT);
1914:
1915: if (error != 0) {
1916: printf("%s: could not map rx desc DMA memory\n",
1917: sc->sc_dev.dv_xname);
1918: return (error);
1919: }
1920:
1921: error = bus_dmamap_load(sc->sc_dmat, rd->rx_ring_dmamap,
1922: rd->rx_ring, ACX_RX_RING_SIZE, NULL, BUS_DMA_WAITOK);
1923:
1924: if (error) {
1925: printf("%s: can't get rx ring dma address\n",
1926: sc->sc_dev.dv_xname);
1927: bus_dmamem_free(sc->sc_dmat, &rd->rx_ring_seg, 1);
1928: return (error);
1929: }
1930:
1931: rd->rx_ring_paddr = rd->rx_ring_dmamap->dm_segs[0].ds_addr;
1932:
1933: /* Allocate DMA stuffs for TX descriptors */
1934: error = bus_dmamap_create(sc->sc_dmat, ACX_TX_RING_SIZE, 1,
1935: ACX_TX_RING_SIZE, 0, BUS_DMA_NOWAIT, &rd->tx_ring_dmamap);
1936:
1937: if (error) {
1938: printf("%s: can't create tx ring dma tag\n", ifp->if_xname);
1939: return (error);
1940: }
1941:
1942: error = bus_dmamem_alloc(sc->sc_dmat, ACX_TX_RING_SIZE, PAGE_SIZE,
1943: 0, &rd->tx_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT);
1944:
1945: if (error) {
1946: printf("%s: can't allocate tx ring dma memory\n",
1947: ifp->if_xname);
1948: return (error);
1949: }
1950:
1951: error = bus_dmamem_map(sc->sc_dmat, &rd->tx_ring_seg, nsegs,
1952: ACX_TX_RING_SIZE, (caddr_t *)&rd->tx_ring, BUS_DMA_NOWAIT);
1953:
1954: if (error != 0) {
1955: printf("%s: could not 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,
1961: rd->tx_ring, ACX_TX_RING_SIZE, NULL, BUS_DMA_WAITOK);
1962:
1963: if (error) {
1964: printf("%s: can't get tx ring dma address\n", ifp->if_xname);
1965: bus_dmamem_free(sc->sc_dmat, &rd->tx_ring_seg, 1);
1966: return (error);
1967: }
1968:
1969: rd->tx_ring_paddr = rd->tx_ring_dmamap->dm_segs[0].ds_addr;
1970:
1971: /* Create a spare RX DMA map */
1972: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
1973: 0, 0, &bd->mbuf_tmp_dmamap);
1974:
1975: if (error) {
1976: printf("%s: can't create tmp mbuf dma map\n", ifp->if_xname);
1977: return (error);
1978: }
1979:
1980: /* Create DMA map for RX mbufs */
1981: for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
1982: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1983: MCLBYTES, 0, 0, &bd->rx_buf[i].rb_mbuf_dmamap);
1984: if (error) {
1985: printf("%s: can't create rx mbuf dma map (%d)\n",
1986: ifp->if_xname, i);
1987: return (error);
1988: }
1989: bd->rx_buf[i].rb_desc = &rd->rx_ring[i];
1990: }
1991:
1992: /* Create DMA map for TX mbufs */
1993: for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
1994: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1995: MCLBYTES, 0, 0, &bd->tx_buf[i].tb_mbuf_dmamap);
1996: if (error) {
1997: printf("%s: can't create tx mbuf dma map (%d)\n",
1998: ifp->if_xname, i);
1999: return (error);
2000: }
2001: bd->tx_buf[i].tb_desc1 = &rd->tx_ring[i * 2];
2002: bd->tx_buf[i].tb_desc2 = &rd->tx_ring[(i * 2) + 1];
2003: }
2004:
2005: return (0);
2006: }
2007:
2008: void
2009: acx_dma_free(struct acx_softc *sc)
2010: {
2011: struct acx_ring_data *rd = &sc->sc_ring_data;
2012: struct acx_buf_data *bd = &sc->sc_buf_data;
2013: int i;
2014:
2015: if (rd->rx_ring != NULL) {
2016: bus_dmamap_unload(sc->sc_dmat, rd->rx_ring_dmamap);
2017: bus_dmamem_free(sc->sc_dmat, &rd->rx_ring_seg, 1);
2018: }
2019:
2020: if (rd->tx_ring != NULL) {
2021: bus_dmamap_unload(sc->sc_dmat, rd->tx_ring_dmamap);
2022: bus_dmamem_free(sc->sc_dmat, &rd->tx_ring_seg, 1);
2023: }
2024:
2025: for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
2026: if (bd->rx_buf[i].rb_desc != NULL) {
2027: if (bd->rx_buf[i].rb_mbuf != NULL) {
2028: bus_dmamap_unload(sc->sc_dmat,
2029: bd->rx_buf[i].rb_mbuf_dmamap);
2030: m_freem(bd->rx_buf[i].rb_mbuf);
2031: }
2032: bus_dmamap_destroy(sc->sc_dmat,
2033: bd->rx_buf[i].rb_mbuf_dmamap);
2034: }
2035: }
2036:
2037: for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
2038: if (bd->tx_buf[i].tb_desc1 != NULL) {
2039: if (bd->tx_buf[i].tb_mbuf != NULL) {
2040: bus_dmamap_unload(sc->sc_dmat,
2041: bd->tx_buf[i].tb_mbuf_dmamap);
2042: m_freem(bd->tx_buf[i].tb_mbuf);
2043: }
2044: bus_dmamap_destroy(sc->sc_dmat,
2045: bd->tx_buf[i].tb_mbuf_dmamap);
2046: }
2047: }
2048:
2049: if (bd->mbuf_tmp_dmamap != NULL)
2050: bus_dmamap_destroy(sc->sc_dmat, bd->mbuf_tmp_dmamap);
2051: }
2052:
2053: int
2054: acx_init_tx_ring(struct acx_softc *sc)
2055: {
2056: struct acx_ring_data *rd;
2057: struct acx_buf_data *bd;
2058: uint32_t paddr;
2059: int i;
2060:
2061: rd = &sc->sc_ring_data;
2062: paddr = rd->tx_ring_paddr;
2063: for (i = 0; i < (ACX_TX_DESC_CNT * 2) - 1; ++i) {
2064: paddr += sizeof(struct acx_host_desc);
2065:
2066: bzero(&rd->tx_ring[i], sizeof(struct acx_host_desc));
2067: rd->tx_ring[i].h_ctrl = htole16(DESC_CTRL_HOSTOWN);
2068:
2069: if (i == (ACX_TX_DESC_CNT * 2) - 1)
2070: rd->tx_ring[i].h_next_desc = htole32(rd->tx_ring_paddr);
2071: else
2072: rd->tx_ring[i].h_next_desc = htole32(paddr);
2073: }
2074:
2075: bus_dmamap_sync(sc->sc_dmat, rd->tx_ring_dmamap, 0,
2076: rd->tx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
2077:
2078: bd = &sc->sc_buf_data;
2079: bd->tx_free_start = 0;
2080: bd->tx_used_start = 0;
2081: bd->tx_used_count = 0;
2082:
2083: return (0);
2084: }
2085:
2086: int
2087: acx_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_CNT; ++i) {
2099: int error;
2100:
2101: paddr += sizeof(struct acx_host_desc);
2102: 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_CNT - 1)
2109: rd->rx_ring[i].h_next_desc = htole32(rd->rx_ring_paddr);
2110: else
2111: rd->rx_ring[i].h_next_desc = htole32(paddr);
2112: }
2113:
2114: bus_dmamap_sync(sc->sc_dmat, rd->rx_ring_dmamap, 0,
2115: rd->rx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
2116:
2117: bd->rx_scan_start = 0;
2118:
2119: return (0);
2120: }
2121:
2122: int
2123: acx_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);
2134: if (m == NULL)
2135: return (ENOBUFS);
2136:
2137: MCLGET(m, wait ? M_WAITOK : M_DONTWAIT);
2138: if (!(m->m_flags & M_EXT)) {
2139: m_freem(m);
2140: return (ENOBUFS);
2141: }
2142:
2143: m->m_len = m->m_pkthdr.len = MCLBYTES;
2144:
2145: error = bus_dmamap_load_mbuf(sc->sc_dmat, bd->mbuf_tmp_dmamap, m,
2146: wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
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)
2156: bus_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);
2166: rb->rb_desc->h_data_len = htole16(m->m_len);
2167:
2168: bus_dmamap_sync(sc->sc_dmat, rb->rb_mbuf_dmamap, 0,
2169: rb->rb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
2170:
2171: return (0);
2172: }
2173:
2174: int
2175: acx_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_if;
2181: uint32_t paddr;
2182: uint8_t ctrl;
2183: int error;
2184:
2185: if (txbuf->tb_mbuf != NULL)
2186: panic("free TX buf has mbuf installed\n");
2187:
2188: error = 0;
2189:
2190: if (m->m_pkthdr.len > MCLBYTES) {
2191: printf("%s: mbuf too big\n", ifp->if_xname);
2192: error = E2BIG;
2193: goto back;
2194: } else if (m->m_pkthdr.len < ACX_FRAME_HDRLEN) {
2195: printf("%s: mbuf too small\n", ifp->if_xname);
2196: error = EINVAL;
2197: goto back;
2198: }
2199:
2200: error = bus_dmamap_load_mbuf(sc->sc_dmat, txbuf->tb_mbuf_dmamap, m,
2201: BUS_DMA_NOWAIT);
2202:
2203: if (error && error != EFBIG) {
2204: printf("%s: can't map tx mbuf1 %d\n",
2205: sc->sc_dev.dv_xname, error);
2206: goto back;
2207: }
2208:
2209: if (error) { /* error == EFBIG */
2210: /* too many fragments, linearize */
2211: struct mbuf *mnew;
2212:
2213: error = 0;
2214:
2215: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
2216: if (mnew == NULL) {
2217: m_freem(m);
2218: error = ENOBUFS;
2219: printf("%s: can't defrag tx mbuf\n", ifp->if_xname);
2220: goto back;
2221: }
2222:
2223: M_DUP_PKTHDR(mnew, m);
2224: if (m->m_pkthdr.len > MHLEN) {
2225: MCLGET(mnew, M_DONTWAIT);
2226: if (!(mnew->m_flags & M_EXT)) {
2227: m_freem(m);
2228: m_freem(mnew);
2229: error = ENOBUFS;
2230: }
2231: }
2232:
2233: if (error) {
2234: printf("%s: can't defrag tx mbuf\n", ifp->if_xname);
2235: goto back;
2236: }
2237:
2238: m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t));
2239: m_freem(m);
2240: mnew->m_len = mnew->m_pkthdr.len;
2241: m = mnew;
2242:
2243: error = bus_dmamap_load_mbuf(sc->sc_dmat,
2244: txbuf->tb_mbuf_dmamap, m, BUS_DMA_NOWAIT);
2245: if (error) {
2246: printf("%s: can't map tx mbuf2 %d\n",
2247: sc->sc_dev.dv_xname, error);
2248: goto back;
2249: }
2250: }
2251:
2252: error = 0;
2253:
2254: bus_dmamap_sync(sc->sc_dmat, txbuf->tb_mbuf_dmamap, 0,
2255: txbuf->tb_mbuf_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
2256:
2257: txbuf->tb_mbuf = m;
2258: txbuf->tb_node = node;
2259: txbuf->tb_rate = rate;
2260:
2261: /*
2262: * TX buffers are accessed in following way:
2263: * acx_fw_txdesc -> acx_host_desc -> buffer
2264: *
2265: * It is quite strange that acx also queries acx_host_desc next to
2266: * the one we have assigned to acx_fw_txdesc even if first one's
2267: * acx_host_desc.h_data_len == acx_fw_txdesc.f_tx_len
2268: *
2269: * So we allocate two acx_host_desc for one acx_fw_txdesc and
2270: * assign the first acx_host_desc to acx_fw_txdesc
2271: *
2272: * For acx111
2273: * host_desc1.h_data_len = buffer_len
2274: * host_desc2.h_data_len = buffer_len - mac_header_len
2275: *
2276: * For acx100
2277: * host_desc1.h_data_len = mac_header_len
2278: * host_desc2.h_data_len = buffer_len - mac_header_len
2279: */
2280: paddr = txbuf->tb_mbuf_dmamap->dm_segs[0].ds_addr;
2281: txbuf->tb_desc1->h_data_paddr = htole32(paddr);
2282: txbuf->tb_desc2->h_data_paddr = htole32(paddr + ACX_FRAME_HDRLEN);
2283:
2284: txbuf->tb_desc1->h_data_len =
2285: htole16(sc->chip_txdesc1_len ? sc->chip_txdesc1_len
2286: : m->m_pkthdr.len);
2287: txbuf->tb_desc2->h_data_len =
2288: htole16(m->m_pkthdr.len - ACX_FRAME_HDRLEN);
2289:
2290: /*
2291: * NOTE:
2292: * We can't simply assign f_tx_ctrl, we will first read it back
2293: * and change it bit by bit
2294: */
2295: ctrl = FW_TXDESC_GETFIELD_1(sc, txbuf, f_tx_ctrl);
2296: ctrl |= sc->chip_fw_txdesc_ctrl; /* extra chip specific flags */
2297: ctrl &= ~(DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE);
2298:
2299: FW_TXDESC_SETFIELD_2(sc, txbuf, f_tx_len, m->m_pkthdr.len);
2300: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_error, 0);
2301: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ack_fail, 0);
2302: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_fail, 0);
2303: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_ok, 0);
2304: sc->chip_set_fw_txdesc_rate(sc, txbuf, rate);
2305:
2306: txbuf->tb_desc1->h_ctrl = 0;
2307: txbuf->tb_desc2->h_ctrl = 0;
2308: bus_dmamap_sync(sc->sc_dmat, rd->tx_ring_dmamap, 0,
2309: rd->tx_ring_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
2310:
2311: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl2, 0);
2312: FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl, ctrl);
2313:
2314: /* Tell chip to inform us about TX completion */
2315: CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_TX_FINI);
2316: back:
2317: if (error)
2318: m_freem(m);
2319:
2320: return (error);
2321: }
2322:
2323: int
2324: acx_set_null_tmplt(struct acx_softc *sc)
2325: {
2326: struct ieee80211com *ic = &sc->sc_ic;
2327: struct acx_tmplt_null_data n;
2328: struct ieee80211_frame *wh;
2329:
2330: bzero(&n, sizeof(n));
2331:
2332: wh = &n.data;
2333: wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA |
2334: IEEE80211_FC0_SUBTYPE_NODATA;
2335: wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2336: IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
2337: IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
2338: IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
2339:
2340: return (acx_set_tmplt(sc, ACXCMD_TMPLT_NULL_DATA, &n, sizeof(n)));
2341: }
2342:
2343: int
2344: acx_set_probe_req_tmplt(struct acx_softc *sc, const char *ssid, int ssid_len)
2345: {
2346: struct ieee80211com *ic = &sc->sc_ic;
2347: struct acx_tmplt_probe_req req;
2348: struct ieee80211_frame *wh;
2349: uint8_t *frm;
2350: int len;
2351:
2352: bzero(&req, sizeof(req));
2353:
2354: wh = &req.data.u_data.f;
2355: wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
2356: IEEE80211_FC0_SUBTYPE_PROBE_REQ;
2357: wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2358: IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
2359: IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
2360: IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
2361:
2362: frm = req.data.u_data.var;
2363: frm = ieee80211_add_ssid(frm, ssid, ssid_len);
2364: frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[sc->chip_phymode]);
2365: frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[sc->chip_phymode]);
2366: len = frm - req.data.u_data.var;
2367:
2368: return (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_REQ, &req,
2369: ACX_TMPLT_PROBE_REQ_SIZ(len)));
2370: }
2371:
2372: struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
2373: struct ieee80211_node *);
2374:
2375: int
2376: acx_set_probe_resp_tmplt(struct acx_softc *sc, struct ieee80211_node *ni)
2377: {
2378: struct ieee80211com *ic = &sc->sc_ic;
2379: struct acx_tmplt_probe_resp resp;
2380: struct ieee80211_frame *wh;
2381: struct mbuf *m;
2382: int len;
2383:
2384: bzero(&resp, sizeof(resp));
2385:
2386: m = ieee80211_get_probe_resp(ic, ni);
2387: if (m == NULL)
2388: return (1);
2389: M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
2390: if (m == NULL)
2391: return (1);
2392: wh = mtod(m, struct ieee80211_frame *);
2393: wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
2394: IEEE80211_FC0_SUBTYPE_PROBE_RESP;
2395: wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2396: *(u_int16_t *)&wh->i_dur[0] = 0;
2397: IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
2398: IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
2399: IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
2400: *(u_int16_t *)wh->i_seq = 0;
2401:
2402: m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&resp.data);
2403: len = m->m_pkthdr.len + sizeof(resp.size);
2404: m_freem(m);
2405:
2406: return (acx_set_tmplt(sc, ACXCMD_TMPLT_PROBE_RESP, &resp, len));
2407: }
2408:
2409: int
2410: acx_beacon_locate(struct mbuf *m, u_int8_t type)
2411: {
2412: int off;
2413: u_int8_t *frm;
2414: /*
2415: * beacon frame format
2416: * [8] time stamp
2417: * [2] beacon interval
2418: * [2] cabability information
2419: * from here on [tlv] values
2420: */
2421:
2422: if (m->m_len != m->m_pkthdr.len)
2423: panic("beacon not in contiguous mbuf");
2424:
2425: off = sizeof(struct ieee80211_frame) + 8 + 2 + 2;
2426: frm = mtod(m, u_int8_t *);
2427: for (; off + 1 < m->m_len; off += frm[off + 1] + 2) {
2428: if (frm[off] == type)
2429: return (off);
2430: }
2431: /* type not found */
2432: return (m->m_len);
2433: }
2434:
2435: int
2436: acx_set_beacon_tmplt(struct acx_softc *sc, struct ieee80211_node *ni)
2437: {
2438: struct ieee80211com *ic = &sc->sc_ic;
2439: struct acx_tmplt_beacon beacon;
2440: struct acx_tmplt_tim tim;
2441: struct mbuf *m;
2442: int len, off;
2443:
2444: bzero(&beacon, sizeof(beacon));
2445: bzero(&tim, sizeof(tim));
2446:
2447: m = ieee80211_beacon_alloc(ic, ni);
2448: if (m == NULL)
2449: return (1);
2450:
2451: off = acx_beacon_locate(m, IEEE80211_ELEMID_TIM);
2452:
2453: m_copydata(m, 0, off, (caddr_t)&beacon.data);
2454: len = off + sizeof(beacon.size);
2455:
2456: if (acx_set_tmplt(sc, ACXCMD_TMPLT_BEACON, &beacon, len) != 0) {
2457: m_freem(m);
2458: return (1);
2459: }
2460:
2461: len = m->m_pkthdr.len - off;
2462: if (len == 0) {
2463: /* no TIM field */
2464: m_freem(m);
2465: return (0);
2466: }
2467:
2468: m_copydata(m, off, len, (caddr_t)&tim.data);
2469: len += sizeof(beacon.size);
2470: m_freem(m);
2471:
2472: return (acx_set_tmplt(sc, ACXCMD_TMPLT_TIM, &tim, len));
2473: }
2474:
2475: void
2476: acx_init_cmd_reg(struct acx_softc *sc)
2477: {
2478: sc->sc_cmd = CSR_READ_4(sc, ACXREG_CMD_REG_OFFSET);
2479: sc->sc_cmd_param = sc->sc_cmd + ACX_CMD_REG_SIZE;
2480:
2481: /* Clear command & status */
2482: CMD_WRITE_4(sc, 0);
2483: }
2484:
2485: int
2486: acx_join_bss(struct acx_softc *sc, uint8_t mode, struct ieee80211_node *node)
2487: {
2488: uint8_t bj_buf[BSS_JOIN_BUFLEN];
2489: struct bss_join_hdr *bj;
2490: int i, dtim_intvl;
2491:
2492: bzero(bj_buf, sizeof(bj_buf));
2493: bj = (struct bss_join_hdr *)bj_buf;
2494:
2495: for (i = 0; i < IEEE80211_ADDR_LEN; ++i)
2496: bj->bssid[i] = node->ni_bssid[IEEE80211_ADDR_LEN - i - 1];
2497:
2498: bj->beacon_intvl = htole16(acx_beacon_intvl);
2499:
2500: /* TODO tunable */
2501: dtim_intvl = sc->sc_ic.ic_opmode == IEEE80211_M_IBSS ? 1 : 10;
2502: sc->chip_set_bss_join_param(sc, bj->chip_spec, dtim_intvl);
2503:
2504: bj->ndata_txrate = ACX_NDATA_TXRATE_2;
2505: bj->ndata_txopt = 0;
2506: bj->mode = mode;
2507: bj->channel = ieee80211_chan2ieee(&sc->sc_ic, node->ni_chan);
2508: bj->esslen = node->ni_esslen;
2509: bcopy(node->ni_essid, bj->essid, node->ni_esslen);
2510:
2511: DPRINTF(("%s: join BSS/IBSS on channel %d\n", sc->sc_dev.dv_xname,
2512: bj->channel));
2513: return (acx_exec_command(sc, ACXCMD_JOIN_BSS,
2514: bj, BSS_JOIN_PARAM_SIZE(bj), NULL, 0));
2515: }
2516:
2517: int
2518: acx_set_channel(struct acx_softc *sc, uint8_t chan)
2519: {
2520: if (acx_exec_command(sc, ACXCMD_ENABLE_TXCHAN, &chan, sizeof(chan),
2521: NULL, 0) != 0) {
2522: DPRINTF(("%s: setting TX channel %d failed\n",
2523: sc->sc_dev.dv_xname, chan));
2524: return (ENXIO);
2525: }
2526:
2527: if (acx_exec_command(sc, ACXCMD_ENABLE_RXCHAN, &chan, sizeof(chan),
2528: NULL, 0) != 0) {
2529: DPRINTF(("%s: setting RX channel %d failed\n",
2530: sc->sc_dev.dv_xname, chan));
2531: return (ENXIO);
2532: }
2533:
2534: return (0);
2535: }
2536:
2537: int
2538: acx_get_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
2539: uint16_t conf_len)
2540: {
2541: struct acx_conf *confcom;
2542:
2543: if (conf_len < sizeof(*confcom)) {
2544: printf("%s: %s configure data is too short\n",
2545: sc->sc_dev.dv_xname, __func__);
2546: return (1);
2547: }
2548:
2549: confcom = conf;
2550: confcom->conf_id = htole16(conf_id);
2551: confcom->conf_data_len = htole16(conf_len - sizeof(*confcom));
2552:
2553: return (acx_exec_command(sc, ACXCMD_GET_CONF, confcom, sizeof(*confcom),
2554: conf, conf_len));
2555: }
2556:
2557: int
2558: acx_set_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
2559: uint16_t conf_len)
2560: {
2561: struct acx_conf *confcom;
2562:
2563: if (conf_len < sizeof(*confcom)) {
2564: printf("%s: %s configure data is too short\n",
2565: sc->sc_dev.dv_xname, __func__);
2566: return (1);
2567: }
2568:
2569: confcom = conf;
2570: confcom->conf_id = htole16(conf_id);
2571: confcom->conf_data_len = htole16(conf_len - sizeof(*confcom));
2572:
2573: return (acx_exec_command(sc, ACXCMD_SET_CONF, conf, conf_len, NULL, 0));
2574: }
2575:
2576: int
2577: acx_set_tmplt(struct acx_softc *sc, uint16_t cmd, void *tmplt,
2578: uint16_t tmplt_len)
2579: {
2580: uint16_t *size;
2581:
2582: if (tmplt_len < sizeof(*size)) {
2583: printf("%s: %s template is too short\n",
2584: sc->sc_dev.dv_xname, __func__);
2585: return (1);
2586: }
2587:
2588: size = tmplt;
2589: *size = htole16(tmplt_len - sizeof(*size));
2590:
2591: return (acx_exec_command(sc, cmd, tmplt, tmplt_len, NULL, 0));
2592: }
2593:
2594: int
2595: acx_init_radio(struct acx_softc *sc, uint32_t radio_ofs, uint32_t radio_len)
2596: {
2597: struct radio_init r;
2598:
2599: r.radio_ofs = htole32(radio_ofs);
2600: r.radio_len = htole32(radio_len);
2601:
2602: return (acx_exec_command(sc, ACXCMD_INIT_RADIO, &r, sizeof(r), NULL,
2603: 0));
2604: }
2605:
2606: int
2607: acx_exec_command(struct acx_softc *sc, uint16_t cmd, void *param,
2608: uint16_t param_len, void *result, uint16_t result_len)
2609: {
2610: uint16_t status;
2611: int i, ret;
2612:
2613: if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0) {
2614: printf("%s: cmd 0x%04x failed (base firmware not loaded)\n",
2615: sc->sc_dev.dv_xname, cmd);
2616: return (1);
2617: }
2618:
2619: ret = 0;
2620:
2621: if (param != NULL && param_len != 0) {
2622: /* Set command param */
2623: CMDPRM_WRITE_REGION_1(sc, param, param_len);
2624: }
2625:
2626: /* Set command */
2627: CMD_WRITE_4(sc, cmd);
2628:
2629: /* Exec command */
2630: CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_CMD_FINI);
2631: DELAY(50);
2632:
2633: /* Wait for command to complete */
2634: if (cmd == ACXCMD_INIT_RADIO) {
2635: /* radio initialization is extremely long */
2636: tsleep(&cmd, 0, "rdinit", (300 * hz) / 1000); /* 300ms */
2637: }
2638:
2639: #define CMDWAIT_RETRY_MAX 1000
2640: for (i = 0; i < CMDWAIT_RETRY_MAX; ++i) {
2641: uint16_t reg;
2642:
2643: reg = CSR_READ_2(sc, ACXREG_INTR_STATUS);
2644: if (reg & ACXRV_INTR_CMD_FINI) {
2645: CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_CMD_FINI);
2646: break;
2647: }
2648: DELAY(50);
2649: }
2650: if (i == CMDWAIT_RETRY_MAX) {
2651: printf("%s: cmd %04x failed (timeout)\n",
2652: sc->sc_dev.dv_xname, cmd);
2653: ret = 1;
2654: goto back;
2655: }
2656: #undef CMDWAIT_RETRY_MAX
2657:
2658: /* Get command exec status */
2659: status = (CMD_READ_4(sc) >> ACX_CMD_STATUS_SHIFT);
2660: if (status != ACX_CMD_STATUS_OK) {
2661: DPRINTF(("%s: cmd %04x failed\n", sc->sc_dev.dv_xname, cmd));
2662: ret = 1;
2663: goto back;
2664: }
2665:
2666: if (result != NULL && result_len != 0) {
2667: /* Get command result */
2668: CMDPRM_READ_REGION_1(sc, result, result_len);
2669: }
2670:
2671: back:
2672: CMD_WRITE_4(sc, 0);
2673:
2674: return (ret);
2675: }
2676:
2677: const char *
2678: acx_get_rf(int rev)
2679: {
2680: switch (rev) {
2681: case ACX_RADIO_TYPE_MAXIM: return "MAX2820";
2682: case ACX_RADIO_TYPE_RFMD: return "RFMD";
2683: case ACX_RADIO_TYPE_RALINK: return "Ralink";
2684: case ACX_RADIO_TYPE_RADIA: return "Radia";
2685: default: return "unknown";
2686: }
2687: }
2688:
2689: int
2690: acx_get_maxrssi(int radio)
2691: {
2692: switch (radio) {
2693: case ACX_RADIO_TYPE_MAXIM: return ACX_RADIO_RSSI_MAXIM;
2694: case ACX_RADIO_TYPE_RFMD: return ACX_RADIO_RSSI_RFMD;
2695: case ACX_RADIO_TYPE_RALINK: return ACX_RADIO_RSSI_RALINK;
2696: case ACX_RADIO_TYPE_RADIA: return ACX_RADIO_RSSI_RADIA;
2697: default: return ACX_RADIO_RSSI_UNKN;
2698: }
2699: }
2700:
2701: void
2702: acx_iter_func(void *arg, struct ieee80211_node *ni)
2703: {
2704: struct acx_softc *sc = arg;
2705: struct acx_node *wn = (struct acx_node *)ni;
2706:
2707: ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
2708: }
2709:
2710: void
2711: acx_amrr_timeout(void *arg)
2712: {
2713: struct acx_softc *sc = arg;
2714: struct ieee80211com *ic = &sc->sc_ic;
2715:
2716: if (ic->ic_opmode == IEEE80211_M_STA)
2717: acx_iter_func(sc, ic->ic_bss);
2718: else
2719: ieee80211_iterate_nodes(ic, acx_iter_func, sc);
2720:
2721: timeout_add(&sc->amrr_ch, hz / 2);
2722: }
2723:
2724: void
2725: acx_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
2726: {
2727: struct acx_softc *sc = ic->ic_if.if_softc;
2728: int i;
2729:
2730: ieee80211_amrr_node_init(&sc->amrr, &((struct acx_node *)ni)->amn);
2731:
2732: /* set rate to some reasonable initial value */
2733: for (i = ni->ni_rates.rs_nrates - 1;
2734: i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
2735: i--);
2736: ni->ni_txrate = i;
2737: }
CVSweb