[BACK]Return to acx.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

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, &reg_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, &reg_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