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

          Line data    Source code
       1             : /*      $OpenBSD: if_wpi.c,v 1.144 2018/04/28 16:05:56 phessler Exp $   */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2006-2008
       5             :  *      Damien Bergamini <damien.bergamini@free.fr>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*
      21             :  * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
      22             :  */
      23             : 
      24             : #include "bpfilter.h"
      25             : 
      26             : #include <sys/param.h>
      27             : #include <sys/sockio.h>
      28             : #include <sys/mbuf.h>
      29             : #include <sys/kernel.h>
      30             : #include <sys/rwlock.h>
      31             : #include <sys/socket.h>
      32             : #include <sys/systm.h>
      33             : #include <sys/malloc.h>
      34             : #include <sys/conf.h>
      35             : #include <sys/device.h>
      36             : #include <sys/task.h>
      37             : #include <sys/endian.h>
      38             : 
      39             : #include <machine/bus.h>
      40             : #include <machine/intr.h>
      41             : 
      42             : #include <dev/pci/pcireg.h>
      43             : #include <dev/pci/pcivar.h>
      44             : #include <dev/pci/pcidevs.h>
      45             : 
      46             : #if NBPFILTER > 0
      47             : #include <net/bpf.h>
      48             : #endif
      49             : #include <net/if.h>
      50             : #include <net/if_dl.h>
      51             : #include <net/if_media.h>
      52             : 
      53             : #include <netinet/in.h>
      54             : #include <netinet/if_ether.h>
      55             : 
      56             : #include <net80211/ieee80211_var.h>
      57             : #include <net80211/ieee80211_amrr.h>
      58             : #include <net80211/ieee80211_radiotap.h>
      59             : 
      60             : #include <dev/pci/if_wpireg.h>
      61             : #include <dev/pci/if_wpivar.h>
      62             : 
      63             : static const struct pci_matchid wpi_devices[] = {
      64             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_3945ABG_1 },
      65             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_3945ABG_2 }
      66             : };
      67             : 
      68             : int             wpi_match(struct device *, void *, void *);
      69             : void            wpi_attach(struct device *, struct device *, void *);
      70             : #if NBPFILTER > 0
      71             : void            wpi_radiotap_attach(struct wpi_softc *);
      72             : #endif
      73             : int             wpi_detach(struct device *, int);
      74             : int             wpi_activate(struct device *, int);
      75             : void            wpi_wakeup(struct wpi_softc *);
      76             : void            wpi_init_task(void *);
      77             : int             wpi_nic_lock(struct wpi_softc *);
      78             : int             wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
      79             : int             wpi_dma_contig_alloc(bus_dma_tag_t, struct wpi_dma_info *,
      80             :                     void **, bus_size_t, bus_size_t);
      81             : void            wpi_dma_contig_free(struct wpi_dma_info *);
      82             : int             wpi_alloc_shared(struct wpi_softc *);
      83             : void            wpi_free_shared(struct wpi_softc *);
      84             : int             wpi_alloc_fwmem(struct wpi_softc *);
      85             : void            wpi_free_fwmem(struct wpi_softc *);
      86             : int             wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
      87             : void            wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
      88             : void            wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
      89             : int             wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
      90             :                     int);
      91             : void            wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
      92             : void            wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
      93             : int             wpi_read_eeprom(struct wpi_softc *);
      94             : void            wpi_read_eeprom_channels(struct wpi_softc *, int);
      95             : void            wpi_read_eeprom_group(struct wpi_softc *, int);
      96             : struct          ieee80211_node *wpi_node_alloc(struct ieee80211com *);
      97             : void            wpi_newassoc(struct ieee80211com *, struct ieee80211_node *,
      98             :                     int);
      99             : int             wpi_media_change(struct ifnet *);
     100             : int             wpi_newstate(struct ieee80211com *, enum ieee80211_state, int);
     101             : void            wpi_iter_func(void *, struct ieee80211_node *);
     102             : void            wpi_calib_timeout(void *);
     103             : int             wpi_ccmp_decap(struct wpi_softc *, struct mbuf *,
     104             :                     struct ieee80211_key *);
     105             : void            wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
     106             :                     struct wpi_rx_data *);
     107             : void            wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
     108             : void            wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
     109             : void            wpi_notif_intr(struct wpi_softc *);
     110             : void            wpi_fatal_intr(struct wpi_softc *);
     111             : int             wpi_intr(void *);
     112             : int             wpi_tx(struct wpi_softc *, struct mbuf *,
     113             :                     struct ieee80211_node *);
     114             : void            wpi_start(struct ifnet *);
     115             : void            wpi_watchdog(struct ifnet *);
     116             : int             wpi_ioctl(struct ifnet *, u_long, caddr_t);
     117             : int             wpi_cmd(struct wpi_softc *, int, const void *, int, int);
     118             : int             wpi_mrr_setup(struct wpi_softc *);
     119             : void            wpi_updateedca(struct ieee80211com *);
     120             : void            wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
     121             : int             wpi_set_timing(struct wpi_softc *, struct ieee80211_node *);
     122             : void            wpi_power_calibration(struct wpi_softc *);
     123             : int             wpi_set_txpower(struct wpi_softc *, int);
     124             : int             wpi_get_power_index(struct wpi_softc *,
     125             :                     struct wpi_power_group *, struct ieee80211_channel *, int);
     126             : int             wpi_set_pslevel(struct wpi_softc *, int, int, int);
     127             : int             wpi_config(struct wpi_softc *);
     128             : int             wpi_scan(struct wpi_softc *, uint16_t);
     129             : int             wpi_auth(struct wpi_softc *);
     130             : int             wpi_run(struct wpi_softc *);
     131             : int             wpi_set_key(struct ieee80211com *, struct ieee80211_node *,
     132             :                     struct ieee80211_key *);
     133             : void            wpi_delete_key(struct ieee80211com *, struct ieee80211_node *,
     134             :                     struct ieee80211_key *);
     135             : int             wpi_post_alive(struct wpi_softc *);
     136             : int             wpi_load_bootcode(struct wpi_softc *, const uint8_t *, int);
     137             : int             wpi_load_firmware(struct wpi_softc *);
     138             : int             wpi_read_firmware(struct wpi_softc *);
     139             : int             wpi_clock_wait(struct wpi_softc *);
     140             : int             wpi_apm_init(struct wpi_softc *);
     141             : void            wpi_apm_stop_master(struct wpi_softc *);
     142             : void            wpi_apm_stop(struct wpi_softc *);
     143             : void            wpi_nic_config(struct wpi_softc *);
     144             : int             wpi_hw_init(struct wpi_softc *);
     145             : void            wpi_hw_stop(struct wpi_softc *);
     146             : int             wpi_init(struct ifnet *);
     147             : void            wpi_stop(struct ifnet *, int);
     148             : 
     149             : #ifdef WPI_DEBUG
     150             : #define DPRINTF(x)      do { if (wpi_debug > 0) printf x; } while (0)
     151             : #define DPRINTFN(n, x)  do { if (wpi_debug >= (n)) printf x; } while (0)
     152             : int wpi_debug = 0;
     153             : #else
     154             : #define DPRINTF(x)
     155             : #define DPRINTFN(n, x)
     156             : #endif
     157             : 
     158             : struct cfdriver wpi_cd = {
     159             :         NULL, "wpi", DV_IFNET
     160             : };
     161             : 
     162             : struct cfattach wpi_ca = {
     163             :         sizeof (struct wpi_softc), wpi_match, wpi_attach, wpi_detach,
     164             :         wpi_activate
     165             : };
     166             : 
     167             : int
     168           0 : wpi_match(struct device *parent, void *match, void *aux)
     169             : {
     170           0 :         return pci_matchbyid((struct pci_attach_args *)aux, wpi_devices,
     171             :             nitems(wpi_devices));
     172             : }
     173             : 
     174             : void
     175           0 : wpi_attach(struct device *parent, struct device *self, void *aux)
     176             : {
     177           0 :         struct wpi_softc *sc = (struct wpi_softc *)self;
     178           0 :         struct ieee80211com *ic = &sc->sc_ic;
     179           0 :         struct ifnet *ifp = &ic->ic_if;
     180           0 :         struct pci_attach_args *pa = aux;
     181             :         const char *intrstr;
     182           0 :         pci_intr_handle_t ih;
     183             :         pcireg_t memtype, reg;
     184             :         int i, error;
     185             : 
     186           0 :         sc->sc_pct = pa->pa_pc;
     187           0 :         sc->sc_pcitag = pa->pa_tag;
     188           0 :         sc->sc_dmat = pa->pa_dmat;
     189             : 
     190             :         /*
     191             :          * Get the offset of the PCI Express Capability Structure in PCI
     192             :          * Configuration Space (the vendor driver hard-codes it as E0h.)
     193             :          */
     194           0 :         error = pci_get_capability(sc->sc_pct, sc->sc_pcitag,
     195           0 :             PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL);
     196           0 :         if (error == 0) {
     197           0 :                 printf(": PCIe capability structure not found!\n");
     198           0 :                 return;
     199             :         }
     200             : 
     201             :         /* Clear device-specific "PCI retry timeout" register (41h). */
     202           0 :         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
     203           0 :         reg &= ~0xff00;
     204           0 :         pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg);
     205             : 
     206           0 :         memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WPI_PCI_BAR0);
     207           0 :         error = pci_mapreg_map(pa, WPI_PCI_BAR0, memtype, 0, &sc->sc_st,
     208           0 :             &sc->sc_sh, NULL, &sc->sc_sz, 0);
     209           0 :         if (error != 0) {
     210           0 :                 printf(": can't map mem space\n");
     211           0 :                 return;
     212             :         }
     213             : 
     214             :         /* Install interrupt handler. */
     215           0 :         if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
     216           0 :                 printf(": can't map interrupt\n");
     217           0 :                 return;
     218             :         }
     219           0 :         intrstr = pci_intr_string(sc->sc_pct, ih);
     220           0 :         sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, wpi_intr, sc,
     221           0 :             sc->sc_dev.dv_xname);
     222           0 :         if (sc->sc_ih == NULL) {
     223           0 :                 printf(": can't establish interrupt");
     224           0 :                 if (intrstr != NULL)
     225           0 :                         printf(" at %s", intrstr);
     226           0 :                 printf("\n");
     227           0 :                 return;
     228             :         }
     229           0 :         printf(": %s", intrstr);
     230             : 
     231             :         /* Power ON adapter. */
     232           0 :         if ((error = wpi_apm_init(sc)) != 0) {
     233           0 :                 printf(": could not power ON adapter\n");
     234           0 :                 return;
     235             :         }
     236             : 
     237             :         /* Read MAC address, channels, etc from EEPROM. */
     238           0 :         if ((error = wpi_read_eeprom(sc)) != 0) {
     239           0 :                 printf(": could not read EEPROM\n");
     240           0 :                 return;
     241             :         }
     242             : 
     243             :         /* Allocate DMA memory for firmware transfers. */
     244           0 :         if ((error = wpi_alloc_fwmem(sc)) != 0) {
     245           0 :                 printf(": could not allocate memory for firmware\n");
     246           0 :                 return;
     247             :         }
     248             : 
     249             :         /* Allocate shared area. */
     250           0 :         if ((error = wpi_alloc_shared(sc)) != 0) {
     251           0 :                 printf(": could not allocate shared area\n");
     252           0 :                 goto fail1;
     253             :         }
     254             : 
     255             :         /* Allocate TX rings. */
     256           0 :         for (i = 0; i < WPI_NTXQUEUES; i++) {
     257           0 :                 if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
     258           0 :                         printf(": could not allocate TX ring %d\n", i);
     259           0 :                         goto fail2;
     260             :                 }
     261             :         }
     262             : 
     263             :         /* Allocate RX ring. */
     264           0 :         if ((error = wpi_alloc_rx_ring(sc, &sc->rxq)) != 0) {
     265           0 :                 printf(": could not allocate Rx ring\n");
     266           0 :                 goto fail2;
     267             :         }
     268             : 
     269             :         /* Power OFF adapter. */
     270           0 :         wpi_apm_stop(sc);
     271             :         /* Clear pending interrupts. */
     272           0 :         WPI_WRITE(sc, WPI_INT, 0xffffffff);
     273             : 
     274           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     275           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     276           0 :         ic->ic_state = IEEE80211_S_INIT;
     277             : 
     278             :         /* Set device capabilities. */
     279           0 :         ic->ic_caps =
     280             :             IEEE80211_C_WEP |           /* WEP */
     281             :             IEEE80211_C_RSN |           /* WPA/RSN */
     282             :             IEEE80211_C_SCANALL |       /* device scans all channels at once */
     283             :             IEEE80211_C_SCANALLBAND |   /* driver scans all bands at once */
     284             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     285             :             IEEE80211_C_SHSLOT |        /* short slot time supported */
     286             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     287             :             IEEE80211_C_PMGT;           /* power saving supported */
     288             : 
     289             :         /* Set supported rates. */
     290           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     291           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     292           0 :         if (sc->sc_flags & WPI_FLAG_HAS_5GHZ) {
     293           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11A] =
     294           0 :                     ieee80211_std_rateset_11a;
     295           0 :         }
     296             : 
     297             :         /* IBSS channel undefined for now. */
     298           0 :         ic->ic_ibss_chan = &ic->ic_channels[0];
     299             : 
     300           0 :         ifp->if_softc = sc;
     301           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     302           0 :         ifp->if_ioctl = wpi_ioctl;
     303           0 :         ifp->if_start = wpi_start;
     304           0 :         ifp->if_watchdog = wpi_watchdog;
     305           0 :         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     306             : 
     307           0 :         if_attach(ifp);
     308           0 :         ieee80211_ifattach(ifp);
     309           0 :         ic->ic_node_alloc = wpi_node_alloc;
     310           0 :         ic->ic_newassoc = wpi_newassoc;
     311           0 :         ic->ic_updateedca = wpi_updateedca;
     312           0 :         ic->ic_set_key = wpi_set_key;
     313           0 :         ic->ic_delete_key = wpi_delete_key;
     314             : 
     315             :         /* Override 802.11 state transition machine. */
     316           0 :         sc->sc_newstate = ic->ic_newstate;
     317           0 :         ic->ic_newstate = wpi_newstate;
     318           0 :         ieee80211_media_init(ifp, wpi_media_change, ieee80211_media_status);
     319             : 
     320           0 :         sc->amrr.amrr_min_success_threshold =  1;
     321           0 :         sc->amrr.amrr_max_success_threshold = 15;
     322             : 
     323             : #if NBPFILTER > 0
     324           0 :         wpi_radiotap_attach(sc);
     325             : #endif
     326           0 :         timeout_set(&sc->calib_to, wpi_calib_timeout, sc);
     327           0 :         rw_init(&sc->sc_rwlock, "wpilock");
     328           0 :         task_set(&sc->init_task, wpi_init_task, sc);
     329           0 :         return;
     330             : 
     331             :         /* Free allocated memory if something failed during attachment. */
     332           0 : fail2:  while (--i >= 0)
     333           0 :                 wpi_free_tx_ring(sc, &sc->txq[i]);
     334           0 :         wpi_free_shared(sc);
     335           0 : fail1:  wpi_free_fwmem(sc);
     336           0 : }
     337             : 
     338             : #if NBPFILTER > 0
     339             : /*
     340             :  * Attach the interface to 802.11 radiotap.
     341             :  */
     342             : void
     343           0 : wpi_radiotap_attach(struct wpi_softc *sc)
     344             : {
     345           0 :         bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
     346             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     347             : 
     348           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     349           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     350           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(WPI_RX_RADIOTAP_PRESENT);
     351             : 
     352           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     353           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     354           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(WPI_TX_RADIOTAP_PRESENT);
     355           0 : }
     356             : #endif
     357             : 
     358             : int
     359           0 : wpi_detach(struct device *self, int flags)
     360             : {
     361           0 :         struct wpi_softc *sc = (struct wpi_softc *)self;
     362           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     363             :         int qid;
     364             : 
     365           0 :         timeout_del(&sc->calib_to);
     366           0 :         task_del(systq, &sc->init_task);
     367             : 
     368             :         /* Uninstall interrupt handler. */
     369           0 :         if (sc->sc_ih != NULL)
     370           0 :                 pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
     371             : 
     372             :         /* Free DMA resources. */
     373           0 :         wpi_free_rx_ring(sc, &sc->rxq);
     374           0 :         for (qid = 0; qid < WPI_NTXQUEUES; qid++)
     375           0 :                 wpi_free_tx_ring(sc, &sc->txq[qid]);
     376           0 :         wpi_free_shared(sc);
     377           0 :         wpi_free_fwmem(sc);
     378             : 
     379           0 :         bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
     380             : 
     381           0 :         ieee80211_ifdetach(ifp);
     382           0 :         if_detach(ifp);
     383             : 
     384           0 :         return 0;
     385             : }
     386             : 
     387             : int
     388           0 : wpi_activate(struct device *self, int act)
     389             : {
     390           0 :         struct wpi_softc *sc = (struct wpi_softc *)self;
     391           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     392             : 
     393           0 :         switch (act) {
     394             :         case DVACT_SUSPEND:
     395           0 :                 if (ifp->if_flags & IFF_RUNNING)
     396           0 :                         wpi_stop(ifp, 0);
     397             :                 break;
     398             :         case DVACT_WAKEUP:
     399           0 :                 wpi_wakeup(sc);
     400           0 :                 break;
     401             :         }
     402             : 
     403           0 :         return 0;
     404             : }
     405             : 
     406             : void
     407           0 : wpi_wakeup(struct wpi_softc *sc)
     408             : {
     409             :         pcireg_t reg;
     410             : 
     411             :         /* Clear device-specific "PCI retry timeout" register (41h). */
     412           0 :         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
     413           0 :         reg &= ~0xff00;
     414           0 :         pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, reg);
     415             : 
     416           0 :         wpi_init_task(sc);
     417           0 : }
     418             : 
     419             : void
     420           0 : wpi_init_task(void *arg1)
     421             : {
     422           0 :         struct wpi_softc *sc = arg1;
     423           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     424             :         int s;
     425             : 
     426           0 :         rw_enter_write(&sc->sc_rwlock);
     427           0 :         s = splnet();
     428             : 
     429           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
     430           0 :                 wpi_init(ifp);
     431             : 
     432           0 :         splx(s);
     433           0 :         rw_exit_write(&sc->sc_rwlock);
     434           0 : }
     435             : 
     436             : int
     437           0 : wpi_nic_lock(struct wpi_softc *sc)
     438             : {
     439             :         int ntries;
     440             : 
     441             :         /* Request exclusive access to NIC. */
     442           0 :         WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ);
     443             : 
     444             :         /* Spin until we actually get the lock. */
     445           0 :         for (ntries = 0; ntries < 1000; ntries++) {
     446           0 :                 if ((WPI_READ(sc, WPI_GP_CNTRL) &
     447           0 :                      (WPI_GP_CNTRL_MAC_ACCESS_ENA | WPI_GP_CNTRL_SLEEP)) ==
     448             :                     WPI_GP_CNTRL_MAC_ACCESS_ENA)
     449           0 :                         return 0;
     450           0 :                 DELAY(10);
     451             :         }
     452           0 :         return ETIMEDOUT;
     453           0 : }
     454             : 
     455             : static __inline void
     456           0 : wpi_nic_unlock(struct wpi_softc *sc)
     457             : {
     458           0 :         WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ);
     459           0 : }
     460             : 
     461             : static __inline uint32_t
     462           0 : wpi_prph_read(struct wpi_softc *sc, uint32_t addr)
     463             : {
     464           0 :         WPI_WRITE(sc, WPI_PRPH_RADDR, WPI_PRPH_DWORD | addr);
     465           0 :         WPI_BARRIER_READ_WRITE(sc);
     466           0 :         return WPI_READ(sc, WPI_PRPH_RDATA);
     467             : }
     468             : 
     469             : static __inline void
     470           0 : wpi_prph_write(struct wpi_softc *sc, uint32_t addr, uint32_t data)
     471             : {
     472           0 :         WPI_WRITE(sc, WPI_PRPH_WADDR, WPI_PRPH_DWORD | addr);
     473           0 :         WPI_BARRIER_WRITE(sc);
     474           0 :         WPI_WRITE(sc, WPI_PRPH_WDATA, data);
     475           0 : }
     476             : 
     477             : static __inline void
     478           0 : wpi_prph_setbits(struct wpi_softc *sc, uint32_t addr, uint32_t mask)
     479             : {
     480           0 :         wpi_prph_write(sc, addr, wpi_prph_read(sc, addr) | mask);
     481           0 : }
     482             : 
     483             : static __inline void
     484           0 : wpi_prph_clrbits(struct wpi_softc *sc, uint32_t addr, uint32_t mask)
     485             : {
     486           0 :         wpi_prph_write(sc, addr, wpi_prph_read(sc, addr) & ~mask);
     487           0 : }
     488             : 
     489             : static __inline void
     490           0 : wpi_prph_write_region_4(struct wpi_softc *sc, uint32_t addr,
     491             :     const uint32_t *data, int count)
     492             : {
     493           0 :         for (; count > 0; count--, data++, addr += 4)
     494           0 :                 wpi_prph_write(sc, addr, *data);
     495           0 : }
     496             : 
     497             : #ifdef WPI_DEBUG
     498             : 
     499             : static __inline uint32_t
     500             : wpi_mem_read(struct wpi_softc *sc, uint32_t addr)
     501             : {
     502             :         WPI_WRITE(sc, WPI_MEM_RADDR, addr);
     503             :         WPI_BARRIER_READ_WRITE(sc);
     504             :         return WPI_READ(sc, WPI_MEM_RDATA);
     505             : }
     506             : 
     507             : static __inline void  
     508             : wpi_mem_write(struct wpi_softc *sc, uint32_t addr, uint32_t data)
     509             : {
     510             :         WPI_WRITE(sc, WPI_MEM_WADDR, addr);
     511             :         WPI_BARRIER_WRITE(sc);
     512             :         WPI_WRITE(sc, WPI_MEM_WDATA, data);
     513             : }
     514             : 
     515             : static __inline void
     516             : wpi_mem_read_region_4(struct wpi_softc *sc, uint32_t addr, uint32_t *data,
     517             :     int count)
     518             : {
     519             :         for (; count > 0; count--, addr += 4)
     520             :                 *data++ = wpi_mem_read(sc, addr);
     521             : }
     522             : 
     523             : #endif
     524             : 
     525             : int
     526           0 : wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int count)
     527             : {
     528             :         uint8_t *out = data;
     529             :         uint32_t val;
     530             :         int error, ntries;
     531             : 
     532           0 :         if ((error = wpi_nic_lock(sc)) != 0)
     533           0 :                 return error;
     534             : 
     535           0 :         for (; count > 0; count -= 2, addr++) {
     536           0 :                 WPI_WRITE(sc, WPI_EEPROM, addr << 2);
     537           0 :                 WPI_CLRBITS(sc, WPI_EEPROM, WPI_EEPROM_CMD);
     538             : 
     539           0 :                 for (ntries = 0; ntries < 10; ntries++) {
     540           0 :                         val = WPI_READ(sc, WPI_EEPROM);
     541           0 :                         if (val & WPI_EEPROM_READ_VALID)
     542             :                                 break;
     543           0 :                         DELAY(5);
     544             :                 }
     545           0 :                 if (ntries == 10) {
     546           0 :                         printf("%s: could not read EEPROM\n",
     547           0 :                             sc->sc_dev.dv_xname);
     548           0 :                         return ETIMEDOUT;
     549             :                 }
     550           0 :                 *out++ = val >> 16;
     551           0 :                 if (count > 1)
     552           0 :                         *out++ = val >> 24;
     553             :         }
     554             : 
     555           0 :         wpi_nic_unlock(sc);
     556           0 :         return 0;
     557           0 : }
     558             : 
     559             : int
     560           0 : wpi_dma_contig_alloc(bus_dma_tag_t tag, struct wpi_dma_info *dma, void **kvap,
     561             :     bus_size_t size, bus_size_t alignment)
     562             : {
     563           0 :         int nsegs, error;
     564             : 
     565           0 :         dma->tag = tag;
     566           0 :         dma->size = size;
     567             : 
     568           0 :         error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
     569             :             &dma->map);
     570           0 :         if (error != 0)
     571             :                 goto fail;
     572             : 
     573           0 :         error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,
     574             :             BUS_DMA_NOWAIT | BUS_DMA_ZERO);
     575           0 :         if (error != 0)
     576             :                 goto fail;
     577             : 
     578           0 :         error = bus_dmamem_map(tag, &dma->seg, 1, size, &dma->vaddr,
     579             :             BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
     580           0 :         if (error != 0)
     581             :                 goto fail;
     582             : 
     583           0 :         error = bus_dmamap_load_raw(tag, dma->map, &dma->seg, 1, size,
     584             :             BUS_DMA_NOWAIT);
     585           0 :         if (error != 0)
     586             :                 goto fail;
     587             : 
     588           0 :         bus_dmamap_sync(tag, dma->map, 0, size, BUS_DMASYNC_PREWRITE);
     589             : 
     590           0 :         dma->paddr = dma->map->dm_segs[0].ds_addr;
     591           0 :         if (kvap != NULL)
     592           0 :                 *kvap = dma->vaddr;
     593             : 
     594           0 :         return 0;
     595             : 
     596           0 : fail:   wpi_dma_contig_free(dma);
     597           0 :         return error;
     598           0 : }
     599             : 
     600             : void
     601           0 : wpi_dma_contig_free(struct wpi_dma_info *dma)
     602             : {
     603           0 :         if (dma->map != NULL) {
     604           0 :                 if (dma->vaddr != NULL) {
     605           0 :                         bus_dmamap_sync(dma->tag, dma->map, 0, dma->size,
     606             :                             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
     607           0 :                         bus_dmamap_unload(dma->tag, dma->map);
     608           0 :                         bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
     609           0 :                         bus_dmamem_free(dma->tag, &dma->seg, 1);
     610           0 :                         dma->vaddr = NULL;
     611           0 :                 }
     612           0 :                 bus_dmamap_destroy(dma->tag, dma->map);
     613           0 :                 dma->map = NULL;
     614           0 :         }
     615           0 : }
     616             : 
     617             : int
     618           0 : wpi_alloc_shared(struct wpi_softc *sc)
     619             : {
     620             :         /* Shared buffer must be aligned on a 4KB boundary. */
     621           0 :         return wpi_dma_contig_alloc(sc->sc_dmat, &sc->shared_dma,
     622           0 :             (void **)&sc->shared, sizeof (struct wpi_shared), 4096);
     623             : }
     624             : 
     625             : void
     626           0 : wpi_free_shared(struct wpi_softc *sc)
     627             : {
     628           0 :         wpi_dma_contig_free(&sc->shared_dma);
     629           0 : }
     630             : 
     631             : int
     632           0 : wpi_alloc_fwmem(struct wpi_softc *sc)
     633             : {
     634             :         /* Allocate enough contiguous space to store text and data. */
     635           0 :         return wpi_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL,
     636             :             WPI_FW_TEXT_MAXSZ + WPI_FW_DATA_MAXSZ, 16);
     637             : }
     638             : 
     639             : void
     640           0 : wpi_free_fwmem(struct wpi_softc *sc)
     641             : {
     642           0 :         wpi_dma_contig_free(&sc->fw_dma);
     643           0 : }
     644             : 
     645             : int
     646           0 : wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
     647             : {
     648             :         bus_size_t size;
     649             :         int i, error;
     650             : 
     651           0 :         ring->cur = 0;
     652             : 
     653             :         /* Allocate RX descriptors (16KB aligned.) */
     654             :         size = WPI_RX_RING_COUNT * sizeof (uint32_t);
     655           0 :         error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
     656           0 :             (void **)&ring->desc, size, 16 * 1024);
     657           0 :         if (error != 0) {
     658           0 :                 printf("%s: could not allocate RX ring DMA memory\n",
     659           0 :                     sc->sc_dev.dv_xname);
     660           0 :                 goto fail;
     661             :         }
     662             : 
     663             :         /*
     664             :          * Allocate and map RX buffers.
     665             :          */
     666           0 :         for (i = 0; i < WPI_RX_RING_COUNT; i++) {
     667           0 :                 struct wpi_rx_data *data = &ring->data[i];
     668             : 
     669           0 :                 error = bus_dmamap_create(sc->sc_dmat, WPI_RBUF_SIZE, 1,
     670             :                     WPI_RBUF_SIZE, 0, BUS_DMA_NOWAIT, &data->map);
     671           0 :                 if (error != 0) {
     672           0 :                         printf("%s: could not create RX buf DMA map\n",
     673           0 :                             sc->sc_dev.dv_xname);
     674           0 :                         goto fail;
     675             :                 }
     676             : 
     677           0 :                 data->m = MCLGETI(NULL, M_DONTWAIT, NULL, WPI_RBUF_SIZE);
     678           0 :                 if (data->m == NULL) {
     679           0 :                         printf("%s: could not allocate RX mbuf\n",
     680           0 :                             sc->sc_dev.dv_xname);
     681             :                         error = ENOBUFS;
     682           0 :                         goto fail;
     683             :                 }
     684             : 
     685           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
     686             :                     mtod(data->m, void *), WPI_RBUF_SIZE, NULL,
     687             :                     BUS_DMA_NOWAIT | BUS_DMA_READ);
     688           0 :                 if (error != 0) {
     689           0 :                         printf("%s: can't map mbuf (error %d)\n",
     690           0 :                             sc->sc_dev.dv_xname, error);
     691           0 :                         goto fail;
     692             :                 }
     693             : 
     694             :                 /* Set physical address of RX buffer. */
     695           0 :                 ring->desc[i] = htole32(data->map->dm_segs[0].ds_addr);
     696           0 :         }
     697             : 
     698           0 :         bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map, 0, size,
     699             :             BUS_DMASYNC_PREWRITE);
     700             : 
     701           0 :         return 0;
     702             : 
     703           0 : fail:   wpi_free_rx_ring(sc, ring);
     704           0 :         return error;
     705           0 : }
     706             : 
     707             : void
     708           0 : wpi_reset_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
     709             : {
     710             :         int ntries;
     711             : 
     712           0 :         if (wpi_nic_lock(sc) == 0) {
     713           0 :                 WPI_WRITE(sc, WPI_FH_RX_CONFIG, 0);
     714           0 :                 for (ntries = 0; ntries < 100; ntries++) {
     715           0 :                         if (WPI_READ(sc, WPI_FH_RX_STATUS) &
     716             :                             WPI_FH_RX_STATUS_IDLE)
     717             :                                 break;
     718           0 :                         DELAY(10);
     719             :                 }
     720           0 :                 wpi_nic_unlock(sc);
     721           0 :         }
     722           0 :         ring->cur = 0;
     723           0 : }
     724             : 
     725             : void
     726           0 : wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
     727             : {
     728             :         int i;
     729             : 
     730           0 :         wpi_dma_contig_free(&ring->desc_dma);
     731             : 
     732           0 :         for (i = 0; i < WPI_RX_RING_COUNT; i++) {
     733           0 :                 struct wpi_rx_data *data = &ring->data[i];
     734             : 
     735           0 :                 if (data->m != NULL) {
     736           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     737             :                             data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
     738           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     739           0 :                         m_freem(data->m);
     740           0 :                 }
     741           0 :                 if (data->map != NULL)
     742           0 :                         bus_dmamap_destroy(sc->sc_dmat, data->map);
     743             :         }
     744           0 : }
     745             : 
     746             : int
     747           0 : wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int qid)
     748             : {
     749             :         bus_addr_t paddr;
     750             :         bus_size_t size;
     751             :         int i, error;
     752             : 
     753           0 :         ring->qid = qid;
     754           0 :         ring->queued = 0;
     755           0 :         ring->cur = 0;
     756             : 
     757             :         /* Allocate TX descriptors (16KB aligned.) */
     758             :         size = WPI_TX_RING_COUNT * sizeof (struct wpi_tx_desc);
     759           0 :         error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
     760           0 :             (void **)&ring->desc, size, 16 * 1024);
     761           0 :         if (error != 0) {
     762           0 :                 printf("%s: could not allocate TX ring DMA memory\n",
     763           0 :                     sc->sc_dev.dv_xname);
     764           0 :                 goto fail;
     765             :         }
     766             : 
     767             :         /* Update shared area with ring physical address. */
     768           0 :         sc->shared->txbase[qid] = htole32(ring->desc_dma.paddr);
     769           0 :         bus_dmamap_sync(sc->sc_dmat, sc->shared_dma.map, 0,
     770             :             sizeof (struct wpi_shared), BUS_DMASYNC_PREWRITE);
     771             : 
     772             :         /*
     773             :          * We only use rings 0 through 4 (4 EDCA + cmd) so there is no need
     774             :          * to allocate commands space for other rings.
     775             :          * XXX Do we really need to allocate descriptors for other rings?
     776             :          */
     777           0 :         if (qid > 4)
     778           0 :                 return 0;
     779             : 
     780             :         size = WPI_TX_RING_COUNT * sizeof (struct wpi_tx_cmd);
     781           0 :         error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma,
     782           0 :             (void **)&ring->cmd, size, 4);
     783           0 :         if (error != 0) {
     784           0 :                 printf("%s: could not allocate TX cmd DMA memory\n",
     785           0 :                     sc->sc_dev.dv_xname);
     786           0 :                 goto fail;
     787             :         }
     788             : 
     789           0 :         paddr = ring->cmd_dma.paddr;
     790           0 :         for (i = 0; i < WPI_TX_RING_COUNT; i++) {
     791           0 :                 struct wpi_tx_data *data = &ring->data[i];
     792             : 
     793           0 :                 data->cmd_paddr = paddr;
     794           0 :                 paddr += sizeof (struct wpi_tx_cmd);
     795             : 
     796           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
     797             :                     WPI_MAX_SCATTER - 1, MCLBYTES, 0, BUS_DMA_NOWAIT,
     798             :                     &data->map);
     799           0 :                 if (error != 0) {
     800           0 :                         printf("%s: could not create TX buf DMA map\n",
     801           0 :                             sc->sc_dev.dv_xname);
     802           0 :                         goto fail;
     803             :                 }
     804           0 :         }
     805           0 :         return 0;
     806             : 
     807           0 : fail:   wpi_free_tx_ring(sc, ring);
     808           0 :         return error;
     809           0 : }
     810             : 
     811             : void
     812           0 : wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
     813             : {
     814             :         int i;
     815             : 
     816           0 :         for (i = 0; i < WPI_TX_RING_COUNT; i++) {
     817           0 :                 struct wpi_tx_data *data = &ring->data[i];
     818             : 
     819           0 :                 if (data->m != NULL) {
     820           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     821             :                             data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     822           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     823           0 :                         m_freem(data->m);
     824           0 :                         data->m = NULL;
     825           0 :                 }
     826             :         }
     827             :         /* Clear TX descriptors. */
     828           0 :         memset(ring->desc, 0, ring->desc_dma.size);
     829           0 :         sc->qfullmsk &= ~(1 << ring->qid);
     830           0 :         ring->queued = 0;
     831           0 :         ring->cur = 0;
     832           0 : }
     833             : 
     834             : void
     835           0 : wpi_free_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
     836             : {
     837             :         int i;
     838             : 
     839           0 :         wpi_dma_contig_free(&ring->desc_dma);
     840           0 :         wpi_dma_contig_free(&ring->cmd_dma);
     841             : 
     842           0 :         for (i = 0; i < WPI_TX_RING_COUNT; i++) {
     843           0 :                 struct wpi_tx_data *data = &ring->data[i];
     844             : 
     845           0 :                 if (data->m != NULL) {
     846           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     847             :                             data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     848           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     849           0 :                         m_freem(data->m);
     850           0 :                 }
     851           0 :                 if (data->map != NULL)
     852           0 :                         bus_dmamap_destroy(sc->sc_dmat, data->map);
     853             :         }
     854           0 : }
     855             : 
     856             : int
     857           0 : wpi_read_eeprom(struct wpi_softc *sc)
     858             : {
     859           0 :         struct ieee80211com *ic = &sc->sc_ic;
     860           0 :         char domain[4];
     861             :         int i;
     862             : 
     863           0 :         if ((WPI_READ(sc, WPI_EEPROM_GP) & 0x6) == 0) {
     864           0 :                 printf("%s: bad EEPROM signature\n", sc->sc_dev.dv_xname);
     865           0 :                 return EIO;
     866             :         }
     867             :         /* Clear HW ownership of EEPROM. */
     868           0 :         WPI_CLRBITS(sc, WPI_EEPROM_GP, WPI_EEPROM_GP_IF_OWNER);
     869             : 
     870           0 :         wpi_read_prom_data(sc, WPI_EEPROM_CAPABILITIES, &sc->cap, 1);
     871           0 :         wpi_read_prom_data(sc, WPI_EEPROM_REVISION, &sc->rev, 2);
     872           0 :         wpi_read_prom_data(sc, WPI_EEPROM_TYPE, &sc->type, 1);
     873             : 
     874             :         DPRINTF(("cap=%x rev=%x type=%x\n", sc->cap, letoh16(sc->rev),
     875             :             sc->type));
     876             : 
     877             :         /* Read and print regulatory domain (4 ASCII characters.) */
     878           0 :         wpi_read_prom_data(sc, WPI_EEPROM_DOMAIN, domain, 4);
     879           0 :         printf(", %.4s", domain);
     880             : 
     881             :         /* Read and print MAC address. */
     882           0 :         wpi_read_prom_data(sc, WPI_EEPROM_MAC, ic->ic_myaddr, 6);
     883           0 :         printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
     884             : 
     885             :         /* Read the list of authorized channels. */
     886           0 :         for (i = 0; i < WPI_CHAN_BANDS_COUNT; i++)
     887           0 :                 wpi_read_eeprom_channels(sc, i);
     888             : 
     889             :         /* Read the list of TX power groups. */
     890           0 :         for (i = 0; i < WPI_POWER_GROUPS_COUNT; i++)
     891           0 :                 wpi_read_eeprom_group(sc, i);
     892             : 
     893           0 :         return 0;
     894           0 : }
     895             : 
     896             : void
     897           0 : wpi_read_eeprom_channels(struct wpi_softc *sc, int n)
     898             : {
     899           0 :         struct ieee80211com *ic = &sc->sc_ic;
     900           0 :         const struct wpi_chan_band *band = &wpi_bands[n];
     901           0 :         struct wpi_eeprom_chan channels[WPI_MAX_CHAN_PER_BAND];
     902             :         int chan, i;
     903             : 
     904           0 :         wpi_read_prom_data(sc, band->addr, channels,
     905           0 :             band->nchan * sizeof (struct wpi_eeprom_chan));
     906             : 
     907           0 :         for (i = 0; i < band->nchan; i++) {
     908           0 :                 if (!(channels[i].flags & WPI_EEPROM_CHAN_VALID))
     909             :                         continue;
     910             : 
     911           0 :                 chan = band->chan[i];
     912             : 
     913           0 :                 if (n == 0) {   /* 2GHz band */
     914           0 :                         ic->ic_channels[chan].ic_freq =
     915           0 :                             ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
     916           0 :                         ic->ic_channels[chan].ic_flags =
     917             :                             IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     918             :                             IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     919             : 
     920           0 :                 } else {        /* 5GHz band */
     921             :                         /*
     922             :                          * Some adapters support channels 7, 8, 11 and 12
     923             :                          * both in the 2GHz and 4.9GHz bands.
     924             :                          * Because of limitations in our net80211 layer,
     925             :                          * we don't support them in the 4.9GHz band.
     926             :                          */
     927           0 :                         if (chan <= 14)
     928             :                                 continue;
     929             : 
     930           0 :                         ic->ic_channels[chan].ic_freq =
     931           0 :                             ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
     932           0 :                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
     933             :                         /* We have at least one valid 5GHz channel. */
     934           0 :                         sc->sc_flags |= WPI_FLAG_HAS_5GHZ;
     935             :                 }
     936             : 
     937             :                 /* Is active scan allowed on this channel? */
     938           0 :                 if (!(channels[i].flags & WPI_EEPROM_CHAN_ACTIVE)) {
     939           0 :                         ic->ic_channels[chan].ic_flags |=
     940             :                             IEEE80211_CHAN_PASSIVE;
     941           0 :                 }
     942             : 
     943             :                 /* Save maximum allowed TX power for this channel. */
     944           0 :                 sc->maxpwr[chan] = channels[i].maxpwr;
     945             : 
     946             :                 DPRINTF(("adding chan %d flags=0x%x maxpwr=%d\n",
     947             :                     chan, channels[i].flags, sc->maxpwr[chan]));
     948           0 :         }
     949           0 : }
     950             : 
     951             : void
     952           0 : wpi_read_eeprom_group(struct wpi_softc *sc, int n)
     953             : {
     954           0 :         struct wpi_power_group *group = &sc->groups[n];
     955           0 :         struct wpi_eeprom_group rgroup;
     956             :         int i;
     957             : 
     958           0 :         wpi_read_prom_data(sc, WPI_EEPROM_POWER_GRP + n * 32, &rgroup,
     959             :             sizeof rgroup);
     960             : 
     961             :         /* Save TX power group information. */
     962           0 :         group->chan   = rgroup.chan;
     963           0 :         group->maxpwr = rgroup.maxpwr;
     964             :         /* Retrieve temperature at which the samples were taken. */
     965           0 :         group->temp   = (int16_t)letoh16(rgroup.temp);
     966             : 
     967             :         DPRINTF(("power group %d: chan=%d maxpwr=%d temp=%d\n", n,
     968             :             group->chan, group->maxpwr, group->temp));
     969             : 
     970           0 :         for (i = 0; i < WPI_SAMPLES_COUNT; i++) {
     971           0 :                 group->samples[i].index = rgroup.samples[i].index;
     972           0 :                 group->samples[i].power = rgroup.samples[i].power;
     973             : 
     974             :                 DPRINTF(("\tsample %d: index=%d power=%d\n", i,
     975             :                     group->samples[i].index, group->samples[i].power));
     976             :         }
     977           0 : }
     978             : 
     979             : struct ieee80211_node *
     980           0 : wpi_node_alloc(struct ieee80211com *ic)
     981             : {
     982           0 :         return malloc(sizeof (struct wpi_node), M_DEVBUF, M_NOWAIT | M_ZERO);
     983             : }
     984             : 
     985             : void
     986           0 : wpi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
     987             : {
     988           0 :         struct wpi_softc *sc = ic->ic_if.if_softc;
     989           0 :         struct wpi_node *wn = (void *)ni;
     990             :         uint8_t rate;
     991             :         int ridx, i;
     992             : 
     993           0 :         ieee80211_amrr_node_init(&sc->amrr, &wn->amn);
     994             :         /* Start at lowest available bit-rate, AMRR will raise. */
     995           0 :         ni->ni_txrate = 0;
     996             : 
     997           0 :         for (i = 0; i < ni->ni_rates.rs_nrates; i++) {
     998           0 :                 rate = ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL;
     999             :                 /* Map 802.11 rate to HW rate index. */
    1000           0 :                 for (ridx = 0; ridx <= WPI_RIDX_MAX; ridx++)
    1001           0 :                         if (wpi_rates[ridx].rate == rate)
    1002             :                                 break;
    1003           0 :                 wn->ridx[i] = ridx;
    1004             :         }
    1005           0 : }
    1006             : 
    1007             : int
    1008           0 : wpi_media_change(struct ifnet *ifp)
    1009             : {
    1010           0 :         struct wpi_softc *sc = ifp->if_softc;
    1011           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1012             :         uint8_t rate, ridx;
    1013             :         int error;
    1014             : 
    1015           0 :         error = ieee80211_media_change(ifp);
    1016           0 :         if (error != ENETRESET)
    1017           0 :                 return error;
    1018             : 
    1019           0 :         if (ic->ic_fixed_rate != -1) {
    1020           0 :                 rate = ic->ic_sup_rates[ic->ic_curmode].
    1021           0 :                     rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
    1022             :                 /* Map 802.11 rate to HW rate index. */
    1023           0 :                 for (ridx = 0; ridx <= WPI_RIDX_MAX; ridx++)
    1024           0 :                         if (wpi_rates[ridx].rate == rate)
    1025             :                                 break;
    1026           0 :                 sc->fixed_ridx = ridx;
    1027           0 :         }
    1028             : 
    1029           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1030             :             (IFF_UP | IFF_RUNNING)) {
    1031           0 :                 wpi_stop(ifp, 0);
    1032           0 :                 error = wpi_init(ifp);
    1033           0 :         }
    1034           0 :         return error;
    1035           0 : }
    1036             : 
    1037             : int
    1038           0 : wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
    1039             : {
    1040           0 :         struct ifnet *ifp = &ic->ic_if;
    1041           0 :         struct wpi_softc *sc = ifp->if_softc;
    1042             :         int error;
    1043             : 
    1044           0 :         timeout_del(&sc->calib_to);
    1045             : 
    1046           0 :         switch (nstate) {
    1047             :         case IEEE80211_S_SCAN:
    1048             :                 /* Make the link LED blink while we're scanning. */
    1049           0 :                 wpi_set_led(sc, WPI_LED_LINK, 20, 2);
    1050             : 
    1051           0 :                 if ((error = wpi_scan(sc, IEEE80211_CHAN_2GHZ)) != 0) {
    1052           0 :                         printf("%s: could not initiate scan\n",
    1053           0 :                             sc->sc_dev.dv_xname);
    1054           0 :                         return error;
    1055             :                 }
    1056           0 :                 if (ifp->if_flags & IFF_DEBUG)
    1057           0 :                         printf("%s: %s -> %s\n", ifp->if_xname,
    1058           0 :                             ieee80211_state_name[ic->ic_state],
    1059           0 :                             ieee80211_state_name[nstate]);
    1060           0 :                 ieee80211_set_link_state(ic, LINK_STATE_DOWN);
    1061           0 :                 ieee80211_free_allnodes(ic, 1);
    1062           0 :                 ic->ic_state = nstate;
    1063           0 :                 return 0;
    1064             : 
    1065             :         case IEEE80211_S_ASSOC:
    1066           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    1067             :                         break;
    1068             :                 /* FALLTHROUGH */
    1069             :         case IEEE80211_S_AUTH:
    1070             :                 /* Reset state to handle reassociations correctly. */
    1071           0 :                 sc->rxon.associd = 0;
    1072           0 :                 sc->rxon.filter &= ~htole32(WPI_FILTER_BSS);
    1073             : 
    1074           0 :                 if ((error = wpi_auth(sc)) != 0) {
    1075           0 :                         printf("%s: could not move to auth state\n",
    1076           0 :                             sc->sc_dev.dv_xname);
    1077           0 :                         return error;
    1078             :                 }
    1079             :                 break;
    1080             : 
    1081             :         case IEEE80211_S_RUN:
    1082           0 :                 if ((error = wpi_run(sc)) != 0) {
    1083           0 :                         printf("%s: could not move to run state\n",
    1084           0 :                             sc->sc_dev.dv_xname);
    1085           0 :                         return error;
    1086             :                 }
    1087             :                 break;
    1088             : 
    1089             :         case IEEE80211_S_INIT:
    1090             :                 break;
    1091             :         }
    1092             : 
    1093           0 :         return sc->sc_newstate(ic, nstate, arg);
    1094           0 : }
    1095             : 
    1096             : void
    1097           0 : wpi_iter_func(void *arg, struct ieee80211_node *ni)
    1098             : {
    1099           0 :         struct wpi_softc *sc = arg;
    1100           0 :         struct wpi_node *wn = (struct wpi_node *)ni;
    1101             : 
    1102           0 :         ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
    1103           0 : }
    1104             : 
    1105             : void
    1106           0 : wpi_calib_timeout(void *arg)
    1107             : {
    1108           0 :         struct wpi_softc *sc = arg;
    1109           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1110             :         int s;
    1111             : 
    1112           0 :         s = splnet();
    1113             :         /* Automatic rate control triggered every 500ms. */
    1114           0 :         if (ic->ic_fixed_rate == -1) {
    1115           0 :                 if (ic->ic_opmode == IEEE80211_M_STA)
    1116           0 :                         wpi_iter_func(sc, ic->ic_bss);
    1117             :                 else
    1118           0 :                         ieee80211_iterate_nodes(ic, wpi_iter_func, sc);
    1119             :         }
    1120             : 
    1121             :         /* Force automatic TX power calibration every 60 secs. */
    1122           0 :         if (++sc->calib_cnt >= 120) {
    1123           0 :                 wpi_power_calibration(sc);
    1124           0 :                 sc->calib_cnt = 0;
    1125           0 :         }
    1126           0 :         splx(s);
    1127             : 
    1128             :         /* Automatic rate control triggered every 500ms. */
    1129           0 :         timeout_add_msec(&sc->calib_to, 500);
    1130           0 : }
    1131             : 
    1132             : int
    1133           0 : wpi_ccmp_decap(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_key *k)
    1134             : {
    1135             :         struct ieee80211_frame *wh;
    1136             :         uint64_t pn, *prsc;
    1137             :         uint8_t *ivp;
    1138             :         uint8_t tid;
    1139             :         int hdrlen;
    1140             : 
    1141           0 :         wh = mtod(m, struct ieee80211_frame *);
    1142           0 :         hdrlen = ieee80211_get_hdrlen(wh);
    1143           0 :         ivp = (uint8_t *)wh + hdrlen;
    1144             : 
    1145             :         /* Check that ExtIV bit is be set. */
    1146           0 :         if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
    1147             :                 DPRINTF(("CCMP decap ExtIV not set\n"));
    1148           0 :                 return 1;
    1149             :         }
    1150           0 :         tid = ieee80211_has_qos(wh) ?
    1151           0 :             ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
    1152           0 :         prsc = &k->k_rsc[tid];
    1153             : 
    1154             :         /* Extract the 48-bit PN from the CCMP header. */
    1155           0 :         pn = (uint64_t)ivp[0]       |
    1156           0 :              (uint64_t)ivp[1] <<  8 |
    1157           0 :              (uint64_t)ivp[4] << 16 |
    1158           0 :              (uint64_t)ivp[5] << 24 |
    1159           0 :              (uint64_t)ivp[6] << 32 |
    1160           0 :              (uint64_t)ivp[7] << 40;
    1161           0 :         if (pn <= *prsc) {
    1162             :                 /*
    1163             :                  * Not necessarily a replayed frame since we did not check
    1164             :                  * the sequence number of the 802.11 header yet.
    1165             :                  */
    1166             :                 DPRINTF(("CCMP replayed\n"));
    1167           0 :                 return 1;
    1168             :         }
    1169             :         /* Update last seen packet number. */
    1170           0 :         *prsc = pn;
    1171             : 
    1172             :         /* Clear Protected bit and strip IV. */
    1173           0 :         wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
    1174           0 :         memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh, hdrlen);
    1175           0 :         m_adj(m, IEEE80211_CCMP_HDRLEN);
    1176             :         /* Strip MIC. */
    1177           0 :         m_adj(m, -IEEE80211_CCMP_MICLEN);
    1178           0 :         return 0;
    1179           0 : }
    1180             : 
    1181             : void
    1182           0 : wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc,
    1183             :     struct wpi_rx_data *data)
    1184             : {
    1185           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1186           0 :         struct ifnet *ifp = &ic->ic_if;
    1187           0 :         struct wpi_rx_ring *ring = &sc->rxq;
    1188             :         struct wpi_rx_stat *stat;
    1189             :         struct wpi_rx_head *head;
    1190             :         struct wpi_rx_tail *tail;
    1191             :         struct ieee80211_frame *wh;
    1192           0 :         struct ieee80211_rxinfo rxi;
    1193             :         struct ieee80211_node *ni;
    1194             :         struct mbuf *m, *m1;
    1195             :         uint32_t flags;
    1196             :         int error;
    1197             : 
    1198           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, WPI_RBUF_SIZE,
    1199             :             BUS_DMASYNC_POSTREAD);
    1200           0 :         stat = (struct wpi_rx_stat *)(desc + 1);
    1201             : 
    1202           0 :         if (stat->len > WPI_STAT_MAXLEN) {
    1203           0 :                 printf("%s: invalid RX statistic header\n",
    1204           0 :                     sc->sc_dev.dv_xname);
    1205           0 :                 ifp->if_ierrors++;
    1206           0 :                 return;
    1207             :         }
    1208           0 :         head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len);
    1209           0 :         tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + letoh16(head->len));
    1210           0 :         flags = letoh32(tail->flags);
    1211             : 
    1212             :         /* Discard frames with a bad FCS early. */
    1213           0 :         if ((flags & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
    1214             :                 DPRINTFN(2, ("rx tail flags error %x\n", flags));
    1215           0 :                 ifp->if_ierrors++;
    1216           0 :                 return;
    1217             :         }
    1218             :         /* Discard frames that are too short. */
    1219           0 :         if (letoh16(head->len) < sizeof (*wh)) {
    1220             :                 DPRINTF(("frame too short: %d\n", letoh16(head->len)));
    1221           0 :                 ic->ic_stats.is_rx_tooshort++;
    1222           0 :                 ifp->if_ierrors++;
    1223           0 :                 return;
    1224             :         }
    1225             : 
    1226           0 :         m1 = MCLGETI(NULL, M_DONTWAIT, NULL, WPI_RBUF_SIZE);
    1227           0 :         if (m1 == NULL) {
    1228           0 :                 ic->ic_stats.is_rx_nombuf++;
    1229           0 :                 ifp->if_ierrors++;
    1230           0 :                 return;
    1231             :         }
    1232           0 :         bus_dmamap_unload(sc->sc_dmat, data->map);
    1233             : 
    1234           0 :         error = bus_dmamap_load(sc->sc_dmat, data->map, mtod(m1, void *),
    1235             :             WPI_RBUF_SIZE, NULL, BUS_DMA_NOWAIT | BUS_DMA_READ);
    1236           0 :         if (error != 0) {
    1237           0 :                 m_freem(m1);
    1238             : 
    1239             :                 /* Try to reload the old mbuf. */
    1240           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
    1241             :                     mtod(data->m, void *), WPI_RBUF_SIZE, NULL,
    1242             :                     BUS_DMA_NOWAIT | BUS_DMA_READ);
    1243           0 :                 if (error != 0) {
    1244           0 :                         panic("%s: could not load old RX mbuf",
    1245           0 :                             sc->sc_dev.dv_xname);
    1246             :                 }
    1247             :                 /* Physical address may have changed. */
    1248           0 :                 ring->desc[ring->cur] = htole32(data->map->dm_segs[0].ds_addr);
    1249           0 :                 bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
    1250             :                     ring->cur * sizeof (uint32_t), sizeof (uint32_t),
    1251             :                     BUS_DMASYNC_PREWRITE);
    1252           0 :                 ifp->if_ierrors++;
    1253           0 :                 return;
    1254             :         }
    1255             : 
    1256           0 :         m = data->m;
    1257           0 :         data->m = m1;
    1258             :         /* Update RX descriptor. */
    1259           0 :         ring->desc[ring->cur] = htole32(data->map->dm_segs[0].ds_addr);
    1260           0 :         bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
    1261             :             ring->cur * sizeof (uint32_t), sizeof (uint32_t),
    1262             :             BUS_DMASYNC_PREWRITE);
    1263             : 
    1264             :         /* Finalize mbuf. */
    1265           0 :         m->m_data = (caddr_t)(head + 1);
    1266           0 :         m->m_pkthdr.len = m->m_len = letoh16(head->len);
    1267             : 
    1268             :         /* Grab a reference to the source node. */
    1269           0 :         wh = mtod(m, struct ieee80211_frame *);
    1270           0 :         ni = ieee80211_find_rxnode(ic, wh);
    1271             : 
    1272           0 :         rxi.rxi_flags = 0;
    1273           0 :         if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
    1274           0 :             !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
    1275           0 :             (ni->ni_flags & IEEE80211_NODE_RXPROT) &&
    1276           0 :             ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
    1277           0 :                 if ((flags & WPI_RX_CIPHER_MASK) != WPI_RX_CIPHER_CCMP) {
    1278           0 :                         ic->ic_stats.is_ccmp_dec_errs++;
    1279           0 :                         ifp->if_ierrors++;
    1280           0 :                         m_freem(m);
    1281           0 :                         return;
    1282             :                 }
    1283             :                 /* Check whether decryption was successful or not. */
    1284           0 :                 if ((flags & WPI_RX_DECRYPT_MASK) != WPI_RX_DECRYPT_OK) {
    1285             :                         DPRINTF(("CCMP decryption failed 0x%x\n", flags));
    1286           0 :                         ic->ic_stats.is_ccmp_dec_errs++;
    1287           0 :                         ifp->if_ierrors++;
    1288           0 :                         m_freem(m);
    1289           0 :                         return;
    1290             :                 }
    1291           0 :                 if (wpi_ccmp_decap(sc, m, &ni->ni_pairwise_key) != 0) {
    1292           0 :                         ifp->if_ierrors++;
    1293           0 :                         m_freem(m);
    1294           0 :                         return;
    1295             :                 }
    1296           0 :                 rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
    1297           0 :         }
    1298             : 
    1299             : #if NBPFILTER > 0
    1300           0 :         if (sc->sc_drvbpf != NULL) {
    1301           0 :                 struct mbuf mb;
    1302           0 :                 struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
    1303             : 
    1304           0 :                 tap->wr_flags = 0;
    1305           0 :                 if (letoh16(head->flags) & 0x4)
    1306           0 :                         tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
    1307           0 :                 tap->wr_chan_freq =
    1308           0 :                     htole16(ic->ic_channels[head->chan].ic_freq);
    1309           0 :                 tap->wr_chan_flags =
    1310           0 :                     htole16(ic->ic_channels[head->chan].ic_flags);
    1311           0 :                 tap->wr_dbm_antsignal = (int8_t)(stat->rssi - WPI_RSSI_OFFSET);
    1312           0 :                 tap->wr_dbm_antnoise = (int8_t)letoh16(stat->noise);
    1313           0 :                 tap->wr_tsft = tail->tstamp;
    1314           0 :                 tap->wr_antenna = (letoh16(head->flags) >> 4) & 0xf;
    1315           0 :                 switch (head->rate) {
    1316             :                 /* CCK rates. */
    1317           0 :                 case  10: tap->wr_rate =   2; break;
    1318           0 :                 case  20: tap->wr_rate =   4; break;
    1319           0 :                 case  55: tap->wr_rate =  11; break;
    1320           0 :                 case 110: tap->wr_rate =  22; break;
    1321             :                 /* OFDM rates. */
    1322           0 :                 case 0xd: tap->wr_rate =  12; break;
    1323           0 :                 case 0xf: tap->wr_rate =  18; break;
    1324           0 :                 case 0x5: tap->wr_rate =  24; break;
    1325           0 :                 case 0x7: tap->wr_rate =  36; break;
    1326           0 :                 case 0x9: tap->wr_rate =  48; break;
    1327           0 :                 case 0xb: tap->wr_rate =  72; break;
    1328           0 :                 case 0x1: tap->wr_rate =  96; break;
    1329           0 :                 case 0x3: tap->wr_rate = 108; break;
    1330             :                 /* Unknown rate: should not happen. */
    1331           0 :                 default:  tap->wr_rate =   0;
    1332           0 :                 }
    1333             : 
    1334           0 :                 mb.m_data = (caddr_t)tap;
    1335           0 :                 mb.m_len = sc->sc_rxtap_len;
    1336           0 :                 mb.m_next = m;
    1337           0 :                 mb.m_nextpkt = NULL;
    1338           0 :                 mb.m_type = 0;
    1339           0 :                 mb.m_flags = 0;
    1340           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1341           0 :         }
    1342             : #endif
    1343             : 
    1344             :         /* Send the frame to the 802.11 layer. */
    1345           0 :         rxi.rxi_rssi = stat->rssi;
    1346           0 :         rxi.rxi_tstamp = 0;     /* unused */
    1347           0 :         ieee80211_input(ifp, m, ni, &rxi);
    1348             : 
    1349             :         /* Node is no longer needed. */
    1350           0 :         ieee80211_release_node(ic, ni);
    1351           0 : }
    1352             : 
    1353             : void
    1354           0 : wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
    1355             : {
    1356           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1357           0 :         struct ifnet *ifp = &ic->ic_if;
    1358           0 :         struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3];
    1359           0 :         struct wpi_tx_data *data = &ring->data[desc->idx];
    1360           0 :         struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
    1361           0 :         struct wpi_node *wn = (struct wpi_node *)data->ni;
    1362             : 
    1363             :         /* Update rate control statistics. */
    1364           0 :         wn->amn.amn_txcnt++;
    1365           0 :         if (stat->retrycnt > 0)
    1366           0 :                 wn->amn.amn_retrycnt++;
    1367             : 
    1368           0 :         if ((letoh32(stat->status) & 0xff) != 1)
    1369           0 :                 ifp->if_oerrors++;
    1370             : 
    1371             :         /* Unmap and free mbuf. */
    1372           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
    1373             :             BUS_DMASYNC_POSTWRITE);
    1374           0 :         bus_dmamap_unload(sc->sc_dmat, data->map);
    1375           0 :         m_freem(data->m);
    1376           0 :         data->m = NULL;
    1377           0 :         ieee80211_release_node(ic, data->ni);
    1378           0 :         data->ni = NULL;
    1379             : 
    1380           0 :         sc->sc_tx_timer = 0;
    1381           0 :         if (--ring->queued < WPI_TX_RING_LOMARK) {
    1382           0 :                 sc->qfullmsk &= ~(1 << ring->qid);
    1383           0 :                 if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {
    1384           0 :                         ifq_clr_oactive(&ifp->if_snd);
    1385           0 :                         (*ifp->if_start)(ifp);
    1386           0 :                 }
    1387             :         }
    1388           0 : }
    1389             : 
    1390             : void
    1391           0 : wpi_cmd_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
    1392             : {
    1393           0 :         struct wpi_tx_ring *ring = &sc->txq[4];
    1394             :         struct wpi_tx_data *data;
    1395             : 
    1396           0 :         if ((desc->qid & 7) != 4)
    1397           0 :                 return; /* Not a command ack. */
    1398             : 
    1399           0 :         data = &ring->data[desc->idx];
    1400             : 
    1401             :         /* If the command was mapped in an mbuf, free it. */
    1402           0 :         if (data->m != NULL) {
    1403           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
    1404             :                     data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
    1405           0 :                 bus_dmamap_unload(sc->sc_dmat, data->map);
    1406           0 :                 m_freem(data->m);
    1407           0 :                 data->m = NULL;
    1408           0 :         }
    1409           0 :         wakeup(&ring->cmd[desc->idx]);
    1410           0 : }
    1411             : 
    1412             : void
    1413           0 : wpi_notif_intr(struct wpi_softc *sc)
    1414             : {
    1415           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1416           0 :         struct ifnet *ifp = &ic->ic_if;
    1417             :         uint32_t hw;
    1418             : 
    1419           0 :         bus_dmamap_sync(sc->sc_dmat, sc->shared_dma.map, 0,
    1420             :             sizeof (struct wpi_shared), BUS_DMASYNC_POSTREAD);
    1421             : 
    1422           0 :         hw = letoh32(sc->shared->next);
    1423           0 :         while (sc->rxq.cur != hw) {
    1424           0 :                 struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
    1425             :                 struct wpi_rx_desc *desc;
    1426             : 
    1427           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0, sizeof (*desc),
    1428             :                     BUS_DMASYNC_POSTREAD);
    1429           0 :                 desc = mtod(data->m, struct wpi_rx_desc *);
    1430             : 
    1431             :                 DPRINTFN(4, ("rx notification qid=%x idx=%d flags=%x type=%d "
    1432             :                     "len=%d\n", desc->qid, desc->idx, desc->flags, desc->type,
    1433             :                     letoh32(desc->len)));
    1434             : 
    1435           0 :                 if (!(desc->qid & 0x80)) /* Reply to a command. */
    1436           0 :                         wpi_cmd_done(sc, desc);
    1437             : 
    1438           0 :                 switch (desc->type) {
    1439             :                 case WPI_RX_DONE:
    1440             :                         /* An 802.11 frame has been received. */
    1441           0 :                         wpi_rx_done(sc, desc, data);
    1442           0 :                         break;
    1443             : 
    1444             :                 case WPI_TX_DONE:
    1445             :                         /* An 802.11 frame has been transmitted. */
    1446           0 :                         wpi_tx_done(sc, desc);
    1447           0 :                         break;
    1448             : 
    1449             :                 case WPI_UC_READY:
    1450             :                 {
    1451             :                         struct wpi_ucode_info *uc =
    1452           0 :                             (struct wpi_ucode_info *)(desc + 1);
    1453             : 
    1454             :                         /* The microcontroller is ready. */
    1455           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),
    1456             :                             sizeof (*uc), BUS_DMASYNC_POSTREAD);
    1457             :                         DPRINTF(("microcode alive notification version %x "
    1458             :                             "alive %x\n", letoh32(uc->version),
    1459             :                             letoh32(uc->valid)));
    1460             : 
    1461           0 :                         if (letoh32(uc->valid) != 1) {
    1462           0 :                                 printf("%s: microcontroller initialization "
    1463           0 :                                     "failed\n", sc->sc_dev.dv_xname);
    1464           0 :                         }
    1465           0 :                         if (uc->subtype != WPI_UCODE_INIT) {
    1466             :                                 /* Save the address of the error log. */
    1467           0 :                                 sc->errptr = letoh32(uc->errptr);
    1468           0 :                         }
    1469             :                         break;
    1470             :                 }
    1471             :                 case WPI_STATE_CHANGED:
    1472             :                 {
    1473           0 :                         uint32_t *status = (uint32_t *)(desc + 1);
    1474             : 
    1475             :                         /* Enabled/disabled notification. */
    1476           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),
    1477             :                             sizeof (*status), BUS_DMASYNC_POSTREAD);
    1478             :                         DPRINTF(("state changed to %x\n", letoh32(*status)));
    1479             : 
    1480           0 :                         if (letoh32(*status) & 1) {
    1481             :                                 /* The radio button has to be pushed. */
    1482           0 :                                 printf("%s: Radio transmitter is off\n",
    1483           0 :                                     sc->sc_dev.dv_xname);
    1484             :                                 /* Turn the interface down. */
    1485           0 :                                 wpi_stop(ifp, 1);
    1486           0 :                                 return; /* No further processing. */
    1487             :                         }
    1488           0 :                         break;
    1489             :                 }
    1490             :                 case WPI_START_SCAN:
    1491             :                 {
    1492             :                         struct wpi_start_scan *scan =
    1493           0 :                             (struct wpi_start_scan *)(desc + 1);
    1494             : 
    1495           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),
    1496             :                             sizeof (*scan), BUS_DMASYNC_POSTREAD);
    1497             :                         DPRINTFN(2, ("scanning channel %d status %x\n",
    1498             :                             scan->chan, letoh32(scan->status)));
    1499             : 
    1500             :                         /* Fix current channel. */
    1501           0 :                         ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
    1502             :                         break;
    1503             :                 }
    1504             :                 case WPI_STOP_SCAN:
    1505             :                 {
    1506             :                         struct wpi_stop_scan *scan =
    1507           0 :                             (struct wpi_stop_scan *)(desc + 1);
    1508             : 
    1509           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),
    1510             :                             sizeof (*scan), BUS_DMASYNC_POSTREAD);
    1511             :                         DPRINTF(("scan finished nchan=%d status=%d chan=%d\n",
    1512             :                             scan->nchan, scan->status, scan->chan));
    1513             : 
    1514           0 :                         if (scan->status == 1 && scan->chan <= 14 &&
    1515           0 :                             (sc->sc_flags & WPI_FLAG_HAS_5GHZ)) {
    1516             :                                 /*
    1517             :                                  * We just finished scanning 2GHz channels,
    1518             :                                  * start scanning 5GHz ones.
    1519             :                                  */
    1520           0 :                                 if (wpi_scan(sc, IEEE80211_CHAN_5GHZ) == 0)
    1521           0 :                                         break;
    1522             :                         }
    1523           0 :                         ieee80211_end_scan(ifp);
    1524           0 :                         break;
    1525             :                 }
    1526             :                 }
    1527             : 
    1528           0 :                 sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
    1529           0 :         }
    1530             : 
    1531             :         /* Tell the firmware what we have processed. */
    1532           0 :         hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
    1533           0 :         WPI_WRITE(sc, WPI_FH_RX_WPTR, hw & ~7);
    1534           0 : }
    1535             : 
    1536             : #ifdef WPI_DEBUG
    1537             : /*
    1538             :  * Dump the error log of the firmware when a firmware panic occurs.  Although
    1539             :  * we can't debug the firmware because it is neither open source nor free, it
    1540             :  * can help us to identify certain classes of problems.
    1541             :  */
    1542             : void
    1543             : wpi_fatal_intr(struct wpi_softc *sc)
    1544             : {
    1545             : #define N(a)    (sizeof (a) / sizeof ((a)[0]))
    1546             :         struct wpi_fwdump dump;
    1547             :         uint32_t i, offset, count;
    1548             : 
    1549             :         /* Check that the error log address is valid. */
    1550             :         if (sc->errptr < WPI_FW_DATA_BASE ||
    1551             :             sc->errptr + sizeof (dump) >
    1552             :             WPI_FW_DATA_BASE + WPI_FW_DATA_MAXSZ) {
    1553             :                 printf("%s: bad firmware error log address 0x%08x\n",
    1554             :                     sc->sc_dev.dv_xname, sc->errptr);
    1555             :                 return;
    1556             :         }
    1557             : 
    1558             :         if (wpi_nic_lock(sc) != 0) {
    1559             :                 printf("%s: could not read firmware error log\n",
    1560             :                     sc->sc_dev.dv_xname);
    1561             :                 return;
    1562             :         }
    1563             :         /* Read number of entries in the log. */
    1564             :         count = wpi_mem_read(sc, sc->errptr);
    1565             :         if (count == 0 || count * sizeof (dump) > WPI_FW_DATA_MAXSZ) {
    1566             :                 printf("%s: invalid count field (count=%u)\n",
    1567             :                     sc->sc_dev.dv_xname, count);
    1568             :                 wpi_nic_unlock(sc);
    1569             :                 return;
    1570             :         }
    1571             :         /* Skip "count" field. */
    1572             :         offset = sc->errptr + sizeof (uint32_t);
    1573             :         printf("firmware error log (count=%u):\n", count);
    1574             :         for (i = 0; i < count; i++) {
    1575             :                 wpi_mem_read_region_4(sc, offset, (uint32_t *)&dump,
    1576             :                     sizeof (dump) / sizeof (uint32_t));
    1577             : 
    1578             :                 printf("  error type = \"%s\" (0x%08X)\n",
    1579             :                     (dump.desc < N(wpi_fw_errmsg)) ?
    1580             :                         wpi_fw_errmsg[dump.desc] : "UNKNOWN",
    1581             :                     dump.desc);
    1582             :                 printf("  error data      = 0x%08X\n",
    1583             :                     dump.data);
    1584             :                 printf("  branch link     = 0x%08X%08X\n",
    1585             :                     dump.blink[0], dump.blink[1]);
    1586             :                 printf("  interrupt link  = 0x%08X%08X\n",
    1587             :                     dump.ilink[0], dump.ilink[1]);
    1588             :                 printf("  time            = %u\n", dump.time);
    1589             : 
    1590             :                 offset += sizeof (dump);
    1591             :         }
    1592             :         wpi_nic_unlock(sc);
    1593             :         /* Dump driver status (TX and RX rings) while we're here. */
    1594             :         printf("driver status:\n");
    1595             :         for (i = 0; i < 6; i++) {
    1596             :                 struct wpi_tx_ring *ring = &sc->txq[i];
    1597             :                 printf("  tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n",
    1598             :                     i, ring->qid, ring->cur, ring->queued);
    1599             :         }
    1600             :         printf("  rx ring: cur=%d\n", sc->rxq.cur);
    1601             :         printf("  802.11 state %d\n", sc->sc_ic.ic_state);
    1602             : #undef N
    1603             : }
    1604             : #endif
    1605             : 
    1606             : int
    1607           0 : wpi_intr(void *arg)
    1608             : {
    1609           0 :         struct wpi_softc *sc = arg;
    1610           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    1611             :         uint32_t r1, r2;
    1612             : 
    1613             :         /* Disable interrupts. */
    1614           0 :         WPI_WRITE(sc, WPI_MASK, 0);
    1615             : 
    1616           0 :         r1 = WPI_READ(sc, WPI_INT);
    1617           0 :         r2 = WPI_READ(sc, WPI_FH_INT);
    1618             : 
    1619           0 :         if (r1 == 0 && r2 == 0) {
    1620           0 :                 if (ifp->if_flags & IFF_UP)
    1621           0 :                         WPI_WRITE(sc, WPI_MASK, WPI_INT_MASK);
    1622           0 :                 return 0;       /* Interrupt not for us. */
    1623             :         }
    1624           0 :         if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
    1625           0 :                 return 0;       /* Hardware gone! */
    1626             : 
    1627             :         /* Acknowledge interrupts. */
    1628           0 :         WPI_WRITE(sc, WPI_INT, r1);
    1629           0 :         WPI_WRITE(sc, WPI_FH_INT, r2);
    1630             : 
    1631           0 :         if (r1 & (WPI_INT_SW_ERR | WPI_INT_HW_ERR)) {
    1632           0 :                 printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
    1633             :                 /* Dump firmware error log and stop. */
    1634             : #ifdef WPI_DEBUG
    1635             :                 wpi_fatal_intr(sc);
    1636             : #endif
    1637           0 :                 wpi_stop(ifp, 1);
    1638           0 :                 task_add(systq, &sc->init_task);
    1639           0 :                 return 1;
    1640             :         }
    1641           0 :         if ((r1 & (WPI_INT_FH_RX | WPI_INT_SW_RX)) ||
    1642           0 :             (r2 & WPI_FH_INT_RX))
    1643           0 :                 wpi_notif_intr(sc);
    1644             : 
    1645           0 :         if (r1 & WPI_INT_ALIVE)
    1646           0 :                 wakeup(sc);     /* Firmware is alive. */
    1647             : 
    1648             :         /* Re-enable interrupts. */
    1649           0 :         if (ifp->if_flags & IFF_UP)
    1650           0 :                 WPI_WRITE(sc, WPI_MASK, WPI_INT_MASK);
    1651             : 
    1652           0 :         return 1;
    1653           0 : }
    1654             : 
    1655             : int
    1656           0 : wpi_tx(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
    1657             : {
    1658           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1659           0 :         struct wpi_node *wn = (void *)ni;
    1660             :         struct wpi_tx_ring *ring;
    1661             :         struct wpi_tx_desc *desc;
    1662             :         struct wpi_tx_data *data;
    1663             :         struct wpi_tx_cmd *cmd;
    1664             :         struct wpi_cmd_data *tx;
    1665             :         const struct wpi_rate *rinfo;
    1666             :         struct ieee80211_frame *wh;
    1667             :         struct ieee80211_key *k = NULL;
    1668             :         enum ieee80211_edca_ac ac;
    1669             :         uint32_t flags;
    1670             :         uint16_t qos;
    1671             :         u_int hdrlen;
    1672             :         uint8_t *ivp, tid, ridx, type;
    1673             :         int i, totlen, hasqos, error;
    1674             : 
    1675           0 :         wh = mtod(m, struct ieee80211_frame *);
    1676           0 :         hdrlen = ieee80211_get_hdrlen(wh);
    1677           0 :         type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
    1678             : 
    1679             :         /* Select EDCA Access Category and TX ring for this frame. */
    1680           0 :         if ((hasqos = ieee80211_has_qos(wh))) {
    1681           0 :                 qos = ieee80211_get_qos(wh);
    1682           0 :                 tid = qos & IEEE80211_QOS_TID;
    1683           0 :                 ac = ieee80211_up_to_ac(ic, tid);
    1684           0 :         } else {
    1685             :                 tid = 0;
    1686             :                 ac = EDCA_AC_BE;
    1687             :         }
    1688             : 
    1689           0 :         ring = &sc->txq[ac];
    1690           0 :         desc = &ring->desc[ring->cur];
    1691           0 :         data = &ring->data[ring->cur];
    1692             : 
    1693             :         /* Choose a TX rate index. */
    1694           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    1695           0 :             type != IEEE80211_FC0_TYPE_DATA) {
    1696           0 :                 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
    1697             :                     WPI_RIDX_OFDM6 : WPI_RIDX_CCK1;
    1698           0 :         } else if (ic->ic_fixed_rate != -1) {
    1699           0 :                 ridx = sc->fixed_ridx;
    1700           0 :         } else
    1701           0 :                 ridx = wn->ridx[ni->ni_txrate];
    1702           0 :         rinfo = &wpi_rates[ridx];
    1703             : 
    1704             : #if NBPFILTER > 0
    1705           0 :         if (sc->sc_drvbpf != NULL) {
    1706           0 :                 struct mbuf mb;
    1707           0 :                 struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
    1708             : 
    1709           0 :                 tap->wt_flags = 0;
    1710           0 :                 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
    1711           0 :                 tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
    1712           0 :                 tap->wt_rate = rinfo->rate;
    1713           0 :                 tap->wt_hwqueue = ac;
    1714           0 :                 if ((ic->ic_flags & IEEE80211_F_WEPON) &&
    1715           0 :                     (wh->i_fc[1] & IEEE80211_FC1_PROTECTED))
    1716           0 :                         tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
    1717             : 
    1718           0 :                 mb.m_data = (caddr_t)tap;
    1719           0 :                 mb.m_len = sc->sc_txtap_len;
    1720           0 :                 mb.m_next = m;
    1721           0 :                 mb.m_nextpkt = NULL;
    1722           0 :                 mb.m_type = 0;
    1723           0 :                 mb.m_flags = 0;
    1724           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1725           0 :         }
    1726             : #endif
    1727             : 
    1728           0 :         totlen = m->m_pkthdr.len;
    1729             : 
    1730             :         /* Encrypt the frame if need be. */
    1731           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    1732             :                 /* Retrieve key for TX. */
    1733           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    1734           0 :                 if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
    1735             :                         /* Do software encryption. */
    1736           0 :                         if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
    1737           0 :                                 return ENOBUFS;
    1738             :                         /* 802.11 header may have moved. */
    1739           0 :                         wh = mtod(m, struct ieee80211_frame *);
    1740           0 :                         totlen = m->m_pkthdr.len;
    1741             : 
    1742           0 :                 } else  /* HW appends CCMP MIC. */
    1743           0 :                         totlen += IEEE80211_CCMP_HDRLEN;
    1744             :         }
    1745             : 
    1746             :         /* Prepare TX firmware command. */
    1747           0 :         cmd = &ring->cmd[ring->cur];
    1748           0 :         cmd->code = WPI_CMD_TX_DATA;
    1749           0 :         cmd->flags = 0;
    1750           0 :         cmd->qid = ring->qid;
    1751           0 :         cmd->idx = ring->cur;
    1752             : 
    1753           0 :         tx = (struct wpi_cmd_data *)cmd->data;
    1754             :         /* NB: No need to clear tx, all fields are reinitialized here. */
    1755             : 
    1756             :         flags = 0;
    1757           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1758             :                 /* Unicast frame, check if an ACK is expected. */
    1759           0 :                 if (!hasqos || (qos & IEEE80211_QOS_ACK_POLICY_MASK) !=
    1760             :                     IEEE80211_QOS_ACK_POLICY_NOACK)
    1761           0 :                         flags |= WPI_TX_NEED_ACK;
    1762             :         }
    1763             : 
    1764             :         /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
    1765           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1766             :                 /* NB: Group frames are sent using CCK in 802.11b/g. */
    1767           0 :                 if (totlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
    1768           0 :                         flags |= WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP;
    1769           0 :                 } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
    1770           0 :                     ridx <= WPI_RIDX_OFDM54) {
    1771           0 :                         if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
    1772           0 :                                 flags |= WPI_TX_NEED_CTS | WPI_TX_FULL_TXOP;
    1773           0 :                         else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
    1774           0 :                                 flags |= WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP;
    1775             :                 }
    1776             :         }
    1777             : 
    1778           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    1779           0 :             type != IEEE80211_FC0_TYPE_DATA)
    1780           0 :                 tx->id = WPI_ID_BROADCAST;
    1781             :         else
    1782           0 :                 tx->id = wn->id;
    1783             : 
    1784           0 :         if (type == IEEE80211_FC0_TYPE_MGT) {
    1785           0 :                 uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
    1786             : 
    1787             : #ifndef IEEE80211_STA_ONLY
    1788             :                 /* Tell HW to set timestamp in probe responses. */
    1789           0 :                 if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
    1790           0 :                         flags |= WPI_TX_INSERT_TSTAMP;
    1791             : #endif
    1792           0 :                 if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
    1793           0 :                     subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
    1794           0 :                         tx->timeout = htole16(3);
    1795             :                 else
    1796           0 :                         tx->timeout = htole16(2);
    1797           0 :         } else
    1798           0 :                 tx->timeout = htole16(0);
    1799             : 
    1800           0 :         tx->len = htole16(totlen);
    1801           0 :         tx->tid = tid;
    1802           0 :         tx->rts_ntries = 7;
    1803           0 :         tx->data_ntries = 15;
    1804           0 :         tx->ofdm_mask = 0xff;
    1805           0 :         tx->cck_mask = 0x0f;
    1806           0 :         tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
    1807           0 :         tx->plcp = rinfo->plcp;
    1808             : 
    1809             :         /* Copy 802.11 header in TX command. */
    1810           0 :         memcpy((uint8_t *)(tx + 1), wh, hdrlen);
    1811             : 
    1812           0 :         if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {
    1813             :                 /* Trim 802.11 header and prepend CCMP IV. */
    1814           0 :                 m_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN);
    1815           0 :                 ivp = mtod(m, uint8_t *);
    1816           0 :                 k->k_tsc++;
    1817           0 :                 ivp[0] = k->k_tsc;
    1818           0 :                 ivp[1] = k->k_tsc >> 8;
    1819           0 :                 ivp[2] = 0;
    1820           0 :                 ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;
    1821           0 :                 ivp[4] = k->k_tsc >> 16;
    1822           0 :                 ivp[5] = k->k_tsc >> 24;
    1823           0 :                 ivp[6] = k->k_tsc >> 32;
    1824           0 :                 ivp[7] = k->k_tsc >> 40;
    1825             : 
    1826           0 :                 tx->security = WPI_CIPHER_CCMP;
    1827           0 :                 memcpy(tx->key, k->k_key, k->k_len);
    1828           0 :         } else {
    1829             :                 /* Trim 802.11 header. */
    1830           0 :                 m_adj(m, hdrlen);
    1831           0 :                 tx->security = 0;
    1832             :         }
    1833           0 :         tx->flags = htole32(flags);
    1834             : 
    1835           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
    1836             :             BUS_DMA_NOWAIT | BUS_DMA_WRITE);
    1837           0 :         if (error != 0 && error != EFBIG) {
    1838           0 :                 printf("%s: can't map mbuf (error %d)\n",
    1839           0 :                     sc->sc_dev.dv_xname, error);
    1840           0 :                 m_freem(m);
    1841           0 :                 return error;
    1842             :         }
    1843           0 :         if (error != 0) {
    1844             :                 /* Too many DMA segments, linearize mbuf. */
    1845           0 :                 if (m_defrag(m, M_DONTWAIT)) {
    1846           0 :                         m_freem(m);
    1847           0 :                         return ENOBUFS;
    1848             :                 }
    1849           0 :                 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
    1850             :                     BUS_DMA_NOWAIT | BUS_DMA_WRITE);
    1851           0 :                 if (error != 0) {
    1852           0 :                         printf("%s: can't map mbuf (error %d)\n",
    1853           0 :                             sc->sc_dev.dv_xname, error);
    1854           0 :                         m_freem(m);
    1855           0 :                         return error;
    1856             :                 }
    1857             :         }
    1858             : 
    1859           0 :         data->m = m;
    1860           0 :         data->ni = ni;
    1861             : 
    1862             :         DPRINTFN(4, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
    1863             :             ring->qid, ring->cur, m->m_pkthdr.len, data->map->dm_nsegs));
    1864             : 
    1865             :         /* Fill TX descriptor. */
    1866           0 :         desc->flags = htole32(WPI_PAD32(m->m_pkthdr.len) << 28 |
    1867             :             (1 + data->map->dm_nsegs) << 24);
    1868             :         /* First DMA segment is used by the TX command. */
    1869           0 :         desc->segs[0].addr = htole32(ring->cmd_dma.paddr +
    1870             :             ring->cur * sizeof (struct wpi_tx_cmd));
    1871           0 :         desc->segs[0].len  = htole32(4 + sizeof (struct wpi_cmd_data) +
    1872             :             ((hdrlen + 3) & ~3));
    1873             :         /* Other DMA segments are for data payload. */
    1874           0 :         for (i = 1; i <= data->map->dm_nsegs; i++) {
    1875           0 :                 desc->segs[i].addr =
    1876           0 :                     htole32(data->map->dm_segs[i - 1].ds_addr);
    1877           0 :                 desc->segs[i].len  =
    1878           0 :                     htole32(data->map->dm_segs[i - 1].ds_len);
    1879             :         }
    1880             : 
    1881           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
    1882             :             BUS_DMASYNC_PREWRITE);
    1883           0 :         bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
    1884             :             (caddr_t)cmd - ring->cmd_dma.vaddr, sizeof (*cmd),
    1885             :             BUS_DMASYNC_PREWRITE);
    1886           0 :         bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
    1887             :             (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),
    1888             :             BUS_DMASYNC_PREWRITE);
    1889             : 
    1890             :         /* Kick TX ring. */
    1891           0 :         ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
    1892           0 :         WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
    1893             : 
    1894             :         /* Mark TX ring as full if we reach a certain threshold. */
    1895           0 :         if (++ring->queued > WPI_TX_RING_HIMARK)
    1896           0 :                 sc->qfullmsk |= 1 << ring->qid;
    1897             : 
    1898           0 :         return 0;
    1899           0 : }
    1900             : 
    1901             : void
    1902           0 : wpi_start(struct ifnet *ifp)
    1903             : {
    1904           0 :         struct wpi_softc *sc = ifp->if_softc;
    1905           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1906           0 :         struct ieee80211_node *ni;
    1907             :         struct mbuf *m;
    1908             : 
    1909           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    1910           0 :                 return;
    1911             : 
    1912           0 :         for (;;) {
    1913           0 :                 if (sc->qfullmsk != 0) {
    1914           0 :                         ifq_set_oactive(&ifp->if_snd);
    1915           0 :                         break;
    1916             :                 }
    1917             :                 /* Send pending management frames first. */
    1918           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    1919           0 :                 if (m != NULL) {
    1920           0 :                         ni = m->m_pkthdr.ph_cookie;
    1921           0 :                         goto sendit;
    1922             :                 }
    1923           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    1924             :                         break;
    1925             : 
    1926             :                 /* Encapsulate and send data frames. */
    1927           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m);
    1928           0 :                 if (m == NULL)
    1929             :                         break;
    1930             : #if NBPFILTER > 0
    1931           0 :                 if (ifp->if_bpf != NULL)
    1932           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    1933             : #endif
    1934           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
    1935           0 :                         continue;
    1936             : sendit:
    1937             : #if NBPFILTER > 0
    1938           0 :                 if (ic->ic_rawbpf != NULL)
    1939           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    1940             : #endif
    1941           0 :                 if (wpi_tx(sc, m, ni) != 0) {
    1942           0 :                         ieee80211_release_node(ic, ni);
    1943           0 :                         ifp->if_oerrors++;
    1944           0 :                         continue;
    1945             :                 }
    1946             : 
    1947           0 :                 sc->sc_tx_timer = 5;
    1948           0 :                 ifp->if_timer = 1;
    1949             :         }
    1950           0 : }
    1951             : 
    1952             : void
    1953           0 : wpi_watchdog(struct ifnet *ifp)
    1954             : {
    1955           0 :         struct wpi_softc *sc = ifp->if_softc;
    1956             : 
    1957           0 :         ifp->if_timer = 0;
    1958             : 
    1959           0 :         if (sc->sc_tx_timer > 0) {
    1960           0 :                 if (--sc->sc_tx_timer == 0) {
    1961           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    1962           0 :                         wpi_stop(ifp, 1);
    1963           0 :                         ifp->if_oerrors++;
    1964           0 :                         return;
    1965             :                 }
    1966           0 :                 ifp->if_timer = 1;
    1967           0 :         }
    1968             : 
    1969           0 :         ieee80211_watchdog(ifp);
    1970           0 : }
    1971             : 
    1972             : int
    1973           0 : wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1974             : {
    1975           0 :         struct wpi_softc *sc = ifp->if_softc;
    1976           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1977             :         int s, error = 0;
    1978             : 
    1979           0 :         error = rw_enter(&sc->sc_rwlock, RW_WRITE | RW_INTR);
    1980           0 :         if (error)
    1981           0 :                 return error;
    1982           0 :         s = splnet();
    1983             : 
    1984           0 :         switch (cmd) {
    1985             :         case SIOCSIFADDR:
    1986           0 :                 ifp->if_flags |= IFF_UP;
    1987             :                 /* FALLTHROUGH */
    1988             :         case SIOCSIFFLAGS:
    1989           0 :                 if (ifp->if_flags & IFF_UP) {
    1990           0 :                         if (!(ifp->if_flags & IFF_RUNNING))
    1991           0 :                                 error = wpi_init(ifp);
    1992             :                 } else {
    1993           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1994           0 :                                 wpi_stop(ifp, 1);
    1995             :                 }
    1996             :                 break;
    1997             : 
    1998             :         case SIOCS80211POWER:
    1999           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2000           0 :                 if (error != ENETRESET)
    2001             :                         break;
    2002           0 :                 if (ic->ic_state == IEEE80211_S_RUN) {
    2003           0 :                         if (ic->ic_flags & IEEE80211_F_PMGTON)
    2004           0 :                                 error = wpi_set_pslevel(sc, 0, 3, 0);
    2005             :                         else    /* back to CAM */
    2006           0 :                                 error = wpi_set_pslevel(sc, 0, 0, 0);
    2007             :                 } else {
    2008             :                         /* Defer until transition to IEEE80211_S_RUN. */
    2009             :                         error = 0;
    2010             :                 }
    2011             :                 break;
    2012             : 
    2013             :         default:
    2014           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2015           0 :         }
    2016             : 
    2017           0 :         if (error == ENETRESET) {
    2018             :                 error = 0;
    2019           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    2020             :                     (IFF_UP | IFF_RUNNING)) {
    2021           0 :                         wpi_stop(ifp, 0);
    2022           0 :                         error = wpi_init(ifp);
    2023           0 :                 }
    2024             :         }
    2025             : 
    2026           0 :         splx(s);
    2027           0 :         rw_exit_write(&sc->sc_rwlock);
    2028           0 :         return error;
    2029           0 : }
    2030             : 
    2031             : /*
    2032             :  * Send a command to the firmware.
    2033             :  */
    2034             : int
    2035           0 : wpi_cmd(struct wpi_softc *sc, int code, const void *buf, int size, int async)
    2036             : {
    2037           0 :         struct wpi_tx_ring *ring = &sc->txq[4];
    2038             :         struct wpi_tx_desc *desc;
    2039             :         struct wpi_tx_data *data;
    2040             :         struct wpi_tx_cmd *cmd;
    2041             :         struct mbuf *m;
    2042             :         bus_addr_t paddr;
    2043             :         int totlen, error;
    2044             : 
    2045           0 :         desc = &ring->desc[ring->cur];
    2046           0 :         data = &ring->data[ring->cur];
    2047           0 :         totlen = 4 + size;
    2048             : 
    2049           0 :         if (size > sizeof cmd->data) {
    2050             :                 /* Command is too large to fit in a descriptor. */
    2051           0 :                 if (totlen > MCLBYTES)
    2052           0 :                         return EINVAL;
    2053           0 :                 MGETHDR(m, M_DONTWAIT, MT_DATA);
    2054           0 :                 if (m == NULL)
    2055           0 :                         return ENOMEM;
    2056           0 :                 if (totlen > MHLEN) {
    2057           0 :                         MCLGET(m, M_DONTWAIT);
    2058           0 :                         if (!(m->m_flags & M_EXT)) {
    2059           0 :                                 m_freem(m);
    2060           0 :                                 return ENOMEM;
    2061             :                         }
    2062             :                 }
    2063           0 :                 cmd = mtod(m, struct wpi_tx_cmd *);
    2064           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, totlen,
    2065             :                     NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
    2066           0 :                 if (error != 0) {
    2067           0 :                         m_freem(m);
    2068           0 :                         return error;
    2069             :                 }
    2070           0 :                 data->m = m;
    2071           0 :                 paddr = data->map->dm_segs[0].ds_addr;
    2072           0 :         } else {
    2073           0 :                 cmd = &ring->cmd[ring->cur];
    2074           0 :                 paddr = data->cmd_paddr;
    2075             :         }
    2076             : 
    2077           0 :         cmd->code = code;
    2078           0 :         cmd->flags = 0;
    2079           0 :         cmd->qid = ring->qid;
    2080           0 :         cmd->idx = ring->cur;
    2081           0 :         memcpy(cmd->data, buf, size);
    2082             : 
    2083           0 :         desc->flags = htole32(WPI_PAD32(size) << 28 | 1 << 24);
    2084           0 :         desc->segs[0].addr = htole32(paddr);
    2085           0 :         desc->segs[0].len  = htole32(totlen);
    2086             : 
    2087           0 :         if (size > sizeof cmd->data) {
    2088           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0, totlen,
    2089             :                     BUS_DMASYNC_PREWRITE);
    2090           0 :         } else {
    2091           0 :                 bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map,
    2092             :                     (caddr_t)cmd - ring->cmd_dma.vaddr, totlen,
    2093             :                     BUS_DMASYNC_PREWRITE);
    2094             :         }
    2095           0 :         bus_dmamap_sync(sc->sc_dmat, ring->desc_dma.map,
    2096             :             (caddr_t)desc - ring->desc_dma.vaddr, sizeof (*desc),
    2097             :             BUS_DMASYNC_PREWRITE);
    2098             : 
    2099             :         /* Kick command ring. */
    2100           0 :         ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
    2101           0 :         WPI_WRITE(sc, WPI_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
    2102             : 
    2103           0 :         return async ? 0 : tsleep(cmd, PCATCH, "wpicmd", hz);
    2104           0 : }
    2105             : 
    2106             : /*
    2107             :  * Configure HW multi-rate retries.
    2108             :  */
    2109             : int
    2110           0 : wpi_mrr_setup(struct wpi_softc *sc)
    2111             : {
    2112           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2113           0 :         struct wpi_mrr_setup mrr;
    2114             :         int i, error;
    2115             : 
    2116             :         /* CCK rates (not used with 802.11a). */
    2117           0 :         for (i = WPI_RIDX_CCK1; i <= WPI_RIDX_CCK11; i++) {
    2118           0 :                 mrr.rates[i].flags = 0;
    2119           0 :                 mrr.rates[i].plcp = wpi_rates[i].plcp;
    2120             :                 /* Fallback to the immediate lower CCK rate (if any.) */
    2121           0 :                 mrr.rates[i].next =
    2122           0 :                     (i == WPI_RIDX_CCK1) ? WPI_RIDX_CCK1 : i - 1;
    2123             :                 /* Try one time at this rate before falling back to "next". */
    2124           0 :                 mrr.rates[i].ntries = 1;
    2125             :         }
    2126             :         /* OFDM rates (not used with 802.11b). */
    2127           0 :         for (i = WPI_RIDX_OFDM6; i <= WPI_RIDX_OFDM54; i++) {
    2128           0 :                 mrr.rates[i].flags = 0;
    2129           0 :                 mrr.rates[i].plcp = wpi_rates[i].plcp;
    2130             :                 /* Fallback to the immediate lower rate (if any.) */
    2131             :                 /* We allow fallback from OFDM/6 to CCK/2 in 11b/g mode. */
    2132           0 :                 mrr.rates[i].next = (i == WPI_RIDX_OFDM6) ?
    2133           0 :                     ((ic->ic_curmode == IEEE80211_MODE_11A) ?
    2134             :                         WPI_RIDX_OFDM6 : WPI_RIDX_CCK2) :
    2135           0 :                     i - 1;
    2136             :                 /* Try one time at this rate before falling back to "next". */
    2137           0 :                 mrr.rates[i].ntries = 1;
    2138             :         }
    2139             :         /* Setup MRR for control frames. */
    2140           0 :         mrr.which = htole32(WPI_MRR_CTL);
    2141           0 :         error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0);
    2142           0 :         if (error != 0) {
    2143           0 :                 printf("%s: could not setup MRR for control frames\n",
    2144           0 :                     sc->sc_dev.dv_xname);
    2145           0 :                 return error;
    2146             :         }
    2147             :         /* Setup MRR for data frames. */
    2148           0 :         mrr.which = htole32(WPI_MRR_DATA);
    2149           0 :         error = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof mrr, 0);
    2150           0 :         if (error != 0) {
    2151           0 :                 printf("%s: could not setup MRR for data frames\n",
    2152           0 :                     sc->sc_dev.dv_xname);
    2153           0 :                 return error;
    2154             :         }
    2155           0 :         return 0;
    2156           0 : }
    2157             : 
    2158             : void
    2159           0 : wpi_updateedca(struct ieee80211com *ic)
    2160             : {
    2161             : #define WPI_EXP2(x)     ((1 << (x)) - 1)  /* CWmin = 2^ECWmin - 1 */
    2162           0 :         struct wpi_softc *sc = ic->ic_softc;
    2163           0 :         struct wpi_edca_params cmd;
    2164             :         int aci;
    2165             : 
    2166           0 :         memset(&cmd, 0, sizeof cmd);
    2167           0 :         cmd.flags = htole32(WPI_EDCA_UPDATE);
    2168           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
    2169             :                 const struct ieee80211_edca_ac_params *ac =
    2170           0 :                     &ic->ic_edca_ac[aci];
    2171           0 :                 cmd.ac[aci].aifsn = ac->ac_aifsn;
    2172           0 :                 cmd.ac[aci].cwmin = htole16(WPI_EXP2(ac->ac_ecwmin));
    2173           0 :                 cmd.ac[aci].cwmax = htole16(WPI_EXP2(ac->ac_ecwmax));
    2174           0 :                 cmd.ac[aci].txoplimit =
    2175           0 :                     htole16(IEEE80211_TXOP_TO_US(ac->ac_txoplimit));
    2176             :         }
    2177           0 :         (void)wpi_cmd(sc, WPI_CMD_EDCA_PARAMS, &cmd, sizeof cmd, 1);
    2178             : #undef WPI_EXP2
    2179           0 : }
    2180             : 
    2181             : void
    2182           0 : wpi_set_led(struct wpi_softc *sc, uint8_t which, uint8_t off, uint8_t on)
    2183             : {
    2184           0 :         struct wpi_cmd_led led;
    2185             : 
    2186           0 :         led.which = which;
    2187           0 :         led.unit = htole32(100000);     /* on/off in unit of 100ms */
    2188           0 :         led.off = off;
    2189           0 :         led.on = on;
    2190           0 :         (void)wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof led, 1);
    2191           0 : }
    2192             : 
    2193             : int
    2194           0 : wpi_set_timing(struct wpi_softc *sc, struct ieee80211_node *ni)
    2195             : {
    2196           0 :         struct wpi_cmd_timing cmd;
    2197             :         uint64_t val, mod;
    2198             : 
    2199           0 :         memset(&cmd, 0, sizeof cmd);
    2200           0 :         memcpy(&cmd.tstamp, ni->ni_tstamp, sizeof (uint64_t));
    2201           0 :         cmd.bintval = htole16(ni->ni_intval);
    2202           0 :         cmd.lintval = htole16(10);
    2203             : 
    2204             :         /* Compute remaining time until next beacon. */
    2205           0 :         val = (uint64_t)ni->ni_intval * 1024;        /* msecs -> usecs */
    2206           0 :         mod = letoh64(cmd.tstamp) % val;
    2207           0 :         cmd.binitval = htole32((uint32_t)(val - mod));
    2208             : 
    2209             :         DPRINTF(("timing bintval=%u, tstamp=%llu, init=%u\n",
    2210             :             ni->ni_intval, letoh64(cmd.tstamp), (uint32_t)(val - mod)));
    2211             : 
    2212           0 :         return wpi_cmd(sc, WPI_CMD_TIMING, &cmd, sizeof cmd, 1);
    2213           0 : }
    2214             : 
    2215             : /*
    2216             :  * This function is called periodically (every minute) to adjust TX power
    2217             :  * based on temperature variation.
    2218             :  */
    2219             : void
    2220           0 : wpi_power_calibration(struct wpi_softc *sc)
    2221             : {
    2222             :         int temp;
    2223             : 
    2224           0 :         temp = (int)WPI_READ(sc, WPI_UCODE_GP2);
    2225             :         /* Sanity-check temperature. */
    2226           0 :         if (temp < -260 || temp > 25) {
    2227             :                 /* This can't be correct, ignore. */
    2228             :                 DPRINTF(("out-of-range temperature reported: %d\n", temp));
    2229           0 :                 return;
    2230             :         }
    2231             :         DPRINTF(("temperature %d->%d\n", sc->temp, temp));
    2232             :         /* Adjust TX power if need be (delta > 6). */
    2233           0 :         if (abs(temp - sc->temp) > 6) {
    2234             :                 /* Record temperature of last calibration. */
    2235           0 :                 sc->temp = temp;
    2236           0 :                 (void)wpi_set_txpower(sc, 1);
    2237           0 :         }
    2238           0 : }
    2239             : 
    2240             : /*
    2241             :  * Set TX power for current channel (each rate has its own power settings).
    2242             :  */
    2243             : int
    2244           0 : wpi_set_txpower(struct wpi_softc *sc, int async)
    2245             : {
    2246           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2247             :         struct ieee80211_channel *ch;
    2248             :         struct wpi_power_group *group;
    2249           0 :         struct wpi_cmd_txpower cmd;
    2250             :         u_int chan;
    2251             :         int idx, i;
    2252             : 
    2253             :         /* Retrieve current channel from last RXON. */
    2254           0 :         chan = sc->rxon.chan;
    2255             :         DPRINTF(("setting TX power for channel %d\n", chan));
    2256           0 :         ch = &ic->ic_channels[chan];
    2257             : 
    2258             :         /* Find the TX power group to which this channel belongs. */
    2259           0 :         if (IEEE80211_IS_CHAN_5GHZ(ch)) {
    2260           0 :                 for (group = &sc->groups[1]; group < &sc->groups[4]; group++)
    2261           0 :                         if (chan <= group->chan)
    2262             :                                 break;
    2263             :         } else
    2264           0 :                 group = &sc->groups[0];
    2265             : 
    2266           0 :         memset(&cmd, 0, sizeof cmd);
    2267           0 :         cmd.band = IEEE80211_IS_CHAN_5GHZ(ch) ? 0 : 1;
    2268           0 :         cmd.chan = htole16(chan);
    2269             : 
    2270             :         /* Set TX power for all OFDM and CCK rates. */
    2271           0 :         for (i = 0; i <= WPI_RIDX_MAX ; i++) {
    2272             :                 /* Retrieve TX power for this channel/rate. */
    2273           0 :                 idx = wpi_get_power_index(sc, group, ch, i);
    2274             : 
    2275           0 :                 cmd.rates[i].plcp = wpi_rates[i].plcp;
    2276             : 
    2277           0 :                 if (IEEE80211_IS_CHAN_5GHZ(ch)) {
    2278           0 :                         cmd.rates[i].rf_gain = wpi_rf_gain_5ghz[idx];
    2279           0 :                         cmd.rates[i].dsp_gain = wpi_dsp_gain_5ghz[idx];
    2280           0 :                 } else {
    2281           0 :                         cmd.rates[i].rf_gain = wpi_rf_gain_2ghz[idx];
    2282           0 :                         cmd.rates[i].dsp_gain = wpi_dsp_gain_2ghz[idx];
    2283             :                 }
    2284             :                 DPRINTF(("chan %d/rate %d: power index %d\n", chan,
    2285             :                     wpi_rates[i].rate, idx));
    2286             :         }
    2287           0 :         return wpi_cmd(sc, WPI_CMD_TXPOWER, &cmd, sizeof cmd, async);
    2288           0 : }
    2289             : 
    2290             : /*
    2291             :  * Determine TX power index for a given channel/rate combination.
    2292             :  * This takes into account the regulatory information from EEPROM and the
    2293             :  * current temperature.
    2294             :  */
    2295             : int
    2296           0 : wpi_get_power_index(struct wpi_softc *sc, struct wpi_power_group *group,
    2297             :     struct ieee80211_channel *c, int ridx)
    2298             : {
    2299             : /* Fixed-point arithmetic division using a n-bit fractional part. */
    2300             : #define fdivround(a, b, n)      \
    2301             :         ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
    2302             : 
    2303             : /* Linear interpolation. */
    2304             : #define interpolate(x, x1, y1, x2, y2, n)       \
    2305             :         ((y1) + fdivround(((x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
    2306             : 
    2307           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2308             :         struct wpi_power_sample *sample;
    2309             :         int pwr, idx;
    2310             :         u_int chan;
    2311             : 
    2312             :         /* Get channel number. */
    2313           0 :         chan = ieee80211_chan2ieee(ic, c);
    2314             : 
    2315             :         /* Default TX power is group maximum TX power minus 3dB. */
    2316           0 :         pwr = group->maxpwr / 2;
    2317             : 
    2318             :         /* Decrease TX power for highest OFDM rates to reduce distortion. */
    2319           0 :         switch (ridx) {
    2320             :         case WPI_RIDX_OFDM36:
    2321           0 :                 pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 0 :  5;
    2322           0 :                 break;
    2323             :         case WPI_RIDX_OFDM48:
    2324           0 :                 pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 7 : 10;
    2325           0 :                 break;
    2326             :         case WPI_RIDX_OFDM54:
    2327           0 :                 pwr -= IEEE80211_IS_CHAN_2GHZ(c) ? 9 : 12;
    2328           0 :                 break;
    2329             :         }
    2330             : 
    2331             :         /* Never exceed the channel maximum allowed TX power. */
    2332           0 :         pwr = MIN(pwr, sc->maxpwr[chan]);
    2333             : 
    2334             :         /* Retrieve TX power index into gain tables from samples. */
    2335           0 :         for (sample = group->samples; sample < &group->samples[3]; sample++)
    2336           0 :                 if (pwr > sample[1].power)
    2337             :                         break;
    2338             :         /* Fixed-point linear interpolation using a 19-bit fractional part. */
    2339           0 :         idx = interpolate(pwr, sample[0].power, sample[0].index,
    2340             :             sample[1].power, sample[1].index, 19);
    2341             : 
    2342             :         /*-
    2343             :          * Adjust power index based on current temperature:
    2344             :          * - if cooler than factory-calibrated: decrease output power
    2345             :          * - if warmer than factory-calibrated: increase output power
    2346             :          */
    2347           0 :         idx -= (sc->temp - group->temp) * 11 / 100;
    2348             : 
    2349             :         /* Decrease TX power for CCK rates (-5dB). */
    2350           0 :         if (ridx >= WPI_RIDX_CCK1)
    2351           0 :                 idx += 10;
    2352             : 
    2353             :         /* Make sure idx stays in a valid range. */
    2354           0 :         if (idx < 0)
    2355           0 :                 idx = 0;
    2356           0 :         else if (idx > WPI_MAX_PWR_INDEX)
    2357           0 :                 idx = WPI_MAX_PWR_INDEX;
    2358           0 :         return idx;
    2359             : 
    2360             : #undef interpolate
    2361             : #undef fdivround
    2362             : }
    2363             : 
    2364             : /*
    2365             :  * Set STA mode power saving level (between 0 and 5).
    2366             :  * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.
    2367             :  */
    2368             : int
    2369           0 : wpi_set_pslevel(struct wpi_softc *sc, int dtim, int level, int async)
    2370             : {
    2371           0 :         struct wpi_pmgt_cmd cmd;
    2372             :         const struct wpi_pmgt *pmgt;
    2373             :         uint32_t max, skip_dtim;
    2374             :         pcireg_t reg;
    2375             :         int i;
    2376             : 
    2377             :         /* Select which PS parameters to use. */
    2378           0 :         if (dtim <= 10)
    2379           0 :                 pmgt = &wpi_pmgt[0][level];
    2380             :         else
    2381           0 :                 pmgt = &wpi_pmgt[1][level];
    2382             : 
    2383           0 :         memset(&cmd, 0, sizeof cmd);
    2384           0 :         if (level != 0) /* not CAM */
    2385           0 :                 cmd.flags |= htole16(WPI_PS_ALLOW_SLEEP);
    2386             :         /* Retrieve PCIe Active State Power Management (ASPM). */
    2387           0 :         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
    2388           0 :             sc->sc_cap_off + PCI_PCIE_LCSR);
    2389           0 :         if (!(reg & PCI_PCIE_LCSR_ASPM_L0S))        /* L0s Entry disabled. */
    2390           0 :                 cmd.flags |= htole16(WPI_PS_PCI_PMGT);
    2391           0 :         cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024);
    2392           0 :         cmd.txtimeout = htole32(pmgt->txtimeout * 1024);
    2393             : 
    2394           0 :         if (dtim == 0) {
    2395             :                 dtim = 1;
    2396             :                 skip_dtim = 0;
    2397           0 :         } else
    2398           0 :                 skip_dtim = pmgt->skip_dtim;
    2399           0 :         if (skip_dtim != 0) {
    2400           0 :                 cmd.flags |= htole16(WPI_PS_SLEEP_OVER_DTIM);
    2401           0 :                 max = pmgt->intval[4];
    2402           0 :                 if (max == (uint32_t)-1)
    2403           0 :                         max = dtim * (skip_dtim + 1);
    2404           0 :                 else if (max > dtim)
    2405           0 :                         max = (max / dtim) * dtim;
    2406             :         } else
    2407             :                 max = dtim;
    2408           0 :         for (i = 0; i < 5; i++)
    2409           0 :                 cmd.intval[i] = htole32(MIN(max, pmgt->intval[i]));
    2410             : 
    2411             :         DPRINTF(("setting power saving level to %d\n", level));
    2412           0 :         return wpi_cmd(sc, WPI_CMD_SET_POWER_MODE, &cmd, sizeof cmd, async);
    2413           0 : }
    2414             : 
    2415             : int
    2416           0 : wpi_config(struct wpi_softc *sc)
    2417             : {
    2418           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2419           0 :         struct ifnet *ifp = &ic->ic_if;
    2420           0 :         struct wpi_bluetooth bluetooth;
    2421           0 :         struct wpi_node_info node;
    2422             :         int error;
    2423             : 
    2424             :         /* Set power saving level to CAM during initialization. */
    2425           0 :         if ((error = wpi_set_pslevel(sc, 0, 0, 0)) != 0) {
    2426           0 :                 printf("%s: could not set power saving level\n",
    2427           0 :                     sc->sc_dev.dv_xname);
    2428           0 :                 return error;
    2429             :         }
    2430             : 
    2431             :         /* Configure bluetooth coexistence. */
    2432           0 :         memset(&bluetooth, 0, sizeof bluetooth);
    2433           0 :         bluetooth.flags = WPI_BT_COEX_MODE_4WIRE;
    2434           0 :         bluetooth.lead_time = WPI_BT_LEAD_TIME_DEF;
    2435           0 :         bluetooth.max_kill = WPI_BT_MAX_KILL_DEF;
    2436           0 :         error = wpi_cmd(sc, WPI_CMD_BT_COEX, &bluetooth, sizeof bluetooth, 0);
    2437           0 :         if (error != 0) {
    2438           0 :                 printf("%s: could not configure bluetooth coexistence\n",
    2439           0 :                     sc->sc_dev.dv_xname);
    2440           0 :                 return error;
    2441             :         }
    2442             : 
    2443             :         /* Configure adapter. */
    2444           0 :         memset(&sc->rxon, 0, sizeof (struct wpi_rxon));
    2445           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    2446           0 :         IEEE80211_ADDR_COPY(sc->rxon.myaddr, ic->ic_myaddr);
    2447             :         /* Set default channel. */
    2448           0 :         sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
    2449           0 :         sc->rxon.flags = htole32(WPI_RXON_TSF);
    2450           0 :         if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan))
    2451           0 :                 sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ);
    2452           0 :         switch (ic->ic_opmode) {
    2453             :         case IEEE80211_M_STA:
    2454           0 :                 sc->rxon.mode = WPI_MODE_STA;
    2455           0 :                 sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
    2456           0 :                 break;
    2457             :         case IEEE80211_M_MONITOR:
    2458           0 :                 sc->rxon.mode = WPI_MODE_MONITOR;
    2459           0 :                 sc->rxon.filter = htole32(WPI_FILTER_MULTICAST |
    2460             :                     WPI_FILTER_CTL | WPI_FILTER_PROMISC);
    2461           0 :                 break;
    2462             :         default:
    2463             :                 /* Should not get there. */
    2464             :                 break;
    2465             :         }
    2466           0 :         sc->rxon.cck_mask  = 0x0f;   /* not yet negotiated */
    2467           0 :         sc->rxon.ofdm_mask = 0xff;   /* not yet negotiated */
    2468             :         DPRINTF(("setting configuration\n"));
    2469           0 :         error = wpi_cmd(sc, WPI_CMD_RXON, &sc->rxon, sizeof (struct wpi_rxon),
    2470             :             0);
    2471           0 :         if (error != 0) {
    2472           0 :                 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
    2473           0 :                 return error;
    2474             :         }
    2475             : 
    2476             :         /* Configuration has changed, set TX power accordingly. */
    2477           0 :         if ((error = wpi_set_txpower(sc, 0)) != 0) {
    2478           0 :                 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
    2479           0 :                 return error;
    2480             :         }
    2481             : 
    2482             :         /* Add broadcast node. */
    2483           0 :         memset(&node, 0, sizeof node);
    2484           0 :         IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr);
    2485           0 :         node.id = WPI_ID_BROADCAST;
    2486           0 :         node.plcp = wpi_rates[WPI_RIDX_CCK1].plcp;
    2487           0 :         node.action = htole32(WPI_ACTION_SET_RATE);
    2488           0 :         node.antenna = WPI_ANTENNA_BOTH;
    2489           0 :         error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 0);
    2490           0 :         if (error != 0) {
    2491           0 :                 printf("%s: could not add broadcast node\n",
    2492           0 :                     sc->sc_dev.dv_xname);
    2493           0 :                 return error;
    2494             :         }
    2495             : 
    2496           0 :         if ((error = wpi_mrr_setup(sc)) != 0) {
    2497           0 :                 printf("%s: could not setup MRR\n", sc->sc_dev.dv_xname);
    2498           0 :                 return error;
    2499             :         }
    2500           0 :         return 0;
    2501           0 : }
    2502             : 
    2503             : int
    2504           0 : wpi_scan(struct wpi_softc *sc, uint16_t flags)
    2505             : {
    2506           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2507             :         struct wpi_scan_hdr *hdr;
    2508             :         struct wpi_cmd_data *tx;
    2509             :         struct wpi_scan_essid *essid;
    2510             :         struct wpi_scan_chan *chan;
    2511             :         struct ieee80211_frame *wh;
    2512             :         struct ieee80211_rateset *rs;
    2513             :         struct ieee80211_channel *c;
    2514             :         uint8_t *buf, *frm;
    2515             :         int buflen, error;
    2516             : 
    2517           0 :         buf = malloc(WPI_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);
    2518           0 :         if (buf == NULL) {
    2519           0 :                 printf("%s: could not allocate buffer for scan command\n",
    2520           0 :                     sc->sc_dev.dv_xname);
    2521           0 :                 return ENOMEM;
    2522             :         }
    2523           0 :         hdr = (struct wpi_scan_hdr *)buf;
    2524             :         /*
    2525             :          * Move to the next channel if no frames are received within 10ms
    2526             :          * after sending the probe request.
    2527             :          */
    2528           0 :         hdr->quiet_time = htole16(10);               /* timeout in milliseconds */
    2529           0 :         hdr->quiet_threshold = htole16(1);   /* min # of packets */
    2530             : 
    2531           0 :         tx = (struct wpi_cmd_data *)(hdr + 1);
    2532           0 :         tx->flags = htole32(WPI_TX_AUTO_SEQ);
    2533           0 :         tx->id = WPI_ID_BROADCAST;
    2534           0 :         tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
    2535             : 
    2536           0 :         if (flags & IEEE80211_CHAN_5GHZ) {
    2537           0 :                 hdr->crc_threshold = htole16(1);
    2538             :                 /* Send probe requests at 6Mbps. */
    2539           0 :                 tx->plcp = wpi_rates[WPI_RIDX_OFDM6].plcp;
    2540           0 :                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
    2541           0 :         } else {
    2542           0 :                 hdr->flags = htole32(WPI_RXON_24GHZ | WPI_RXON_AUTO);
    2543             :                 /* Send probe requests at 1Mbps. */
    2544           0 :                 tx->plcp = wpi_rates[WPI_RIDX_CCK1].plcp;
    2545           0 :                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
    2546             :         }
    2547             : 
    2548           0 :         essid = (struct wpi_scan_essid *)(tx + 1);
    2549           0 :         if (ic->ic_des_esslen != 0) {
    2550           0 :                 essid[0].id  = IEEE80211_ELEMID_SSID;
    2551           0 :                 essid[0].len = ic->ic_des_esslen;
    2552           0 :                 memcpy(essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);
    2553           0 :         }
    2554             :         /*
    2555             :          * Build a probe request frame.  Most of the following code is a
    2556             :          * copy & paste of what is done in net80211.
    2557             :          */
    2558           0 :         wh = (struct ieee80211_frame *)(essid + 4);
    2559           0 :         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
    2560             :             IEEE80211_FC0_SUBTYPE_PROBE_REQ;
    2561           0 :         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
    2562           0 :         IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
    2563           0 :         IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
    2564           0 :         IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
    2565           0 :         *(uint16_t *)&wh->i_dur[0] = 0;  /* filled by HW */
    2566           0 :         *(uint16_t *)&wh->i_seq[0] = 0;  /* filled by HW */
    2567             : 
    2568           0 :         frm = (uint8_t *)(wh + 1);
    2569           0 :         frm = ieee80211_add_ssid(frm, NULL, 0);
    2570           0 :         frm = ieee80211_add_rates(frm, rs);
    2571           0 :         if (rs->rs_nrates > IEEE80211_RATE_SIZE)
    2572           0 :                 frm = ieee80211_add_xrates(frm, rs);
    2573             : 
    2574             :         /* Set length of probe request. */
    2575           0 :         tx->len = htole16(frm - (uint8_t *)wh);
    2576             : 
    2577           0 :         chan = (struct wpi_scan_chan *)frm;
    2578           0 :         for (c  = &ic->ic_channels[1];
    2579           0 :              c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {
    2580           0 :                 if ((c->ic_flags & flags) != flags)
    2581             :                         continue;
    2582             : 
    2583           0 :                 chan->chan = ieee80211_chan2ieee(ic, c);
    2584             :                 DPRINTFN(2, ("adding channel %d\n", chan->chan));
    2585           0 :                 chan->flags = 0;
    2586           0 :                 if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE))
    2587           0 :                         chan->flags |= WPI_CHAN_ACTIVE;
    2588           0 :                 if (ic->ic_des_esslen != 0)
    2589           0 :                         chan->flags |= WPI_CHAN_NPBREQS(1);
    2590           0 :                 chan->dsp_gain = 0x6e;
    2591           0 :                 if (IEEE80211_IS_CHAN_5GHZ(c)) {
    2592           0 :                         chan->rf_gain = 0x3b;
    2593           0 :                         chan->active  = htole16(24);
    2594           0 :                         chan->passive = htole16(110);
    2595           0 :                 } else {
    2596           0 :                         chan->rf_gain = 0x28;
    2597           0 :                         chan->active  = htole16(36);
    2598           0 :                         chan->passive = htole16(120);
    2599             :                 }
    2600           0 :                 hdr->nchan++;
    2601           0 :                 chan++;
    2602           0 :         }
    2603             : 
    2604           0 :         buflen = (uint8_t *)chan - buf;
    2605           0 :         hdr->len = htole16(buflen);
    2606             : 
    2607             :         DPRINTF(("sending scan command nchan=%d\n", hdr->nchan));
    2608           0 :         error = wpi_cmd(sc, WPI_CMD_SCAN, buf, buflen, 1);
    2609           0 :         free(buf, M_DEVBUF, WPI_SCAN_MAXSZ);
    2610           0 :         return error;
    2611           0 : }
    2612             : 
    2613             : int
    2614           0 : wpi_auth(struct wpi_softc *sc)
    2615             : {
    2616           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2617           0 :         struct ieee80211_node *ni = ic->ic_bss;
    2618           0 :         struct wpi_node_info node;
    2619             :         int error;
    2620             : 
    2621             :         /* Update adapter configuration. */
    2622           0 :         IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid);
    2623           0 :         sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
    2624           0 :         sc->rxon.flags = htole32(WPI_RXON_TSF);
    2625           0 :         if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
    2626           0 :                 sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ);
    2627           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT)
    2628           0 :                 sc->rxon.flags |= htole32(WPI_RXON_SHSLOT);
    2629           0 :         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
    2630           0 :                 sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE);
    2631           0 :         switch (ic->ic_curmode) {
    2632             :         case IEEE80211_MODE_11A:
    2633           0 :                 sc->rxon.cck_mask  = 0;
    2634           0 :                 sc->rxon.ofdm_mask = 0x15;
    2635           0 :                 break;
    2636             :         case IEEE80211_MODE_11B:
    2637           0 :                 sc->rxon.cck_mask  = 0x03;
    2638           0 :                 sc->rxon.ofdm_mask = 0;
    2639           0 :                 break;
    2640             :         default:        /* Assume 802.11b/g. */
    2641           0 :                 sc->rxon.cck_mask  = 0x0f;
    2642           0 :                 sc->rxon.ofdm_mask = 0x15;
    2643           0 :         }
    2644             :         DPRINTF(("rxon chan %d flags %x cck %x ofdm %x\n", sc->rxon.chan,
    2645             :             sc->rxon.flags, sc->rxon.cck_mask, sc->rxon.ofdm_mask));
    2646           0 :         error = wpi_cmd(sc, WPI_CMD_RXON, &sc->rxon, sizeof (struct wpi_rxon),
    2647             :             1);
    2648           0 :         if (error != 0) {
    2649           0 :                 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
    2650           0 :                 return error;
    2651             :         }
    2652             : 
    2653             :         /* Configuration has changed, set TX power accordingly. */
    2654           0 :         if ((error = wpi_set_txpower(sc, 1)) != 0) {
    2655           0 :                 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
    2656           0 :                 return error;
    2657             :         }
    2658             :         /*
    2659             :          * Reconfiguring RXON clears the firmware nodes table so we must
    2660             :          * add the broadcast node again.
    2661             :          */
    2662           0 :         memset(&node, 0, sizeof node);
    2663           0 :         IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr);
    2664           0 :         node.id = WPI_ID_BROADCAST;
    2665           0 :         node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ?
    2666             :             wpi_rates[WPI_RIDX_OFDM6].plcp : wpi_rates[WPI_RIDX_CCK1].plcp;
    2667           0 :         node.action = htole32(WPI_ACTION_SET_RATE);
    2668           0 :         node.antenna = WPI_ANTENNA_BOTH;
    2669           0 :         error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
    2670           0 :         if (error != 0) {
    2671           0 :                 printf("%s: could not add broadcast node\n",
    2672           0 :                     sc->sc_dev.dv_xname);
    2673           0 :                 return error;
    2674             :         }
    2675           0 :         return 0;
    2676           0 : }
    2677             : 
    2678             : int
    2679           0 : wpi_run(struct wpi_softc *sc)
    2680             : {
    2681           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2682           0 :         struct ieee80211_node *ni = ic->ic_bss;
    2683           0 :         struct wpi_node_info node;
    2684             :         int error;
    2685             : 
    2686           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    2687             :                 /* Link LED blinks while monitoring. */
    2688           0 :                 wpi_set_led(sc, WPI_LED_LINK, 5, 5);
    2689           0 :                 return 0;
    2690             :         }
    2691           0 :         if ((error = wpi_set_timing(sc, ni)) != 0) {
    2692           0 :                 printf("%s: could not set timing\n", sc->sc_dev.dv_xname);
    2693           0 :                 return error;
    2694             :         }
    2695             : 
    2696             :         /* Update adapter configuration. */
    2697           0 :         sc->rxon.associd = htole16(IEEE80211_AID(ni->ni_associd));
    2698             :         /* Short preamble and slot time are negotiated when associating. */
    2699           0 :         sc->rxon.flags &= ~htole32(WPI_RXON_SHPREAMBLE | WPI_RXON_SHSLOT);
    2700           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT)
    2701           0 :                 sc->rxon.flags |= htole32(WPI_RXON_SHSLOT);
    2702           0 :         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
    2703           0 :                 sc->rxon.flags |= htole32(WPI_RXON_SHPREAMBLE);
    2704           0 :         sc->rxon.filter |= htole32(WPI_FILTER_BSS);
    2705             :         DPRINTF(("rxon chan %d flags %x\n", sc->rxon.chan, sc->rxon.flags));
    2706           0 :         error = wpi_cmd(sc, WPI_CMD_RXON, &sc->rxon, sizeof (struct wpi_rxon),
    2707             :             1);
    2708           0 :         if (error != 0) {
    2709           0 :                 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
    2710           0 :                 return error;
    2711             :         }
    2712             : 
    2713             :         /* Configuration has changed, set TX power accordingly. */
    2714           0 :         if ((error = wpi_set_txpower(sc, 1)) != 0) {
    2715           0 :                 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
    2716           0 :                 return error;
    2717             :         }
    2718             : 
    2719             :         /* Fake a join to init the TX rate. */
    2720           0 :         ((struct wpi_node *)ni)->id = WPI_ID_BSS;
    2721           0 :         wpi_newassoc(ic, ni, 1);
    2722             : 
    2723             :         /* Add BSS node. */
    2724           0 :         memset(&node, 0, sizeof node);
    2725           0 :         IEEE80211_ADDR_COPY(node.macaddr, ni->ni_bssid);
    2726           0 :         node.id = WPI_ID_BSS;
    2727           0 :         node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ?
    2728             :             wpi_rates[WPI_RIDX_OFDM6].plcp : wpi_rates[WPI_RIDX_CCK1].plcp;
    2729           0 :         node.action = htole32(WPI_ACTION_SET_RATE);
    2730           0 :         node.antenna = WPI_ANTENNA_BOTH;
    2731             :         DPRINTF(("adding BSS node\n"));
    2732           0 :         error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
    2733           0 :         if (error != 0) {
    2734           0 :                 printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
    2735           0 :                 return error;
    2736             :         }
    2737             : 
    2738             :         /* Start periodic calibration timer. */
    2739           0 :         sc->calib_cnt = 0;
    2740           0 :         timeout_add_msec(&sc->calib_to, 500);
    2741             : 
    2742             :         /* Link LED always on while associated. */
    2743           0 :         wpi_set_led(sc, WPI_LED_LINK, 0, 1);
    2744             : 
    2745             :         /* Enable power-saving mode if requested by user. */
    2746           0 :         if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON)
    2747           0 :                 (void)wpi_set_pslevel(sc, 0, 3, 1);
    2748             : 
    2749           0 :         return 0;
    2750           0 : }
    2751             : 
    2752             : /*
    2753             :  * We support CCMP hardware encryption/decryption of unicast frames only.
    2754             :  * HW support for TKIP really sucks.  We should let TKIP die anyway.
    2755             :  */
    2756             : int
    2757           0 : wpi_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    2758             :     struct ieee80211_key *k)
    2759             : {
    2760           0 :         struct wpi_softc *sc = ic->ic_softc;
    2761           0 :         struct wpi_node *wn = (void *)ni;
    2762           0 :         struct wpi_node_info node;
    2763             :         uint16_t kflags;
    2764             : 
    2765           0 :         if ((k->k_flags & IEEE80211_KEY_GROUP) ||
    2766           0 :             k->k_cipher != IEEE80211_CIPHER_CCMP)
    2767           0 :                 return ieee80211_set_key(ic, ni, k);
    2768             : 
    2769           0 :         kflags = WPI_KFLAG_CCMP | WPI_KFLAG_KID(k->k_id);
    2770           0 :         memset(&node, 0, sizeof node);
    2771           0 :         node.id = wn->id;
    2772           0 :         node.control = WPI_NODE_UPDATE;
    2773           0 :         node.flags = WPI_FLAG_SET_KEY;
    2774           0 :         node.kflags = htole16(kflags);
    2775           0 :         memcpy(node.key, k->k_key, k->k_len);
    2776             :         DPRINTF(("set key id=%d for node %d\n", k->k_id, node.id));
    2777           0 :         return wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
    2778           0 : }
    2779             : 
    2780             : void
    2781           0 : wpi_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    2782             :     struct ieee80211_key *k)
    2783             : {
    2784           0 :         struct wpi_softc *sc = ic->ic_softc;
    2785           0 :         struct wpi_node *wn = (void *)ni;
    2786           0 :         struct wpi_node_info node;
    2787             : 
    2788           0 :         if ((k->k_flags & IEEE80211_KEY_GROUP) ||
    2789           0 :             k->k_cipher != IEEE80211_CIPHER_CCMP) {
    2790             :                 /* See comment about other ciphers above. */
    2791           0 :                 ieee80211_delete_key(ic, ni, k);
    2792           0 :                 return;
    2793             :         }
    2794           0 :         if (ic->ic_state != IEEE80211_S_RUN)
    2795           0 :                 return; /* Nothing to do. */
    2796           0 :         memset(&node, 0, sizeof node);
    2797           0 :         node.id = wn->id;
    2798           0 :         node.control = WPI_NODE_UPDATE;
    2799           0 :         node.flags = WPI_FLAG_SET_KEY;
    2800           0 :         node.kflags = 0;
    2801             :         DPRINTF(("delete keys for node %d\n", node.id));
    2802           0 :         (void)wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
    2803           0 : }
    2804             : 
    2805             : int
    2806           0 : wpi_post_alive(struct wpi_softc *sc)
    2807             : {
    2808             :         int ntries, error;
    2809             : 
    2810             :         /* Check (again) that the radio is not disabled. */
    2811           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    2812           0 :                 return error;
    2813             :         /* NB: Runtime firmware must be up and running. */
    2814           0 :         if (!(wpi_prph_read(sc, WPI_APMG_RFKILL) & 1)) {
    2815           0 :                 printf("%s: radio is disabled by hardware switch\n",
    2816           0 :                     sc->sc_dev.dv_xname);
    2817           0 :                 wpi_nic_unlock(sc);
    2818           0 :                 return EPERM;   /* :-) */
    2819             :         }
    2820           0 :         wpi_nic_unlock(sc);
    2821             : 
    2822             :         /* Wait for thermal sensor to calibrate. */
    2823           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    2824           0 :                 if ((sc->temp = (int)WPI_READ(sc, WPI_UCODE_GP2)) != 0)
    2825             :                         break;
    2826           0 :                 DELAY(10);
    2827             :         }
    2828           0 :         if (ntries == 1000) {
    2829           0 :                 printf("%s: timeout waiting for thermal sensor calibration\n",
    2830           0 :                     sc->sc_dev.dv_xname);
    2831           0 :                 return ETIMEDOUT;
    2832             :         }
    2833             :         DPRINTF(("temperature %d\n", sc->temp));
    2834           0 :         return 0;
    2835           0 : }
    2836             : 
    2837             : /*
    2838             :  * The firmware boot code is small and is intended to be copied directly into
    2839             :  * the NIC internal memory (no DMA transfer.)
    2840             :  */
    2841             : int
    2842           0 : wpi_load_bootcode(struct wpi_softc *sc, const uint8_t *ucode, int size)
    2843             : {
    2844             :         int error, ntries;
    2845             : 
    2846           0 :         size /= sizeof (uint32_t);
    2847             : 
    2848           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    2849           0 :                 return error;
    2850             : 
    2851             :         /* Copy microcode image into NIC memory. */
    2852           0 :         wpi_prph_write_region_4(sc, WPI_BSM_SRAM_BASE,
    2853           0 :             (const uint32_t *)ucode, size);
    2854             : 
    2855           0 :         wpi_prph_write(sc, WPI_BSM_WR_MEM_SRC, 0);
    2856           0 :         wpi_prph_write(sc, WPI_BSM_WR_MEM_DST, WPI_FW_TEXT_BASE);
    2857           0 :         wpi_prph_write(sc, WPI_BSM_WR_DWCOUNT, size);
    2858             : 
    2859             :         /* Start boot load now. */
    2860           0 :         wpi_prph_write(sc, WPI_BSM_WR_CTRL, WPI_BSM_WR_CTRL_START);
    2861             : 
    2862             :         /* Wait for transfer to complete. */
    2863           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    2864           0 :                 if (!(wpi_prph_read(sc, WPI_BSM_WR_CTRL) &
    2865             :                     WPI_BSM_WR_CTRL_START))
    2866             :                         break;
    2867           0 :                 DELAY(10);
    2868             :         }
    2869           0 :         if (ntries == 1000) {
    2870           0 :                 printf("%s: could not load boot firmware\n",
    2871           0 :                     sc->sc_dev.dv_xname);
    2872           0 :                 wpi_nic_unlock(sc);
    2873           0 :                 return ETIMEDOUT;
    2874             :         }
    2875             : 
    2876             :         /* Enable boot after power up. */
    2877           0 :         wpi_prph_write(sc, WPI_BSM_WR_CTRL, WPI_BSM_WR_CTRL_START_EN);
    2878             : 
    2879           0 :         wpi_nic_unlock(sc);
    2880           0 :         return 0;
    2881           0 : }
    2882             : 
    2883             : int
    2884           0 : wpi_load_firmware(struct wpi_softc *sc)
    2885             : {
    2886           0 :         struct wpi_fw_info *fw = &sc->fw;
    2887           0 :         struct wpi_dma_info *dma = &sc->fw_dma;
    2888             :         int error;
    2889             : 
    2890             :         /* Copy initialization sections into pre-allocated DMA-safe memory. */
    2891           0 :         memcpy(dma->vaddr, fw->init.data, fw->init.datasz);
    2892           0 :         bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->init.datasz,
    2893             :             BUS_DMASYNC_PREWRITE);
    2894           0 :         memcpy(dma->vaddr + WPI_FW_DATA_MAXSZ,
    2895             :             fw->init.text, fw->init.textsz);
    2896           0 :         bus_dmamap_sync(sc->sc_dmat, dma->map, WPI_FW_DATA_MAXSZ,
    2897             :             fw->init.textsz, BUS_DMASYNC_PREWRITE);
    2898             : 
    2899             :         /* Tell adapter where to find initialization sections. */
    2900           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    2901           0 :                 return error;
    2902           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_DATA_ADDR, dma->paddr);
    2903           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_DATA_SIZE, fw->init.datasz);
    2904           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_ADDR,
    2905           0 :             dma->paddr + WPI_FW_DATA_MAXSZ);
    2906           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_SIZE, fw->init.textsz);
    2907           0 :         wpi_nic_unlock(sc);
    2908             : 
    2909             :         /* Load firmware boot code. */
    2910           0 :         error = wpi_load_bootcode(sc, fw->boot.text, fw->boot.textsz);
    2911           0 :         if (error != 0) {
    2912           0 :                 printf("%s: could not load boot firmware\n",
    2913           0 :                     sc->sc_dev.dv_xname);
    2914           0 :                 return error;
    2915             :         }
    2916             :         /* Now press "execute". */
    2917           0 :         WPI_WRITE(sc, WPI_RESET, 0);
    2918             : 
    2919             :         /* Wait at most one second for first alive notification. */
    2920           0 :         if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
    2921           0 :                 printf("%s: timeout waiting for adapter to initialize\n",
    2922           0 :                     sc->sc_dev.dv_xname);
    2923           0 :                 return error;
    2924             :         }
    2925             : 
    2926             :         /* Copy runtime sections into pre-allocated DMA-safe memory. */
    2927           0 :         memcpy(dma->vaddr, fw->main.data, fw->main.datasz);
    2928           0 :         bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->main.datasz,
    2929             :             BUS_DMASYNC_PREWRITE);
    2930           0 :         memcpy(dma->vaddr + WPI_FW_DATA_MAXSZ,
    2931             :             fw->main.text, fw->main.textsz);
    2932           0 :         bus_dmamap_sync(sc->sc_dmat, dma->map, WPI_FW_DATA_MAXSZ,
    2933             :             fw->main.textsz, BUS_DMASYNC_PREWRITE);
    2934             : 
    2935             :         /* Tell adapter where to find runtime sections. */
    2936           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    2937           0 :                 return error;
    2938           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_DATA_ADDR, dma->paddr);
    2939           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_DATA_SIZE, fw->main.datasz);
    2940           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_ADDR,
    2941           0 :             dma->paddr + WPI_FW_DATA_MAXSZ);
    2942           0 :         wpi_prph_write(sc, WPI_BSM_DRAM_TEXT_SIZE,
    2943           0 :             WPI_FW_UPDATED | fw->main.textsz);
    2944           0 :         wpi_nic_unlock(sc);
    2945             : 
    2946           0 :         return 0;
    2947           0 : }
    2948             : 
    2949             : int
    2950           0 : wpi_read_firmware(struct wpi_softc *sc)
    2951             : {
    2952           0 :         struct wpi_fw_info *fw = &sc->fw;
    2953             :         const struct wpi_firmware_hdr *hdr;
    2954             :         int error;
    2955             : 
    2956             :         /* Read firmware image from filesystem. */
    2957           0 :         if ((error = loadfirmware("wpi-3945abg", &fw->data, &fw->datalen)) != 0) {
    2958           0 :                 printf("%s: error, %d, could not read firmware %s\n",
    2959           0 :                     sc->sc_dev.dv_xname, error, "wpi-3945abg");
    2960           0 :                 return error;
    2961             :         }
    2962           0 :         if (fw->datalen < sizeof (*hdr)) {
    2963           0 :                 printf("%s: truncated firmware header: %zu bytes\n",
    2964           0 :                     sc->sc_dev.dv_xname, fw->datalen);
    2965           0 :                 free(fw->data, M_DEVBUF, fw->datalen);
    2966           0 :                 return EINVAL;
    2967             :         }
    2968             :         /* Extract firmware header information. */
    2969           0 :         hdr = (struct wpi_firmware_hdr *)fw->data;
    2970           0 :         fw->main.textsz = letoh32(hdr->main_textsz);
    2971           0 :         fw->main.datasz = letoh32(hdr->main_datasz);
    2972           0 :         fw->init.textsz = letoh32(hdr->init_textsz);
    2973           0 :         fw->init.datasz = letoh32(hdr->init_datasz);
    2974           0 :         fw->boot.textsz = letoh32(hdr->boot_textsz);
    2975           0 :         fw->boot.datasz = 0;
    2976             : 
    2977             :         /* Sanity-check firmware header. */
    2978           0 :         if (fw->main.textsz > WPI_FW_TEXT_MAXSZ ||
    2979           0 :             fw->main.datasz > WPI_FW_DATA_MAXSZ ||
    2980           0 :             fw->init.textsz > WPI_FW_TEXT_MAXSZ ||
    2981           0 :             fw->init.datasz > WPI_FW_DATA_MAXSZ ||
    2982           0 :             fw->boot.textsz > WPI_FW_BOOT_TEXT_MAXSZ ||
    2983           0 :             (fw->boot.textsz & 3) != 0) {
    2984           0 :                 printf("%s: invalid firmware header\n", sc->sc_dev.dv_xname);
    2985           0 :                 free(fw->data, M_DEVBUF, fw->datalen);
    2986           0 :                 return EINVAL;
    2987             :         }
    2988             : 
    2989             :         /* Check that all firmware sections fit. */
    2990           0 :         if (fw->datalen < sizeof (*hdr) + fw->main.textsz + fw->main.datasz +
    2991           0 :             fw->init.textsz + fw->init.datasz + fw->boot.textsz) {
    2992           0 :                 printf("%s: firmware file too short: %zu bytes\n",
    2993           0 :                     sc->sc_dev.dv_xname, fw->datalen);
    2994           0 :                 free(fw->data, M_DEVBUF, fw->datalen);
    2995           0 :                 return EINVAL;
    2996             :         }
    2997             : 
    2998             :         /* Get pointers to firmware sections. */
    2999           0 :         fw->main.text = (const uint8_t *)(hdr + 1);
    3000           0 :         fw->main.data = fw->main.text + fw->main.textsz;
    3001           0 :         fw->init.text = fw->main.data + fw->main.datasz;
    3002           0 :         fw->init.data = fw->init.text + fw->init.textsz;
    3003           0 :         fw->boot.text = fw->init.data + fw->init.datasz;
    3004             : 
    3005           0 :         return 0;
    3006           0 : }
    3007             : 
    3008             : int
    3009           0 : wpi_clock_wait(struct wpi_softc *sc)
    3010             : {
    3011             :         int ntries;
    3012             : 
    3013             :         /* Set "initialization complete" bit. */
    3014           0 :         WPI_SETBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_INIT_DONE);
    3015             : 
    3016             :         /* Wait for clock stabilization. */
    3017           0 :         for (ntries = 0; ntries < 25000; ntries++) {
    3018           0 :                 if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_MAC_CLOCK_READY)
    3019           0 :                         return 0;
    3020           0 :                 DELAY(100);
    3021             :         }
    3022           0 :         printf("%s: timeout waiting for clock stabilization\n",
    3023           0 :             sc->sc_dev.dv_xname);
    3024           0 :         return ETIMEDOUT;
    3025           0 : }
    3026             : 
    3027             : int
    3028           0 : wpi_apm_init(struct wpi_softc *sc)
    3029             : {
    3030             :         int error;
    3031             : 
    3032           0 :         WPI_SETBITS(sc, WPI_ANA_PLL, WPI_ANA_PLL_INIT);
    3033             :         /* Disable L0s. */
    3034           0 :         WPI_SETBITS(sc, WPI_GIO_CHICKEN, WPI_GIO_CHICKEN_L1A_NO_L0S_RX);
    3035             : 
    3036           0 :         if ((error = wpi_clock_wait(sc)) != 0)
    3037           0 :                 return error;
    3038             : 
    3039           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    3040           0 :                 return error;
    3041             :         /* Enable DMA. */
    3042           0 :         wpi_prph_write(sc, WPI_APMG_CLK_ENA,
    3043             :             WPI_APMG_CLK_DMA_CLK_RQT | WPI_APMG_CLK_BSM_CLK_RQT);
    3044           0 :         DELAY(20);
    3045             :         /* Disable L1. */
    3046           0 :         wpi_prph_setbits(sc, WPI_APMG_PCI_STT, WPI_APMG_PCI_STT_L1A_DIS);
    3047           0 :         wpi_nic_unlock(sc);
    3048             : 
    3049           0 :         return 0;
    3050           0 : }
    3051             : 
    3052             : void
    3053           0 : wpi_apm_stop_master(struct wpi_softc *sc)
    3054             : {
    3055             :         int ntries;
    3056             : 
    3057           0 :         WPI_SETBITS(sc, WPI_RESET, WPI_RESET_STOP_MASTER);
    3058             : 
    3059           0 :         if ((WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_PS_MASK) ==
    3060             :             WPI_GP_CNTRL_MAC_PS)
    3061           0 :                 return; /* Already asleep. */
    3062             : 
    3063           0 :         for (ntries = 0; ntries < 100; ntries++) {
    3064           0 :                 if (WPI_READ(sc, WPI_RESET) & WPI_RESET_MASTER_DISABLED)
    3065           0 :                         return;
    3066           0 :                 DELAY(10);
    3067             :         }
    3068           0 :         printf("%s: timeout waiting for master\n", sc->sc_dev.dv_xname);
    3069           0 : }
    3070             : 
    3071             : void
    3072           0 : wpi_apm_stop(struct wpi_softc *sc)
    3073             : {
    3074           0 :         wpi_apm_stop_master(sc);
    3075           0 :         WPI_SETBITS(sc, WPI_RESET, WPI_RESET_SW);
    3076           0 : }
    3077             : 
    3078             : void
    3079           0 : wpi_nic_config(struct wpi_softc *sc)
    3080             : {
    3081             :         pcireg_t reg;
    3082             :         uint8_t rev;
    3083             : 
    3084             :         /* Voodoo from the reference driver. */
    3085           0 :         reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_CLASS_REG);
    3086           0 :         rev = PCI_REVISION(reg);
    3087           0 :         if ((rev & 0xc0) == 0x40)
    3088           0 :                 WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_ALM_MB);
    3089           0 :         else if (!(rev & 0x80))
    3090           0 :                 WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_ALM_MM);
    3091             : 
    3092           0 :         if (sc->cap == 0x80)
    3093           0 :                 WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_SKU_MRC);
    3094             : 
    3095           0 :         if ((letoh16(sc->rev) & 0xf0) == 0xd0)
    3096           0 :                 WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_REV_D);
    3097             :         else
    3098           0 :                 WPI_CLRBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_REV_D);
    3099             : 
    3100           0 :         if (sc->type > 1)
    3101           0 :                 WPI_SETBITS(sc, WPI_HW_IF_CONFIG, WPI_HW_IF_CONFIG_TYPE_B);
    3102           0 : }
    3103             : 
    3104             : int
    3105           0 : wpi_hw_init(struct wpi_softc *sc)
    3106             : {
    3107             :         int chnl, ntries, error;
    3108             : 
    3109             :         /* Clear pending interrupts. */
    3110           0 :         WPI_WRITE(sc, WPI_INT, 0xffffffff);
    3111             : 
    3112           0 :         if ((error = wpi_apm_init(sc)) != 0) {
    3113           0 :                 printf("%s: could not power ON adapter\n",
    3114           0 :                     sc->sc_dev.dv_xname);
    3115           0 :                 return error;
    3116             :         }
    3117             : 
    3118             :         /* Select VMAIN power source. */
    3119           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    3120           0 :                 return error;
    3121           0 :         wpi_prph_clrbits(sc, WPI_APMG_PS, WPI_APMG_PS_PWR_SRC_MASK);
    3122           0 :         wpi_nic_unlock(sc);
    3123             :         /* Spin until VMAIN gets selected. */
    3124           0 :         for (ntries = 0; ntries < 5000; ntries++) {
    3125           0 :                 if (WPI_READ(sc, WPI_GPIO_IN) & WPI_GPIO_IN_VMAIN)
    3126             :                         break;
    3127           0 :                 DELAY(10);
    3128             :         }
    3129           0 :         if (ntries == 5000) {
    3130           0 :                 printf("%s: timeout selecting power source\n",
    3131           0 :                     sc->sc_dev.dv_xname);
    3132           0 :                 return ETIMEDOUT;
    3133             :         }
    3134             : 
    3135             :         /* Perform adapter initialization. */
    3136           0 :         (void)wpi_nic_config(sc);
    3137             : 
    3138             :         /* Initialize RX ring. */
    3139           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    3140           0 :                 return error;
    3141             :         /* Set physical address of RX ring. */
    3142           0 :         WPI_WRITE(sc, WPI_FH_RX_BASE, sc->rxq.desc_dma.paddr);
    3143             :         /* Set physical address of RX read pointer. */
    3144           0 :         WPI_WRITE(sc, WPI_FH_RX_RPTR_ADDR, sc->shared_dma.paddr +
    3145             :             offsetof(struct wpi_shared, next));
    3146           0 :         WPI_WRITE(sc, WPI_FH_RX_WPTR, 0);
    3147             :         /* Enable RX. */
    3148           0 :         WPI_WRITE(sc, WPI_FH_RX_CONFIG,
    3149             :             WPI_FH_RX_CONFIG_DMA_ENA |
    3150             :             WPI_FH_RX_CONFIG_RDRBD_ENA |
    3151             :             WPI_FH_RX_CONFIG_WRSTATUS_ENA |
    3152             :             WPI_FH_RX_CONFIG_MAXFRAG |
    3153             :             WPI_FH_RX_CONFIG_NRBD(WPI_RX_RING_COUNT_LOG) |
    3154             :             WPI_FH_RX_CONFIG_IRQ_DST_HOST |
    3155             :             WPI_FH_RX_CONFIG_IRQ_RBTH(1));
    3156           0 :         (void)WPI_READ(sc, WPI_FH_RSSR_TBL);    /* barrier */
    3157           0 :         WPI_WRITE(sc, WPI_FH_RX_WPTR, (WPI_RX_RING_COUNT - 1) & ~7);
    3158           0 :         wpi_nic_unlock(sc);
    3159             : 
    3160             :         /* Initialize TX rings. */
    3161           0 :         if ((error = wpi_nic_lock(sc)) != 0)
    3162           0 :                 return error;
    3163           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_MODE, 2);      /* bypass mode */
    3164           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_ARASTAT, 1);   /* enable RA0 */
    3165             :         /* Enable all 6 TX rings. */
    3166           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_TXFACT, 0x3f);
    3167           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_SBYPASS_MODE1, 0x10000);
    3168           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_SBYPASS_MODE2, 0x30002);
    3169           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_TXF4MF, 4);
    3170           0 :         wpi_prph_write(sc, WPI_ALM_SCHED_TXF5MF, 5);
    3171             :         /* Set physical address of TX rings. */
    3172           0 :         WPI_WRITE(sc, WPI_FH_TX_BASE, sc->shared_dma.paddr);
    3173           0 :         WPI_WRITE(sc, WPI_FH_MSG_CONFIG, 0xffff05a5);
    3174             : 
    3175             :         /* Enable all DMA channels. */
    3176           0 :         for (chnl = 0; chnl < WPI_NDMACHNLS; chnl++) {
    3177           0 :                 WPI_WRITE(sc, WPI_FH_CBBC_CTRL(chnl), 0);
    3178           0 :                 WPI_WRITE(sc, WPI_FH_CBBC_BASE(chnl), 0);
    3179           0 :                 WPI_WRITE(sc, WPI_FH_TX_CONFIG(chnl), 0x80200008);
    3180             :         }
    3181           0 :         wpi_nic_unlock(sc);
    3182           0 :         (void)WPI_READ(sc, WPI_FH_TX_BASE);     /* barrier */
    3183             : 
    3184             :         /* Clear "radio off" and "commands blocked" bits. */
    3185           0 :         WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL);
    3186           0 :         WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_CMD_BLOCKED);
    3187             : 
    3188             :         /* Clear pending interrupts. */
    3189           0 :         WPI_WRITE(sc, WPI_INT, 0xffffffff);
    3190             :         /* Enable interrupts. */
    3191           0 :         WPI_WRITE(sc, WPI_MASK, WPI_INT_MASK);
    3192             : 
    3193             :         /* _Really_ make sure "radio off" bit is cleared! */
    3194           0 :         WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL);
    3195           0 :         WPI_WRITE(sc, WPI_UCODE_GP1_CLR, WPI_UCODE_GP1_RFKILL);
    3196             : 
    3197           0 :         if ((error = wpi_load_firmware(sc)) != 0) {
    3198           0 :                 printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
    3199           0 :                 return error;
    3200             :         }
    3201             :         /* Wait at most one second for firmware alive notification. */
    3202           0 :         if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
    3203           0 :                 printf("%s: timeout waiting for adapter to initialize\n",
    3204           0 :                     sc->sc_dev.dv_xname);
    3205           0 :                 return error;
    3206             :         }
    3207             :         /* Do post-firmware initialization. */
    3208           0 :         return wpi_post_alive(sc);
    3209           0 : }
    3210             : 
    3211             : void
    3212           0 : wpi_hw_stop(struct wpi_softc *sc)
    3213             : {
    3214             :         int chnl, qid, ntries;
    3215             :         uint32_t tmp;
    3216             : 
    3217           0 :         WPI_WRITE(sc, WPI_RESET, WPI_RESET_NEVO);
    3218             : 
    3219             :         /* Disable interrupts. */
    3220           0 :         WPI_WRITE(sc, WPI_MASK, 0);
    3221           0 :         WPI_WRITE(sc, WPI_INT, 0xffffffff);
    3222           0 :         WPI_WRITE(sc, WPI_FH_INT, 0xffffffff);
    3223             : 
    3224             :         /* Make sure we no longer hold the NIC lock. */
    3225           0 :         wpi_nic_unlock(sc);
    3226             : 
    3227           0 :         if (wpi_nic_lock(sc) == 0) {
    3228             :                 /* Stop TX scheduler. */
    3229           0 :                 wpi_prph_write(sc, WPI_ALM_SCHED_MODE, 0);
    3230           0 :                 wpi_prph_write(sc, WPI_ALM_SCHED_TXFACT, 0);
    3231             : 
    3232             :                 /* Stop all DMA channels. */
    3233           0 :                 for (chnl = 0; chnl < WPI_NDMACHNLS; chnl++) {
    3234           0 :                         WPI_WRITE(sc, WPI_FH_TX_CONFIG(chnl), 0);
    3235           0 :                         for (ntries = 0; ntries < 100; ntries++) {
    3236           0 :                                 tmp = WPI_READ(sc, WPI_FH_TX_STATUS);
    3237           0 :                                 if ((tmp & WPI_FH_TX_STATUS_IDLE(chnl)) ==
    3238             :                                     WPI_FH_TX_STATUS_IDLE(chnl))
    3239             :                                         break;
    3240           0 :                                 DELAY(10);
    3241             :                         }
    3242             :                 }
    3243           0 :                 wpi_nic_unlock(sc);
    3244           0 :         }
    3245             : 
    3246             :         /* Stop RX ring. */
    3247           0 :         wpi_reset_rx_ring(sc, &sc->rxq);
    3248             : 
    3249             :         /* Reset all TX rings. */
    3250           0 :         for (qid = 0; qid < WPI_NTXQUEUES; qid++)
    3251           0 :                 wpi_reset_tx_ring(sc, &sc->txq[qid]);
    3252             : 
    3253           0 :         if (wpi_nic_lock(sc) == 0) {
    3254           0 :                 wpi_prph_write(sc, WPI_APMG_CLK_DIS, WPI_APMG_CLK_DMA_CLK_RQT);
    3255           0 :                 wpi_nic_unlock(sc);
    3256           0 :         }
    3257           0 :         DELAY(5);
    3258             :         /* Power OFF adapter. */
    3259           0 :         wpi_apm_stop(sc);
    3260           0 : }
    3261             : 
    3262             : int
    3263           0 : wpi_init(struct ifnet *ifp)
    3264             : {
    3265           0 :         struct wpi_softc *sc = ifp->if_softc;
    3266           0 :         struct ieee80211com *ic = &sc->sc_ic;
    3267             :         int error;
    3268             : 
    3269             : #ifdef notyet
    3270             :         /* Check that the radio is not disabled by hardware switch. */
    3271             :         if (!(WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL)) {
    3272             :                 printf("%s: radio is disabled by hardware switch\n",
    3273             :                     sc->sc_dev.dv_xname);
    3274             :                 error = EPERM;  /* :-) */
    3275             :                 goto fail;
    3276             :         }
    3277             : #endif
    3278             :         /* Read firmware images from the filesystem. */
    3279           0 :         if ((error = wpi_read_firmware(sc)) != 0) {
    3280           0 :                 printf("%s: could not read firmware\n", sc->sc_dev.dv_xname);
    3281           0 :                 goto fail;
    3282             :         }
    3283             : 
    3284             :         /* Initialize hardware and upload firmware. */
    3285           0 :         error = wpi_hw_init(sc);
    3286           0 :         free(sc->fw.data, M_DEVBUF, sc->fw.datalen);
    3287           0 :         if (error != 0) {
    3288           0 :                 printf("%s: could not initialize hardware\n",
    3289           0 :                     sc->sc_dev.dv_xname);
    3290           0 :                 goto fail;
    3291             :         }
    3292             : 
    3293             :         /* Configure adapter now that it is ready. */
    3294           0 :         if ((error = wpi_config(sc)) != 0) {
    3295           0 :                 printf("%s: could not configure device\n",
    3296           0 :                     sc->sc_dev.dv_xname);
    3297           0 :                 goto fail;
    3298             :         }
    3299             : 
    3300           0 :         ifq_clr_oactive(&ifp->if_snd);
    3301           0 :         ifp->if_flags |= IFF_RUNNING;
    3302             : 
    3303           0 :         if (ic->ic_opmode != IEEE80211_M_MONITOR)
    3304           0 :                 ieee80211_begin_scan(ifp);
    3305             :         else
    3306           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    3307             : 
    3308           0 :         return 0;
    3309             : 
    3310           0 : fail:   wpi_stop(ifp, 1);
    3311           0 :         return error;
    3312           0 : }
    3313             : 
    3314             : void
    3315           0 : wpi_stop(struct ifnet *ifp, int disable)
    3316             : {
    3317           0 :         struct wpi_softc *sc = ifp->if_softc;
    3318           0 :         struct ieee80211com *ic = &sc->sc_ic;
    3319             : 
    3320           0 :         ifp->if_timer = sc->sc_tx_timer = 0;
    3321           0 :         ifp->if_flags &= ~IFF_RUNNING;
    3322           0 :         ifq_clr_oactive(&ifp->if_snd);
    3323             : 
    3324           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    3325             : 
    3326             :         /* Power OFF hardware. */
    3327           0 :         wpi_hw_stop(sc);
    3328           0 : }

Generated by: LCOV version 1.13