LCOV - code coverage report
Current view: top level - dev/ic - acx.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1323 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 55 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13