[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     ! 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