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

          Line data    Source code
       1             : /*      $OpenBSD: if_iwi.c,v 1.138 2018/04/26 12:50:07 pirofti Exp $    */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2004-2008
       5             :  *      Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
       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 2200BG/2915ABG 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/conf.h>
      34             : #include <sys/device.h>
      35             : #include <sys/task.h>
      36             : #include <sys/endian.h>
      37             : 
      38             : #include <machine/bus.h>
      39             : #include <machine/intr.h>
      40             : 
      41             : #include <dev/pci/pcireg.h>
      42             : #include <dev/pci/pcivar.h>
      43             : #include <dev/pci/pcidevs.h>
      44             : 
      45             : #if NBPFILTER > 0
      46             : #include <net/bpf.h>
      47             : #endif
      48             : #include <net/if.h>
      49             : #include <net/if_dl.h>
      50             : #include <net/if_media.h>
      51             : 
      52             : #include <netinet/in.h>
      53             : #include <netinet/if_ether.h>
      54             : 
      55             : #include <net80211/ieee80211_var.h>
      56             : #include <net80211/ieee80211_radiotap.h>
      57             : 
      58             : #include <dev/pci/if_iwireg.h>
      59             : #include <dev/pci/if_iwivar.h>
      60             : 
      61             : const struct pci_matchid iwi_devices[] = {
      62             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2200BG },
      63             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2225BG },
      64             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2915ABG_1 },
      65             :         { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2915ABG_2 }
      66             : };
      67             : 
      68             : int             iwi_match(struct device *, void *, void *);
      69             : void            iwi_attach(struct device *, struct device *, void *);
      70             : int             iwi_activate(struct device *, int);
      71             : void            iwi_wakeup(struct iwi_softc *);
      72             : void            iwi_init_task(void *);
      73             : int             iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
      74             : void            iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
      75             : void            iwi_free_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
      76             : int             iwi_alloc_tx_ring(struct iwi_softc *, struct iwi_tx_ring *,
      77             :                     int);
      78             : void            iwi_reset_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
      79             : void            iwi_free_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
      80             : int             iwi_alloc_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
      81             : void            iwi_reset_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
      82             : void            iwi_free_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
      83             : int             iwi_media_change(struct ifnet *);
      84             : void            iwi_media_status(struct ifnet *, struct ifmediareq *);
      85             : uint16_t        iwi_read_prom_word(struct iwi_softc *, uint8_t);
      86             : int             iwi_find_txnode(struct iwi_softc *, const uint8_t *);
      87             : int             iwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
      88             : uint8_t         iwi_rate(int);
      89             : void            iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *,
      90             :                     struct iwi_frame *);
      91             : void            iwi_notification_intr(struct iwi_softc *, struct iwi_rx_data *,
      92             :                     struct iwi_notif *);
      93             : void            iwi_rx_intr(struct iwi_softc *);
      94             : void            iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
      95             : int             iwi_intr(void *);
      96             : int             iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t, int);
      97             : int             iwi_send_mgmt(struct ieee80211com *, struct ieee80211_node *,
      98             :                     int, int, int);
      99             : int             iwi_tx_start(struct ifnet *, struct mbuf *,
     100             :                     struct ieee80211_node *);
     101             : void            iwi_start(struct ifnet *);
     102             : void            iwi_watchdog(struct ifnet *);
     103             : int             iwi_ioctl(struct ifnet *, u_long, caddr_t);
     104             : void            iwi_stop_master(struct iwi_softc *);
     105             : int             iwi_reset(struct iwi_softc *);
     106             : int             iwi_load_ucode(struct iwi_softc *, const char *, int);
     107             : int             iwi_load_firmware(struct iwi_softc *, const char *, int);
     108             : int             iwi_config(struct iwi_softc *);
     109             : void            iwi_update_edca(struct ieee80211com *);
     110             : int             iwi_set_chan(struct iwi_softc *, struct ieee80211_channel *);
     111             : int             iwi_scan(struct iwi_softc *);
     112             : int             iwi_auth_and_assoc(struct iwi_softc *);
     113             : int             iwi_init(struct ifnet *);
     114             : void            iwi_stop(struct ifnet *, int);
     115             : 
     116             : static __inline uint8_t
     117           0 : MEM_READ_1(struct iwi_softc *sc, uint32_t addr)
     118             : {
     119           0 :         CSR_WRITE_4(sc, IWI_CSR_INDIRECT_ADDR, addr);
     120           0 :         return CSR_READ_1(sc, IWI_CSR_INDIRECT_DATA);
     121             : }
     122             : 
     123             : static __inline uint32_t
     124           0 : MEM_READ_4(struct iwi_softc *sc, uint32_t addr)
     125             : {
     126           0 :         CSR_WRITE_4(sc, IWI_CSR_INDIRECT_ADDR, addr);
     127           0 :         return CSR_READ_4(sc, IWI_CSR_INDIRECT_DATA);
     128             : }
     129             : 
     130             : #ifdef IWI_DEBUG
     131             : #define DPRINTF(x)      do { if (iwi_debug > 0) printf x; } while (0)
     132             : #define DPRINTFN(n, x)  do { if (iwi_debug >= (n)) printf x; } while (0)
     133             : int iwi_debug = 0;
     134             : #else
     135             : #define DPRINTF(x)
     136             : #define DPRINTFN(n, x)
     137             : #endif
     138             : 
     139             : struct cfattach iwi_ca = {
     140             :         sizeof (struct iwi_softc), iwi_match, iwi_attach, NULL,
     141             :         iwi_activate
     142             : };
     143             : 
     144             : int
     145           0 : iwi_match(struct device *parent, void *match, void *aux)
     146             : {
     147           0 :         return pci_matchbyid((struct pci_attach_args *)aux, iwi_devices,
     148             :             nitems(iwi_devices));
     149             : }
     150             : 
     151             : /* Base Address Register */
     152             : #define IWI_PCI_BAR0    0x10
     153             : 
     154             : void
     155           0 : iwi_attach(struct device *parent, struct device *self, void *aux)
     156             : {
     157           0 :         struct iwi_softc *sc = (struct iwi_softc *)self;
     158           0 :         struct ieee80211com *ic = &sc->sc_ic;
     159           0 :         struct ifnet *ifp = &ic->ic_if;
     160           0 :         struct pci_attach_args *pa = aux;
     161             :         const char *intrstr;
     162           0 :         bus_space_tag_t memt;
     163           0 :         bus_space_handle_t memh;
     164           0 :         pci_intr_handle_t ih;
     165             :         pcireg_t data;
     166             :         uint16_t val;
     167             :         int error, ac, i;
     168             : 
     169           0 :         sc->sc_pct = pa->pa_pc;
     170           0 :         sc->sc_pcitag = pa->pa_tag;
     171             : 
     172             :         /* clear device specific PCI configuration register 0x41 */
     173           0 :         data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
     174           0 :         data &= ~0x0000ff00;
     175           0 :         pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
     176             : 
     177             :         /* map the register window */
     178           0 :         error = pci_mapreg_map(pa, IWI_PCI_BAR0, PCI_MAPREG_TYPE_MEM |
     179           0 :             PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &sc->sc_sz, 0);
     180           0 :         if (error != 0) {
     181           0 :                 printf(": can't map mem space\n");
     182           0 :                 return;
     183             :         }
     184             : 
     185           0 :         sc->sc_st = memt;
     186           0 :         sc->sc_sh = memh;
     187           0 :         sc->sc_dmat = pa->pa_dmat;
     188             : 
     189           0 :         if (pci_intr_map(pa, &ih) != 0) {
     190           0 :                 printf(": can't map interrupt\n");
     191           0 :                 return;
     192             :         }
     193             : 
     194           0 :         intrstr = pci_intr_string(sc->sc_pct, ih);
     195           0 :         sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwi_intr, sc,
     196           0 :             sc->sc_dev.dv_xname);
     197           0 :         if (sc->sc_ih == NULL) {
     198           0 :                 printf(": can't establish interrupt");
     199           0 :                 if (intrstr != NULL)
     200           0 :                         printf(" at %s", intrstr);
     201           0 :                 printf("\n");
     202           0 :                 return;
     203             :         }
     204           0 :         printf(": %s", intrstr);
     205             : 
     206           0 :         if (iwi_reset(sc) != 0) {
     207           0 :                 printf(": could not reset adapter\n");
     208           0 :                 return;
     209             :         }
     210             : 
     211             :         /*
     212             :          * Allocate rings.
     213             :          */
     214           0 :         if (iwi_alloc_cmd_ring(sc, &sc->cmdq) != 0) {
     215           0 :                 printf(": could not allocate Cmd ring\n");
     216           0 :                 return;
     217             :         }
     218           0 :         for (ac = 0; ac < EDCA_NUM_AC; ac++) {
     219           0 :                 if (iwi_alloc_tx_ring(sc, &sc->txq[ac], ac) != 0) {
     220           0 :                         printf(": could not allocate Tx ring %d\n", ac);
     221           0 :                         goto fail;
     222             :                 }
     223             :         }
     224           0 :         if (iwi_alloc_rx_ring(sc, &sc->rxq) != 0) {
     225           0 :                 printf(": could not allocate Rx ring\n");
     226           0 :                 goto fail;
     227             :         }
     228             : 
     229           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     230           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     231           0 :         ic->ic_state = IEEE80211_S_INIT;
     232             : 
     233             :         /* set device capabilities */
     234           0 :         ic->ic_caps =
     235             : #ifndef IEEE80211_STA_ONLY
     236             :             IEEE80211_C_IBSS |          /* IBSS mode supported */
     237             : #endif
     238             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     239             :             IEEE80211_C_TXPMGT |        /* tx power management */
     240             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     241             :             IEEE80211_C_SHSLOT |        /* short slot time supported */
     242             :             IEEE80211_C_WEP |           /* s/w WEP */
     243             :             IEEE80211_C_RSN |           /* WPA/RSN supported */
     244             :             IEEE80211_C_SCANALL;        /* h/w scanning */
     245             : 
     246             :         /* read MAC address from EEPROM */
     247           0 :         val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
     248           0 :         ic->ic_myaddr[0] = val & 0xff;
     249           0 :         ic->ic_myaddr[1] = val >> 8;
     250           0 :         val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
     251           0 :         ic->ic_myaddr[2] = val & 0xff;
     252           0 :         ic->ic_myaddr[3] = val >> 8;
     253           0 :         val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
     254           0 :         ic->ic_myaddr[4] = val & 0xff;
     255           0 :         ic->ic_myaddr[5] = val >> 8;
     256             : 
     257           0 :         printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
     258             : 
     259           0 :         if (PCI_PRODUCT(pa->pa_id) >= PCI_PRODUCT_INTEL_PRO_WL_2915ABG_1) {
     260             :                 /* set supported .11a rates */
     261           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11A] =
     262           0 :                     ieee80211_std_rateset_11a;
     263             : 
     264             :                 /* set supported .11a channels */
     265           0 :                 for (i = 36; i <= 64; i += 4) {
     266           0 :                         ic->ic_channels[i].ic_freq =
     267           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     268           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     269             :                 }
     270           0 :                 for (i = 149; i <= 165; i += 4) {
     271           0 :                         ic->ic_channels[i].ic_freq =
     272           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     273           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     274             :                 }
     275             :         }
     276             : 
     277             :         /* set supported .11b and .11g rates */
     278           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     279           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     280             : 
     281             :         /* set supported .11b and .11g channels (1 through 14) */
     282           0 :         for (i = 1; i <= 14; i++) {
     283           0 :                 ic->ic_channels[i].ic_freq =
     284           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     285           0 :                 ic->ic_channels[i].ic_flags =
     286             :                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     287             :                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     288             :         }
     289             : 
     290             :         /* IBSS channel undefined for now */
     291           0 :         ic->ic_ibss_chan = &ic->ic_channels[0];
     292             : 
     293           0 :         ifp->if_softc = sc;
     294           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     295           0 :         ifp->if_ioctl = iwi_ioctl;
     296           0 :         ifp->if_start = iwi_start;
     297           0 :         ifp->if_watchdog = iwi_watchdog;
     298           0 :         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
     299             : 
     300           0 :         if_attach(ifp);
     301           0 :         ieee80211_ifattach(ifp);
     302             :         /* override state transition machine */
     303           0 :         sc->sc_newstate = ic->ic_newstate;
     304           0 :         ic->ic_newstate = iwi_newstate;
     305           0 :         ic->ic_send_mgmt = iwi_send_mgmt;
     306           0 :         ieee80211_media_init(ifp, iwi_media_change, iwi_media_status);
     307             : 
     308             : #if NBPFILTER > 0
     309           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     310             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     311             : 
     312           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     313           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     314           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(IWI_RX_RADIOTAP_PRESENT);
     315             : 
     316           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     317           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     318           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(IWI_TX_RADIOTAP_PRESENT);
     319             : #endif
     320             : 
     321           0 :         rw_init(&sc->sc_rwlock, "iwilock");
     322           0 :         task_set(&sc->init_task, iwi_init_task, sc);
     323           0 :         return;
     324             : 
     325           0 : fail:   while (--ac >= 0)
     326           0 :                 iwi_free_tx_ring(sc, &sc->txq[ac]);
     327           0 :         iwi_free_cmd_ring(sc, &sc->cmdq);
     328           0 : }
     329             : 
     330             : int
     331           0 : iwi_activate(struct device *self, int act)
     332             : {
     333           0 :         struct iwi_softc *sc = (struct iwi_softc *)self;
     334           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     335             : 
     336           0 :         switch (act) {
     337             :         case DVACT_SUSPEND:
     338           0 :                 if (ifp->if_flags & IFF_RUNNING)
     339           0 :                         iwi_stop(ifp, 0);
     340             :                 break;
     341             :         case DVACT_WAKEUP:
     342           0 :                 iwi_wakeup(sc);
     343           0 :                 break;
     344             :         }
     345             : 
     346           0 :         return 0;
     347             : }
     348             : 
     349             : void
     350           0 : iwi_wakeup(struct iwi_softc *sc)
     351             : {
     352             :         pcireg_t data;
     353             : 
     354             :         /* clear device specific PCI configuration register 0x41 */
     355           0 :         data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
     356           0 :         data &= ~0x0000ff00;
     357           0 :         pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
     358             : 
     359           0 :         iwi_init_task(sc);
     360           0 : }
     361             : 
     362             : void
     363           0 : iwi_init_task(void *arg1)
     364             : {
     365           0 :         struct iwi_softc *sc = arg1;
     366           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     367             :         int s;
     368             : 
     369           0 :         rw_enter_write(&sc->sc_rwlock);
     370           0 :         s = splnet();
     371             : 
     372           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
     373           0 :                 iwi_init(ifp);
     374             : 
     375           0 :         splx(s);
     376           0 :         rw_exit_write(&sc->sc_rwlock);
     377           0 : }
     378             : 
     379             : int
     380           0 : iwi_alloc_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
     381             : {
     382           0 :         int nsegs, error;
     383             : 
     384           0 :         ring->queued = 0;
     385           0 :         ring->cur = ring->next = 0;
     386             : 
     387           0 :         error = bus_dmamap_create(sc->sc_dmat,
     388             :             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT, 1,
     389             :             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT, 0,
     390             :             BUS_DMA_NOWAIT, &ring->map);
     391           0 :         if (error != 0) {
     392           0 :                 printf("%s: could not create cmd ring DMA map\n",
     393           0 :                     sc->sc_dev.dv_xname);
     394           0 :                 goto fail;
     395             :         }
     396             : 
     397           0 :         error = bus_dmamem_alloc(sc->sc_dmat,
     398             :             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT, PAGE_SIZE, 0,
     399             :             &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
     400           0 :         if (error != 0) {
     401           0 :                 printf("%s: could not allocate cmd ring DMA memory\n",
     402           0 :                     sc->sc_dev.dv_xname);
     403           0 :                 goto fail;
     404             :         }
     405             : 
     406           0 :         error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
     407             :             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT,
     408             :             (caddr_t *)&ring->desc, BUS_DMA_NOWAIT);
     409           0 :         if (error != 0) {
     410           0 :                 printf("%s: can't map cmd ring DMA memory\n",
     411           0 :                     sc->sc_dev.dv_xname);
     412           0 :                 goto fail;
     413             :         }
     414             : 
     415           0 :         error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
     416             :             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT, NULL,
     417             :             BUS_DMA_NOWAIT);
     418           0 :         if (error != 0) {
     419           0 :                 printf("%s: could not load cmd ring DMA map\n",
     420           0 :                     sc->sc_dev.dv_xname);
     421           0 :                 goto fail;
     422             :         }
     423             : 
     424           0 :         return 0;
     425             : 
     426           0 : fail:   iwi_free_cmd_ring(sc, ring);
     427           0 :         return error;
     428           0 : }
     429             : 
     430             : void
     431           0 : iwi_reset_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
     432             : {
     433           0 :         ring->queued = 0;
     434           0 :         ring->cur = ring->next = 0;
     435           0 : }
     436             : 
     437             : void
     438           0 : iwi_free_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
     439             : {
     440           0 :         if (ring->map != NULL) {
     441           0 :                 if (ring->desc != NULL) {
     442           0 :                         bus_dmamap_unload(sc->sc_dmat, ring->map);
     443           0 :                         bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
     444             :                             sizeof (struct iwi_cmd_desc) * IWI_CMD_RING_COUNT);
     445           0 :                         bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
     446           0 :                 }
     447           0 :                 bus_dmamap_destroy(sc->sc_dmat, ring->map);
     448           0 :         }
     449           0 : }
     450             : 
     451             : int
     452           0 : iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring, int ac)
     453             : {
     454             :         struct iwi_tx_data *data;
     455           0 :         int i, nsegs, error;
     456             : 
     457           0 :         ring->queued = 0;
     458           0 :         ring->cur = ring->next = 0;
     459           0 :         ring->csr_ridx = IWI_CSR_TX_RIDX(ac);
     460           0 :         ring->csr_widx = IWI_CSR_TX_WIDX(ac);
     461             : 
     462           0 :         error = bus_dmamap_create(sc->sc_dmat,
     463             :             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT, 1,
     464             :             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT, 0, BUS_DMA_NOWAIT,
     465             :             &ring->map);
     466           0 :         if (error != 0) {
     467           0 :                 printf("%s: could not create tx ring DMA map\n",
     468           0 :                     sc->sc_dev.dv_xname);
     469           0 :                 goto fail;
     470             :         }
     471             : 
     472           0 :         error = bus_dmamem_alloc(sc->sc_dmat,
     473             :             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT, PAGE_SIZE, 0,
     474             :             &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
     475           0 :         if (error != 0) {
     476           0 :                 printf("%s: could not allocate tx ring DMA memory\n",
     477           0 :                     sc->sc_dev.dv_xname);
     478           0 :                 goto fail;
     479             :         }
     480             : 
     481           0 :         error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
     482             :             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT,
     483             :             (caddr_t *)&ring->desc, BUS_DMA_NOWAIT);
     484           0 :         if (error != 0) {
     485           0 :                 printf("%s: can't map tx ring DMA memory\n",
     486           0 :                     sc->sc_dev.dv_xname);
     487           0 :                 goto fail;
     488             :         }
     489             : 
     490           0 :         error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
     491             :             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT, NULL,
     492             :             BUS_DMA_NOWAIT);
     493           0 :         if (error != 0) {
     494           0 :                 printf("%s: could not load tx ring DMA map\n",
     495           0 :                     sc->sc_dev.dv_xname);
     496           0 :                 goto fail;
     497             :         }
     498             : 
     499           0 :         for (i = 0; i < IWI_TX_RING_COUNT; i++) {
     500           0 :                 data = &ring->data[i];
     501             : 
     502           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
     503             :                     IWI_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT, &data->map);
     504           0 :                 if (error != 0) {
     505           0 :                         printf("%s: could not create tx buf DMA map\n",
     506           0 :                             sc->sc_dev.dv_xname);
     507           0 :                         goto fail;
     508             :                 }
     509             :         }
     510             : 
     511           0 :         return 0;
     512             : 
     513           0 : fail:   iwi_free_tx_ring(sc, ring);
     514           0 :         return error;
     515           0 : }
     516             : 
     517             : void
     518           0 : iwi_reset_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring)
     519             : {
     520             :         struct iwi_tx_data *data;
     521             :         int i;
     522             : 
     523           0 :         for (i = 0; i < IWI_TX_RING_COUNT; i++) {
     524           0 :                 data = &ring->data[i];
     525             : 
     526           0 :                 if (data->m != NULL) {
     527           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     528           0 :                         m_freem(data->m);
     529           0 :                         data->m = NULL;
     530           0 :                 }
     531             :         }
     532             : 
     533           0 :         ring->queued = 0;
     534           0 :         ring->cur = ring->next = 0;
     535           0 : }
     536             : 
     537             : void
     538           0 : iwi_free_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring)
     539             : {
     540             :         struct iwi_tx_data *data;
     541             :         int i;
     542             : 
     543           0 :         if (ring->map != NULL) {
     544           0 :                 if (ring->desc != NULL) {
     545           0 :                         bus_dmamap_unload(sc->sc_dmat, ring->map);
     546           0 :                         bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
     547             :                             sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT);
     548           0 :                         bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
     549           0 :                 }
     550           0 :                 bus_dmamap_destroy(sc->sc_dmat, ring->map);
     551           0 :         }
     552             : 
     553           0 :         for (i = 0; i < IWI_TX_RING_COUNT; i++) {
     554           0 :                 data = &ring->data[i];
     555             : 
     556           0 :                 if (data->m != NULL) {
     557           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     558           0 :                         m_freem(data->m);
     559           0 :                 }
     560           0 :                 bus_dmamap_destroy(sc->sc_dmat, data->map);
     561             :         }
     562           0 : }
     563             : 
     564             : int
     565           0 : iwi_alloc_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring)
     566             : {
     567             :         struct iwi_rx_data *data;
     568             :         int i, error;
     569             : 
     570           0 :         ring->cur = 0;
     571             : 
     572           0 :         for (i = 0; i < IWI_RX_RING_COUNT; i++) {
     573           0 :                 data = &sc->rxq.data[i];
     574             : 
     575           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
     576             :                     0, BUS_DMA_NOWAIT, &data->map);
     577           0 :                 if (error != 0) {
     578           0 :                         printf("%s: could not create rx buf DMA map\n",
     579           0 :                             sc->sc_dev.dv_xname);
     580           0 :                         goto fail;
     581             :                 }
     582             : 
     583           0 :                 MGETHDR(data->m, M_DONTWAIT, MT_DATA);
     584           0 :                 if (data->m == NULL) {
     585           0 :                         printf("%s: could not allocate rx mbuf\n",
     586           0 :                             sc->sc_dev.dv_xname);
     587             :                         error = ENOMEM;
     588           0 :                         goto fail;
     589             :                 }
     590           0 :                 MCLGET(data->m, M_DONTWAIT);
     591           0 :                 if (!(data->m->m_flags & M_EXT)) {
     592           0 :                         m_freem(data->m);
     593           0 :                         data->m = NULL;
     594           0 :                         printf("%s: could not allocate rx mbuf cluster\n",
     595           0 :                             sc->sc_dev.dv_xname);
     596             :                         error = ENOMEM;
     597           0 :                         goto fail;
     598             :                 }
     599             : 
     600           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
     601             :                     mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
     602           0 :                 if (error != 0) {
     603           0 :                         printf("%s: could not load rx buf DMA map\n",
     604           0 :                             sc->sc_dev.dv_xname);
     605           0 :                         goto fail;
     606             :                 }
     607             : 
     608           0 :                 data->reg = IWI_CSR_RX_BASE + i * 4;
     609             :         }
     610             : 
     611           0 :         return 0;
     612             : 
     613           0 : fail:   iwi_free_rx_ring(sc, ring);
     614           0 :         return error;
     615           0 : }
     616             : 
     617             : void
     618           0 : iwi_reset_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring)
     619             : {
     620           0 :         ring->cur = 0;
     621           0 : }
     622             : 
     623             : void
     624           0 : iwi_free_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring)
     625             : {
     626             :         struct iwi_rx_data *data;
     627             :         int i;
     628             : 
     629           0 :         for (i = 0; i < IWI_RX_RING_COUNT; i++) {
     630           0 :                 data = &sc->rxq.data[i];
     631             : 
     632           0 :                 if (data->m != NULL) {
     633           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     634           0 :                         m_freem(data->m);
     635           0 :                 }
     636           0 :                 bus_dmamap_destroy(sc->sc_dmat, data->map);
     637             :         }
     638           0 : }
     639             : 
     640             : int
     641           0 : iwi_media_change(struct ifnet *ifp)
     642             : {
     643             :         int error;
     644             : 
     645           0 :         error = ieee80211_media_change(ifp);
     646           0 :         if (error != ENETRESET)
     647           0 :                 return error;
     648             : 
     649           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
     650           0 :                 iwi_init(ifp);
     651             : 
     652           0 :         return 0;
     653           0 : }
     654             : 
     655             : void
     656           0 : iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
     657             : {
     658           0 :         struct iwi_softc *sc = ifp->if_softc;
     659           0 :         struct ieee80211com *ic = &sc->sc_ic;
     660             :         uint32_t val;
     661             :         int rate;
     662             : 
     663           0 :         imr->ifm_status = IFM_AVALID;
     664           0 :         imr->ifm_active = IFM_IEEE80211;
     665           0 :         if (ic->ic_state == IEEE80211_S_RUN)
     666           0 :                 imr->ifm_status |= IFM_ACTIVE;
     667             : 
     668             :         /* read current transmission rate from adapter */
     669           0 :         val = CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE);
     670             :         /* convert PLCP signal to 802.11 rate */
     671           0 :         rate = iwi_rate(val);
     672             : 
     673           0 :         imr->ifm_active |= ieee80211_rate2media(ic, rate, ic->ic_curmode);
     674           0 :         switch (ic->ic_opmode) {
     675             :         case IEEE80211_M_STA:
     676             :                 break;
     677             : #ifndef IEEE80211_STA_ONLY
     678             :         case IEEE80211_M_IBSS:
     679           0 :                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
     680           0 :                 break;
     681             : #endif
     682             :         case IEEE80211_M_MONITOR:
     683           0 :                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
     684           0 :                 break;
     685             :         default:
     686             :                 /* should not get there */
     687             :                 break;
     688             :         }
     689           0 : }
     690             : 
     691             : #ifndef IEEE80211_STA_ONLY
     692             : /*
     693             :  * This is only used for IBSS mode where the firmware expect an index to an
     694             :  * internal node table instead of a destination address.
     695             :  */
     696             : int
     697           0 : iwi_find_txnode(struct iwi_softc *sc, const uint8_t *macaddr)
     698             : {
     699           0 :         struct iwi_node node;
     700             :         int i;
     701             : 
     702           0 :         for (i = 0; i < sc->nsta; i++)
     703           0 :                 if (IEEE80211_ADDR_EQ(sc->sta[i], macaddr))
     704           0 :                         return i;       /* already existing node */
     705             : 
     706           0 :         if (i == IWI_MAX_NODE)
     707           0 :                 return -1;      /* no place left in neighbor table */
     708             : 
     709             :         /* save this new node in our softc table */
     710           0 :         IEEE80211_ADDR_COPY(sc->sta[i], macaddr);
     711           0 :         sc->nsta = i;
     712             : 
     713             :         /* write node information into NIC memory */
     714           0 :         bzero(&node, sizeof node);
     715           0 :         IEEE80211_ADDR_COPY(node.bssid, macaddr);
     716             : 
     717           0 :         CSR_WRITE_REGION_1(sc, IWI_CSR_NODE_BASE + i * sizeof node,
     718             :             (uint8_t *)&node, sizeof node);
     719             : 
     720           0 :         return i;
     721           0 : }
     722             : #endif
     723             : 
     724             : int
     725           0 : iwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     726             : {
     727           0 :         struct iwi_softc *sc = ic->ic_softc;
     728             :         enum ieee80211_state ostate;
     729             :         uint32_t tmp;
     730             : 
     731           0 :         ostate = ic->ic_state;
     732             : 
     733           0 :         switch (nstate) {
     734             :         case IEEE80211_S_SCAN:
     735           0 :                 iwi_scan(sc);
     736           0 :                 break;
     737             : 
     738             :         case IEEE80211_S_AUTH:
     739           0 :                 iwi_auth_and_assoc(sc);
     740           0 :                 break;
     741             : 
     742             :         case IEEE80211_S_RUN:
     743             : #ifndef IEEE80211_STA_ONLY
     744           0 :                 if (ic->ic_opmode == IEEE80211_M_IBSS) {
     745           0 :                         sc->nsta = 0;        /* flush IBSS nodes */
     746           0 :                         ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
     747           0 :                 } else
     748             : #endif
     749           0 :                 if (ic->ic_opmode == IEEE80211_M_MONITOR)
     750           0 :                         iwi_set_chan(sc, ic->ic_ibss_chan);
     751             : 
     752             :                 /* assoc led on */
     753           0 :                 tmp = MEM_READ_4(sc, IWI_MEM_EVENT_CTL) & IWI_LED_MASK;
     754           0 :                 MEM_WRITE_4(sc, IWI_MEM_EVENT_CTL, tmp | IWI_LED_ASSOC);
     755           0 :                 break;
     756             : 
     757             :         case IEEE80211_S_INIT:
     758           0 :                 if (ostate != IEEE80211_S_RUN)
     759             :                         break;
     760             : 
     761             :                 /* assoc led off */
     762           0 :                 tmp = MEM_READ_4(sc, IWI_MEM_EVENT_CTL) & IWI_LED_MASK;
     763           0 :                 MEM_WRITE_4(sc, IWI_MEM_EVENT_CTL, tmp & ~IWI_LED_ASSOC);
     764           0 :                 break;
     765             : 
     766             :         case IEEE80211_S_ASSOC:
     767             :                 break;
     768             :         }
     769             : 
     770           0 :         ic->ic_state = nstate;
     771           0 :         return 0;
     772             : }
     773             : 
     774             : /*
     775             :  * Read 16 bits at address 'addr' from the serial EEPROM.
     776             :  * DON'T PLAY WITH THIS CODE UNLESS YOU KNOW *EXACTLY* WHAT YOU'RE DOING!
     777             :  */
     778             : uint16_t
     779           0 : iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
     780             : {
     781             :         uint32_t tmp;
     782             :         uint16_t val;
     783             :         int n;
     784             : 
     785             :         /* clock C once before the first command */
     786           0 :         IWI_EEPROM_CTL(sc, 0);
     787           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     788           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
     789           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     790             : 
     791             :         /* write start bit (1) */
     792           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D);
     793           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D | IWI_EEPROM_C);
     794             : 
     795             :         /* write READ opcode (10) */
     796           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D);
     797           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D | IWI_EEPROM_C);
     798           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     799           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
     800             : 
     801             :         /* write address A7-A0 */
     802           0 :         for (n = 7; n >= 0; n--) {
     803           0 :                 IWI_EEPROM_CTL(sc, IWI_EEPROM_S |
     804             :                     (((addr >> n) & 1) << IWI_EEPROM_SHIFT_D));
     805           0 :                 IWI_EEPROM_CTL(sc, IWI_EEPROM_S |
     806             :                     (((addr >> n) & 1) << IWI_EEPROM_SHIFT_D) | IWI_EEPROM_C);
     807             :         }
     808             : 
     809           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     810             : 
     811             :         /* read data Q15-Q0 */
     812             :         val = 0;
     813           0 :         for (n = 15; n >= 0; n--) {
     814           0 :                 IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
     815           0 :                 IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     816           0 :                 tmp = MEM_READ_4(sc, IWI_MEM_EEPROM_CTL);
     817           0 :                 val |= ((tmp & IWI_EEPROM_Q) >> IWI_EEPROM_SHIFT_Q) << n;
     818             :         }
     819             : 
     820           0 :         IWI_EEPROM_CTL(sc, 0);
     821             : 
     822             :         /* clear Chip Select and clock C */
     823           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
     824           0 :         IWI_EEPROM_CTL(sc, 0);
     825           0 :         IWI_EEPROM_CTL(sc, IWI_EEPROM_C);
     826             : 
     827           0 :         return val;
     828             : }
     829             : 
     830             : uint8_t
     831           0 : iwi_rate(int plcp)
     832             : {
     833           0 :         switch (plcp) {
     834             :         /* CCK rates (values are device-dependent) */
     835           0 :         case  10:       return 2;
     836           0 :         case  20:       return 4;
     837           0 :         case  55:       return 11;
     838           0 :         case 110:       return 22;
     839             : 
     840             :         /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
     841           0 :         case 0xd:       return 12;
     842           0 :         case 0xf:       return 18;
     843           0 :         case 0x5:       return 24;
     844           0 :         case 0x7:       return 36;
     845           0 :         case 0x9:       return 48;
     846           0 :         case 0xb:       return 72;
     847           0 :         case 0x1:       return 96;
     848           0 :         case 0x3:       return 108;
     849             : 
     850             :         /* unknown rate: should not happen */
     851           0 :         default:        return 0;
     852             :         }
     853           0 : }
     854             : 
     855             : void
     856           0 : iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data,
     857             :     struct iwi_frame *frame)
     858             : {
     859           0 :         struct ieee80211com *ic = &sc->sc_ic;
     860           0 :         struct ifnet *ifp = &ic->ic_if;
     861             :         struct mbuf *mnew, *m;
     862             :         struct ieee80211_frame *wh;
     863           0 :         struct ieee80211_rxinfo rxi;
     864             :         struct ieee80211_node *ni;
     865             :         int error;
     866             : 
     867             :         DPRINTFN(5, ("received frame len=%u chan=%u rssi=%u\n",
     868             :             letoh16(frame->len), frame->chan, frame->rssi_dbm));
     869             : 
     870           0 :         if (letoh16(frame->len) < sizeof (struct ieee80211_frame_min) ||
     871           0 :             letoh16(frame->len) > MCLBYTES) {
     872             :                 DPRINTF(("%s: bad frame length\n", sc->sc_dev.dv_xname));
     873           0 :                 ifp->if_ierrors++;
     874           0 :                 return;
     875             :         }
     876             : 
     877             :         /*
     878             :          * Try to allocate a new mbuf for this ring element and load it before
     879             :          * processing the current mbuf.  If the ring element cannot be loaded,
     880             :          * drop the received packet and reuse the old mbuf.  In the unlikely
     881             :          * case that the old mbuf can't be reloaded either, explicitly panic.
     882             :          */
     883           0 :         MGETHDR(mnew, M_DONTWAIT, MT_DATA);
     884           0 :         if (mnew == NULL) {
     885           0 :                 ifp->if_ierrors++;
     886           0 :                 return;
     887             :         }
     888           0 :         MCLGET(mnew, M_DONTWAIT);
     889           0 :         if (!(mnew->m_flags & M_EXT)) {
     890           0 :                 m_freem(mnew);
     891           0 :                 ifp->if_ierrors++;
     892           0 :                 return;
     893             :         }
     894             : 
     895           0 :         bus_dmamap_unload(sc->sc_dmat, data->map);
     896             : 
     897           0 :         error = bus_dmamap_load(sc->sc_dmat, data->map, mtod(mnew, void *),
     898             :             MCLBYTES, NULL, BUS_DMA_NOWAIT);
     899           0 :         if (error != 0) {
     900           0 :                 m_freem(mnew);
     901             : 
     902             :                 /* try to reload the old mbuf */
     903           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
     904             :                     mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
     905           0 :                 if (error != 0) {
     906             :                         /* very unlikely that it will fail... */
     907           0 :                         panic("%s: could not load old rx mbuf",
     908           0 :                             sc->sc_dev.dv_xname);
     909             :                 }
     910           0 :                 CSR_WRITE_4(sc, data->reg, data->map->dm_segs[0].ds_addr);
     911           0 :                 ifp->if_ierrors++;
     912           0 :                 return;
     913             :         }
     914             : 
     915           0 :         m = data->m;
     916           0 :         data->m = mnew;
     917           0 :         CSR_WRITE_4(sc, data->reg, data->map->dm_segs[0].ds_addr);
     918             : 
     919             :         /* finalize mbuf */
     920           0 :         m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
     921           0 :             sizeof (struct iwi_frame) + letoh16(frame->len);
     922           0 :         m_adj(m, sizeof (struct iwi_hdr) + sizeof (struct iwi_frame));
     923             : 
     924             : #if NBPFILTER > 0
     925           0 :         if (sc->sc_drvbpf != NULL) {
     926           0 :                 struct mbuf mb;
     927           0 :                 struct iwi_rx_radiotap_header *tap = &sc->sc_rxtap;
     928             : 
     929           0 :                 tap->wr_flags = 0;
     930           0 :                 tap->wr_rate = iwi_rate(frame->rate);
     931           0 :                 tap->wr_chan_freq =
     932           0 :                     htole16(ic->ic_channels[frame->chan].ic_freq);
     933           0 :                 tap->wr_chan_flags =
     934           0 :                     htole16(ic->ic_channels[frame->chan].ic_flags);
     935           0 :                 tap->wr_antsignal = frame->signal;
     936           0 :                 tap->wr_antenna = frame->antenna & 0x3;
     937           0 :                 if (frame->antenna & 0x40)
     938           0 :                         tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
     939             : 
     940           0 :                 mb.m_data = (caddr_t)tap;
     941           0 :                 mb.m_len = sc->sc_rxtap_len;
     942           0 :                 mb.m_next = m;
     943           0 :                 mb.m_nextpkt = NULL;
     944           0 :                 mb.m_type = 0;
     945           0 :                 mb.m_flags = 0;
     946           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
     947           0 :         }
     948             : #endif
     949             : 
     950           0 :         wh = mtod(m, struct ieee80211_frame *);
     951           0 :         ni = ieee80211_find_rxnode(ic, wh);
     952             : 
     953             :         /* send the frame to the upper layer */
     954           0 :         rxi.rxi_flags = 0;
     955           0 :         rxi.rxi_rssi = frame->rssi_dbm;
     956           0 :         rxi.rxi_tstamp = 0;     /* unused */
     957           0 :         ieee80211_input(ifp, m, ni, &rxi);
     958             : 
     959             :         /* node is no longer needed */
     960           0 :         ieee80211_release_node(ic, ni);
     961           0 : }
     962             : 
     963             : void
     964           0 : iwi_notification_intr(struct iwi_softc *sc, struct iwi_rx_data *data,
     965             :     struct iwi_notif *notif)
     966             : {
     967           0 :         struct ieee80211com *ic = &sc->sc_ic;
     968           0 :         struct ieee80211_node *ni = ic->ic_bss;
     969           0 :         struct ifnet *ifp = &ic->ic_if;
     970             : 
     971           0 :         switch (notif->type) {
     972             :         case IWI_NOTIF_TYPE_SCAN_CHANNEL:
     973             :         {
     974             : #ifdef IWI_DEBUG
     975             :                 struct iwi_notif_scan_channel *chan =
     976             :                     (struct iwi_notif_scan_channel *)(notif + 1);
     977             : #endif
     978             :                 DPRINTFN(2, ("Scanning channel (%u)\n", chan->nchan));
     979             :                 break;
     980             :         }
     981             :         case IWI_NOTIF_TYPE_SCAN_COMPLETE:
     982             :         {
     983             : #ifdef IWI_DEBUG
     984             :                 struct iwi_notif_scan_complete *scan =
     985             :                     (struct iwi_notif_scan_complete *)(notif + 1);
     986             : #endif
     987             :                 DPRINTFN(2, ("Scan completed (%u, %u)\n", scan->nchan,
     988             :                     scan->status));
     989             : 
     990             :                 /* monitor mode uses scan to set the channel ... */
     991           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR)
     992           0 :                         ieee80211_end_scan(ifp);
     993             :                 else
     994           0 :                         iwi_set_chan(sc, ic->ic_ibss_chan);
     995             :                 break;
     996             :         }
     997             :         case IWI_NOTIF_TYPE_AUTHENTICATION:
     998             :         {
     999             :                 struct iwi_notif_authentication *auth =
    1000           0 :                     (struct iwi_notif_authentication *)(notif + 1);
    1001             : 
    1002             :                 DPRINTFN(2, ("Authentication (%u)\n", auth->state));
    1003             : 
    1004           0 :                 switch (auth->state) {
    1005             :                 case IWI_AUTHENTICATED:
    1006           0 :                         ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
    1007           0 :                         break;
    1008             : 
    1009             :                 case IWI_DEAUTHENTICATED:
    1010             :                         break;
    1011             : 
    1012             :                 default:
    1013           0 :                         printf("%s: unknown authentication state %u\n",
    1014           0 :                             sc->sc_dev.dv_xname, auth->state);
    1015           0 :                 }
    1016             :                 break;
    1017             :         }
    1018             :         case IWI_NOTIF_TYPE_ASSOCIATION:
    1019             :         {
    1020             :                 struct iwi_notif_association *assoc =
    1021           0 :                     (struct iwi_notif_association *)(notif + 1);
    1022             : 
    1023             :                 DPRINTFN(2, ("Association (%u, %u)\n", assoc->state,
    1024             :                     assoc->status));
    1025             : 
    1026           0 :                 switch (assoc->state) {
    1027             :                 case IWI_AUTHENTICATED:
    1028             :                         /* re-association, do nothing */
    1029             :                         break;
    1030             : 
    1031             :                 case IWI_ASSOCIATED:
    1032           0 :                         if (ic->ic_flags & IEEE80211_F_RSNON)
    1033           0 :                                 ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
    1034           0 :                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    1035           0 :                         break;
    1036             : 
    1037             :                 case IWI_DEASSOCIATED:
    1038           0 :                         ieee80211_begin_scan(ifp);
    1039           0 :                         break;
    1040             : 
    1041             :                 default:
    1042           0 :                         printf("%s: unknown association state %u\n",
    1043           0 :                             sc->sc_dev.dv_xname, assoc->state);
    1044           0 :                 }
    1045             :                 break;
    1046             :         }
    1047             :         case IWI_NOTIF_TYPE_BEACON:     
    1048             :         {
    1049             :                 struct iwi_notif_beacon *beacon =
    1050           0 :                     (struct iwi_notif_beacon *)(notif + 1);
    1051             : 
    1052           0 :                 if (letoh32(beacon->status) == IWI_BEACON_MISSED) {
    1053             :                         /* XXX should roam when too many beacons missed */
    1054             :                         DPRINTFN(2, ("%s: %u beacon(s) missed\n",
    1055             :                             sc->sc_dev.dv_xname, letoh32(beacon->count)));
    1056             :                 }
    1057             :                 break;
    1058             :         }
    1059             :         case IWI_NOTIF_TYPE_BAD_LINK:
    1060             :                 DPRINTFN(2, ("link deterioration detected\n"));
    1061             :                 break;
    1062             : 
    1063             :         case IWI_NOTIF_TYPE_NOISE:
    1064             :                 DPRINTFN(5, ("Measured noise %u\n",
    1065             :                     letoh32(*(uint32_t *)(notif + 1)) & 0xff));
    1066             :                 break;
    1067             : 
    1068             :         default:
    1069             :                 DPRINTFN(5, ("Notification (%u)\n", notif->type));
    1070             :         }
    1071           0 : }
    1072             : 
    1073             : void
    1074           0 : iwi_rx_intr(struct iwi_softc *sc)
    1075             : {
    1076             :         struct iwi_rx_data *data;
    1077             :         struct iwi_hdr *hdr;
    1078             :         uint32_t hw;
    1079             : 
    1080           0 :         hw = CSR_READ_4(sc, IWI_CSR_RX_RIDX);
    1081             : 
    1082           0 :         for (; sc->rxq.cur != hw;) {
    1083           0 :                 data = &sc->rxq.data[sc->rxq.cur];
    1084             : 
    1085           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0, MCLBYTES,
    1086             :                     BUS_DMASYNC_POSTREAD);
    1087             : 
    1088           0 :                 hdr = mtod(data->m, struct iwi_hdr *);
    1089             : 
    1090           0 :                 switch (hdr->type) {
    1091             :                 case IWI_HDR_TYPE_FRAME:
    1092           0 :                         iwi_frame_intr(sc, data,
    1093           0 :                             (struct iwi_frame *)(hdr + 1));
    1094           0 :                         break;
    1095             : 
    1096             :                 case IWI_HDR_TYPE_NOTIF:
    1097           0 :                         iwi_notification_intr(sc, data,
    1098           0 :                             (struct iwi_notif *)(hdr + 1));
    1099           0 :                         break;
    1100             : 
    1101             :                 default:
    1102           0 :                         printf("%s: unknown hdr type %u\n",
    1103           0 :                             sc->sc_dev.dv_xname, hdr->type);
    1104           0 :                 }
    1105             : 
    1106           0 :                 sc->rxq.cur = (sc->rxq.cur + 1) % IWI_RX_RING_COUNT;
    1107             :         }
    1108             : 
    1109             :         /* tell the firmware what we have processed */
    1110           0 :         hw = (hw == 0) ? IWI_RX_RING_COUNT - 1 : hw - 1;
    1111           0 :         CSR_WRITE_4(sc, IWI_CSR_RX_WIDX, hw);
    1112           0 : }
    1113             : 
    1114             : void
    1115           0 : iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
    1116             : {
    1117           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1118           0 :         struct ifnet *ifp = &ic->ic_if;
    1119             :         struct iwi_tx_data *data;
    1120             :         uint32_t hw;
    1121             : 
    1122           0 :         hw = CSR_READ_4(sc, txq->csr_ridx);
    1123             : 
    1124           0 :         for (; txq->next != hw;) {
    1125           0 :                 data = &txq->data[txq->next];
    1126             : 
    1127           0 :                 bus_dmamap_unload(sc->sc_dmat, data->map);
    1128           0 :                 m_freem(data->m);
    1129           0 :                 data->m = NULL;
    1130           0 :                 ieee80211_release_node(ic, data->ni);
    1131           0 :                 data->ni = NULL;
    1132             : 
    1133           0 :                 txq->queued--;
    1134           0 :                 txq->next = (txq->next + 1) % IWI_TX_RING_COUNT;
    1135             :         }
    1136             : 
    1137           0 :         sc->sc_tx_timer = 0;
    1138           0 :         ifq_clr_oactive(&ifp->if_snd);
    1139           0 :         (*ifp->if_start)(ifp);
    1140           0 : }
    1141             : 
    1142             : int
    1143           0 : iwi_intr(void *arg)
    1144             : {
    1145           0 :         struct iwi_softc *sc = arg;
    1146           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    1147             :         uint32_t r;
    1148             : 
    1149           0 :         if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff)
    1150           0 :                 return 0;
    1151             : 
    1152             :         /* disable interrupts */
    1153           0 :         CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
    1154             : 
    1155             :         /* acknowledge interrupts */
    1156           0 :         CSR_WRITE_4(sc, IWI_CSR_INTR, r);
    1157             : 
    1158           0 :         if (r & IWI_INTR_FATAL_ERROR) {
    1159           0 :                 printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
    1160           0 :                 iwi_stop(ifp, 1);
    1161           0 :                 task_add(systq, &sc->init_task);
    1162           0 :                 return 1;
    1163             :         }
    1164             : 
    1165           0 :         if (r & IWI_INTR_FW_INITED)
    1166           0 :                 wakeup(sc);
    1167             : 
    1168           0 :         if (r & IWI_INTR_RADIO_OFF) {
    1169             :                 DPRINTF(("radio transmitter off\n"));
    1170           0 :                 iwi_stop(ifp, 1);
    1171           0 :                 return 1;
    1172             :         }
    1173             : 
    1174           0 :         if (r & IWI_INTR_CMD_DONE) {
    1175             :                 /* kick next pending command if any */
    1176           0 :                 sc->cmdq.next = (sc->cmdq.next + 1) % IWI_CMD_RING_COUNT;
    1177           0 :                 if (--sc->cmdq.queued > 0)
    1178           0 :                         CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.next);
    1179             : 
    1180           0 :                 wakeup(sc);
    1181           0 :         }
    1182             : 
    1183           0 :         if (r & IWI_INTR_TX1_DONE)
    1184           0 :                 iwi_tx_intr(sc, &sc->txq[0]);
    1185             : 
    1186           0 :         if (r & IWI_INTR_TX2_DONE)
    1187           0 :                 iwi_tx_intr(sc, &sc->txq[1]);
    1188             : 
    1189           0 :         if (r & IWI_INTR_TX3_DONE)
    1190           0 :                 iwi_tx_intr(sc, &sc->txq[2]);
    1191             : 
    1192           0 :         if (r & IWI_INTR_TX4_DONE)
    1193           0 :                 iwi_tx_intr(sc, &sc->txq[3]);
    1194             : 
    1195           0 :         if (r & IWI_INTR_RX_DONE)
    1196           0 :                 iwi_rx_intr(sc);
    1197             : 
    1198             :         /* re-enable interrupts */
    1199           0 :         CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK);
    1200             : 
    1201           0 :         return 1;
    1202           0 : }
    1203             : 
    1204             : int
    1205           0 : iwi_cmd(struct iwi_softc *sc, uint8_t type, void *data, uint8_t len, int async)
    1206             : {
    1207             :         struct iwi_cmd_desc *desc;
    1208             : 
    1209           0 :         desc = &sc->cmdq.desc[sc->cmdq.cur];
    1210           0 :         desc->hdr.type = IWI_HDR_TYPE_COMMAND;
    1211           0 :         desc->hdr.flags = IWI_HDR_FLAG_IRQ;
    1212           0 :         desc->type = type;
    1213           0 :         desc->len = len;
    1214           0 :         bcopy(data, desc->data, len);
    1215             : 
    1216           0 :         bus_dmamap_sync(sc->sc_dmat, sc->cmdq.map,
    1217             :             sc->cmdq.cur * sizeof (struct iwi_cmd_desc),
    1218             :             sizeof (struct iwi_cmd_desc), BUS_DMASYNC_PREWRITE);
    1219             : 
    1220             :         DPRINTFN(2, ("sending command idx=%u type=%u len=%u\n", sc->cmdq.cur,
    1221             :             type, len));
    1222             : 
    1223           0 :         sc->cmdq.cur = (sc->cmdq.cur + 1) % IWI_CMD_RING_COUNT;
    1224             : 
    1225             :         /* don't kick cmd immediately if another async command is pending */
    1226           0 :         if (++sc->cmdq.queued == 1) {
    1227           0 :                 sc->cmdq.next = sc->cmdq.cur;
    1228           0 :                 CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.next);
    1229           0 :         }
    1230             : 
    1231           0 :         return async ? 0 : tsleep(sc, PCATCH, "iwicmd", hz);
    1232             : }
    1233             : 
    1234             : /* ARGSUSED */
    1235             : int
    1236           0 : iwi_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, int type,
    1237             :     int arg1, int arg2)
    1238             : {
    1239           0 :         return EOPNOTSUPP;
    1240             : }
    1241             : 
    1242             : int
    1243           0 : iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
    1244             : {
    1245           0 :         struct iwi_softc *sc = ifp->if_softc;
    1246           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1247             :         struct ieee80211_frame *wh;
    1248             :         struct ieee80211_key *k;
    1249             :         struct iwi_tx_data *data;
    1250             :         struct iwi_tx_desc *desc;
    1251           0 :         struct iwi_tx_ring *txq = &sc->txq[0];
    1252             :         int hdrlen, error, i, station = 0;
    1253             : 
    1254           0 :         wh = mtod(m0, struct ieee80211_frame *);
    1255             : 
    1256           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    1257           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    1258             : 
    1259           0 :                 if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL)
    1260           0 :                         return ENOBUFS;
    1261             : 
    1262             :                 /* packet header may have moved, reset our local pointer */
    1263           0 :                 wh = mtod(m0, struct ieee80211_frame *);
    1264           0 :         }
    1265             : 
    1266             : #if NBPFILTER > 0
    1267           0 :         if (sc->sc_drvbpf != NULL) {
    1268           0 :                 struct mbuf mb;
    1269           0 :                 struct iwi_tx_radiotap_header *tap = &sc->sc_txtap;
    1270             : 
    1271           0 :                 tap->wt_flags = 0;
    1272           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1273           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1274             : 
    1275           0 :                 mb.m_data = (caddr_t)tap;
    1276           0 :                 mb.m_len = sc->sc_txtap_len;
    1277           0 :                 mb.m_next = m0;
    1278           0 :                 mb.m_nextpkt = NULL;
    1279           0 :                 mb.m_type = 0;
    1280           0 :                 mb.m_flags = 0;
    1281           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1282           0 :         }
    1283             : #endif
    1284             : 
    1285           0 :         data = &txq->data[txq->cur];
    1286           0 :         desc = &txq->desc[txq->cur];
    1287             : 
    1288             :         /* copy and trim IEEE802.11 header */
    1289           0 :         hdrlen = ieee80211_get_hdrlen(wh);
    1290           0 :         bcopy(wh, &desc->wh, hdrlen);
    1291           0 :         m_adj(m0, hdrlen);
    1292             : 
    1293             : #ifndef IEEE80211_STA_ONLY
    1294           0 :         if (ic->ic_opmode == IEEE80211_M_IBSS) {
    1295           0 :                 station = iwi_find_txnode(sc, desc->wh.i_addr1);
    1296           0 :                 if (station == -1) {
    1297           0 :                         m_freem(m0);
    1298           0 :                         ieee80211_release_node(ic, ni);
    1299           0 :                         ifp->if_oerrors++;
    1300           0 :                         return 0;
    1301             :                 }
    1302             :         }
    1303             : #endif
    1304             : 
    1305           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
    1306             :             BUS_DMA_NOWAIT);
    1307           0 :         if (error != 0 && error != EFBIG) {
    1308           0 :                 printf("%s: can't map mbuf (error %d)\n",
    1309           0 :                     sc->sc_dev.dv_xname, error);
    1310           0 :                 m_freem(m0);
    1311           0 :                 return error;
    1312             :         }
    1313           0 :         if (error != 0) {
    1314             :                 /* too many fragments, linearize */
    1315           0 :                 if (m_defrag(m0, M_DONTWAIT)) {
    1316           0 :                         m_freem(m0);
    1317           0 :                         return ENOBUFS;
    1318             :                 }
    1319           0 :                 error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
    1320             :                     BUS_DMA_NOWAIT);
    1321           0 :                 if (error != 0) {
    1322           0 :                         printf("%s: can't map mbuf (error %d)\n",
    1323           0 :                             sc->sc_dev.dv_xname, error);
    1324           0 :                         m_freem(m0);
    1325           0 :                         return error;
    1326             :                 }
    1327             :         }
    1328             : 
    1329           0 :         data->m = m0;
    1330           0 :         data->ni = ni;
    1331             : 
    1332           0 :         desc->hdr.type = IWI_HDR_TYPE_DATA;
    1333           0 :         desc->hdr.flags = IWI_HDR_FLAG_IRQ;
    1334           0 :         desc->cmd = IWI_DATA_CMD_TX;
    1335           0 :         desc->len = htole16(m0->m_pkthdr.len);
    1336           0 :         desc->station = station;
    1337           0 :         desc->flags = IWI_DATA_FLAG_NO_WEP;
    1338           0 :         desc->xflags = 0;
    1339             : 
    1340           0 :         if (!IEEE80211_IS_MULTICAST(desc->wh.i_addr1))
    1341           0 :                 desc->flags |= IWI_DATA_FLAG_NEED_ACK;
    1342             : 
    1343           0 :         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
    1344           0 :                 desc->flags |= IWI_DATA_FLAG_SHPREAMBLE;
    1345             : 
    1346           0 :         if ((desc->wh.i_fc[0] &
    1347           0 :             (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
    1348             :             (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
    1349           0 :                 desc->xflags |= IWI_DATA_XFLAG_QOS;
    1350             : 
    1351           0 :         if (ic->ic_curmode == IEEE80211_MODE_11B)
    1352           0 :                 desc->xflags |= IWI_DATA_XFLAG_CCK;
    1353             : 
    1354           0 :         desc->nseg = htole32(data->map->dm_nsegs);
    1355           0 :         for (i = 0; i < data->map->dm_nsegs; i++) {
    1356           0 :                 desc->seg_addr[i] = htole32(data->map->dm_segs[i].ds_addr);
    1357           0 :                 desc->seg_len[i]  = htole16(data->map->dm_segs[i].ds_len);
    1358             :         }
    1359             : 
    1360           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
    1361             :             BUS_DMASYNC_PREWRITE);
    1362           0 :         bus_dmamap_sync(sc->sc_dmat, txq->map,
    1363             :             txq->cur * sizeof (struct iwi_tx_desc),
    1364             :             sizeof (struct iwi_tx_desc), BUS_DMASYNC_PREWRITE);
    1365             : 
    1366             :         DPRINTFN(5, ("sending data frame idx=%u len=%u nseg=%u\n", txq->cur,
    1367             :             letoh16(desc->len), data->map->dm_nsegs));
    1368             : 
    1369           0 :         txq->queued++;
    1370           0 :         txq->cur = (txq->cur + 1) % IWI_TX_RING_COUNT;
    1371           0 :         CSR_WRITE_4(sc, txq->csr_widx, txq->cur);
    1372             : 
    1373           0 :         return 0;
    1374           0 : }
    1375             : 
    1376             : void
    1377           0 : iwi_start(struct ifnet *ifp)
    1378             : {
    1379           0 :         struct iwi_softc *sc = ifp->if_softc;
    1380           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1381             :         struct mbuf *m0;
    1382           0 :         struct ieee80211_node *ni;
    1383             : 
    1384           0 :         if (ic->ic_state != IEEE80211_S_RUN)
    1385           0 :                 return;
    1386             : 
    1387           0 :         for (;;) {
    1388           0 :                 if (sc->txq[0].queued + IWI_MAX_NSEG + 2 >= IWI_TX_RING_COUNT) {
    1389           0 :                         ifq_set_oactive(&ifp->if_snd);
    1390           0 :                         break;
    1391             :                 }
    1392             : 
    1393           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m0);
    1394           0 :                 if (m0 == NULL)
    1395             :                         break;
    1396             : 
    1397             : #if NBPFILTER > 0
    1398           0 :                 if (ifp->if_bpf != NULL)
    1399           0 :                         bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
    1400             : #endif
    1401             : 
    1402           0 :                 m0 = ieee80211_encap(ifp, m0, &ni);
    1403           0 :                 if (m0 == NULL)
    1404           0 :                         continue;
    1405             : 
    1406             : #if NBPFILTER > 0
    1407           0 :                 if (ic->ic_rawbpf != NULL)
    1408           0 :                         bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1409             : #endif
    1410             : 
    1411           0 :                 if (iwi_tx_start(ifp, m0, ni) != 0) {
    1412           0 :                         if (ni != NULL)
    1413           0 :                                 ieee80211_release_node(ic, ni);
    1414           0 :                         ifp->if_oerrors++;
    1415           0 :                         break;
    1416             :                 }
    1417             : 
    1418             :                 /* start watchdog timer */
    1419           0 :                 sc->sc_tx_timer = 5;
    1420           0 :                 ifp->if_timer = 1;
    1421             :         }
    1422           0 : }
    1423             : 
    1424             : void
    1425           0 : iwi_watchdog(struct ifnet *ifp)
    1426             : {
    1427           0 :         struct iwi_softc *sc = ifp->if_softc;
    1428             : 
    1429           0 :         ifp->if_timer = 0;
    1430             : 
    1431           0 :         if (sc->sc_tx_timer > 0) {
    1432           0 :                 if (--sc->sc_tx_timer == 0) {
    1433           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    1434           0 :                         iwi_stop(ifp, 1);
    1435           0 :                         ifp->if_oerrors++;
    1436           0 :                         return;
    1437             :                 }
    1438           0 :                 ifp->if_timer = 1;
    1439           0 :         }
    1440             : 
    1441           0 :         ieee80211_watchdog(ifp);
    1442           0 : }
    1443             : 
    1444             : int
    1445           0 : iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1446             : {
    1447           0 :         struct iwi_softc *sc = ifp->if_softc;
    1448             :         int s, error = 0;
    1449             : 
    1450           0 :         error = rw_enter(&sc->sc_rwlock, RW_WRITE | RW_INTR);
    1451           0 :         if (error)
    1452           0 :                 return error;
    1453           0 :         s = splnet();
    1454             : 
    1455           0 :         switch (cmd) {
    1456             :         case SIOCSIFADDR:
    1457           0 :                 ifp->if_flags |= IFF_UP;
    1458             :                 /* FALLTHROUGH */
    1459             :         case SIOCSIFFLAGS:
    1460           0 :                 if (ifp->if_flags & IFF_UP) {
    1461           0 :                         if (!(ifp->if_flags & IFF_RUNNING))
    1462           0 :                                 iwi_init(ifp);
    1463             :                 } else {
    1464           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1465           0 :                                 iwi_stop(ifp, 1);
    1466             :                 }
    1467             :                 break;
    1468             : 
    1469             :         case SIOCG80211TXPOWER:
    1470             :                 /*
    1471             :                  * If the hardware radio transmitter switch is off, report a
    1472             :                  * tx power of IEEE80211_TXPOWER_MIN to indicate that radio
    1473             :                  * transmitter is killed.
    1474             :                  */
    1475           0 :                 ((struct ieee80211_txpower *)data)->i_val =
    1476           0 :                     (CSR_READ_4(sc, IWI_CSR_IO) & IWI_IO_RADIO_ENABLED) ?
    1477           0 :                     sc->sc_ic.ic_txpower : IEEE80211_TXPOWER_MIN;
    1478           0 :                 break;
    1479             : 
    1480             :         default:
    1481           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1482           0 :         }
    1483             : 
    1484           0 :         if (error == ENETRESET) {
    1485           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1486             :                     (IFF_UP | IFF_RUNNING))
    1487           0 :                         iwi_init(ifp);
    1488             :                 error = 0;
    1489           0 :         }
    1490             : 
    1491           0 :         splx(s);
    1492           0 :         rw_exit_write(&sc->sc_rwlock);
    1493           0 :         return error;
    1494           0 : }
    1495             : 
    1496             : void
    1497           0 : iwi_stop_master(struct iwi_softc *sc)
    1498             : {
    1499             :         uint32_t tmp;
    1500             :         int ntries;
    1501             : 
    1502             :         /* disable interrupts */
    1503           0 :         CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
    1504             : 
    1505           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_STOP_MASTER);
    1506           0 :         for (ntries = 0; ntries < 5; ntries++) {
    1507           0 :                 if (CSR_READ_4(sc, IWI_CSR_RST) & IWI_RST_MASTER_DISABLED)
    1508             :                         break;
    1509           0 :                 DELAY(10);
    1510             :         }
    1511           0 :         if (ntries == 5) {
    1512           0 :                 printf("%s: timeout waiting for master\n",
    1513           0 :                     sc->sc_dev.dv_xname);
    1514           0 :         }
    1515             : 
    1516           0 :         tmp = CSR_READ_4(sc, IWI_CSR_RST);
    1517           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_PRINCETON_RESET);
    1518           0 : }
    1519             : 
    1520             : int
    1521           0 : iwi_reset(struct iwi_softc *sc)
    1522             : {
    1523             :         uint32_t tmp;
    1524             :         int i, ntries;
    1525             : 
    1526           0 :         iwi_stop_master(sc);
    1527             : 
    1528             :         /* move adapter to D0 state */
    1529           0 :         tmp = CSR_READ_4(sc, IWI_CSR_CTL);
    1530           0 :         CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_INIT);
    1531             : 
    1532           0 :         CSR_WRITE_4(sc, IWI_CSR_READ_INT, IWI_READ_INT_INIT_HOST);
    1533             : 
    1534             :         /* wait for clock stabilization */
    1535           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    1536           0 :                 if (CSR_READ_4(sc, IWI_CSR_CTL) & IWI_CTL_CLOCK_READY)
    1537             :                         break;
    1538           0 :                 DELAY(200);
    1539             :         }
    1540           0 :         if (ntries == 1000) {
    1541           0 :                 printf("%s: timeout waiting for clock stabilization\n",
    1542           0 :                     sc->sc_dev.dv_xname);
    1543           0 :                 return ETIMEDOUT;
    1544             :         }
    1545             : 
    1546           0 :         tmp = CSR_READ_4(sc, IWI_CSR_RST);
    1547           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_SW_RESET);
    1548             : 
    1549           0 :         DELAY(10);
    1550             : 
    1551           0 :         tmp = CSR_READ_4(sc, IWI_CSR_CTL);
    1552           0 :         CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_INIT);
    1553             : 
    1554             :         /* clear NIC memory */
    1555           0 :         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_ADDR, 0);
    1556           0 :         for (i = 0; i < 0xc000; i++)
    1557           0 :                 CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, 0);
    1558             : 
    1559           0 :         return 0;
    1560           0 : }
    1561             : 
    1562             : int
    1563           0 : iwi_load_ucode(struct iwi_softc *sc, const char *data, int size)
    1564             : {
    1565             :         const uint16_t *w;
    1566             :         uint32_t tmp;
    1567             :         int ntries, i;
    1568             : 
    1569           0 :         tmp = CSR_READ_4(sc, IWI_CSR_RST);
    1570           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_STOP_MASTER);
    1571           0 :         for (ntries = 0; ntries < 5; ntries++) {
    1572           0 :                 if (CSR_READ_4(sc, IWI_CSR_RST) & IWI_RST_MASTER_DISABLED)
    1573             :                         break;
    1574           0 :                 DELAY(10);
    1575             :         }
    1576           0 :         if (ntries == 5) {
    1577           0 :                 printf("%s: timeout waiting for master\n",
    1578           0 :                     sc->sc_dev.dv_xname);
    1579           0 :                 return ETIMEDOUT;
    1580             :         }
    1581             : 
    1582           0 :         MEM_WRITE_4(sc, 0x3000e0, 0x80000000);
    1583           0 :         DELAY(5000);
    1584             : 
    1585           0 :         tmp = CSR_READ_4(sc, IWI_CSR_RST);
    1586           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, tmp & ~IWI_RST_PRINCETON_RESET);
    1587             : 
    1588           0 :         DELAY(5000);
    1589           0 :         MEM_WRITE_4(sc, 0x3000e0, 0);
    1590           0 :         DELAY(1000);
    1591           0 :         MEM_WRITE_4(sc, IWI_MEM_EVENT_CTL, 1);
    1592           0 :         DELAY(1000);
    1593           0 :         MEM_WRITE_4(sc, IWI_MEM_EVENT_CTL, 0);
    1594           0 :         DELAY(1000);
    1595           0 :         MEM_WRITE_1(sc, 0x200000, 0x00);
    1596           0 :         MEM_WRITE_1(sc, 0x200000, 0x40);
    1597           0 :         DELAY(1000);
    1598             : 
    1599             :         /* adapter is buggy, we must set the address for each word */
    1600           0 :         for (w = (const uint16_t *)data; size > 0; w++, size -= 2)
    1601           0 :                 MEM_WRITE_2(sc, 0x200010, htole16(*w));
    1602             : 
    1603           0 :         MEM_WRITE_1(sc, 0x200000, 0x00);
    1604           0 :         MEM_WRITE_1(sc, 0x200000, 0x80);
    1605             : 
    1606             :         /* wait until we get an answer */
    1607           0 :         for (ntries = 0; ntries < 100; ntries++) {
    1608           0 :                 if (MEM_READ_1(sc, 0x200000) & 1)
    1609             :                         break;
    1610           0 :                 DELAY(100);
    1611             :         }
    1612           0 :         if (ntries == 100) {
    1613           0 :                 printf("%s: timeout waiting for ucode to initialize\n",
    1614           0 :                     sc->sc_dev.dv_xname);
    1615           0 :                 return ETIMEDOUT;
    1616             :         }
    1617             : 
    1618             :         /* read the answer or the firmware will not initialize properly */
    1619           0 :         for (i = 0; i < 7; i++)
    1620           0 :                 MEM_READ_4(sc, 0x200004);
    1621             : 
    1622           0 :         MEM_WRITE_1(sc, 0x200000, 0x00);
    1623             : 
    1624           0 :         return 0;
    1625           0 : }
    1626             : 
    1627             : /* macro to handle unaligned little endian data in firmware image */
    1628             : #define GETLE32(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
    1629             : 
    1630             : int
    1631           0 : iwi_load_firmware(struct iwi_softc *sc, const char *data, int size)
    1632             : {
    1633           0 :         bus_dmamap_t map;
    1634           0 :         bus_dma_segment_t seg;
    1635           0 :         caddr_t virtaddr;
    1636             :         u_char *p, *end;
    1637             :         uint32_t sentinel, tmp, ctl, src, dst, sum, len, mlen;
    1638           0 :         int ntries, nsegs, error;
    1639             : 
    1640             :         /* allocate DMA memory to store firmware image */
    1641           0 :         error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    1642             :             BUS_DMA_NOWAIT, &map);
    1643           0 :         if (error != 0) {
    1644           0 :                 printf("%s: could not create firmware DMA map\n",
    1645           0 :                     sc->sc_dev.dv_xname);
    1646           0 :                 goto fail1;
    1647             :         }
    1648             : 
    1649           0 :         error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg, 1,
    1650             :             &nsegs, BUS_DMA_NOWAIT);
    1651           0 :         if (error != 0) {
    1652           0 :                 printf("%s: could not allocate firmware DMA memory\n",
    1653           0 :                     sc->sc_dev.dv_xname);
    1654           0 :                 goto fail2;
    1655             :         }
    1656             : 
    1657           0 :         error = bus_dmamem_map(sc->sc_dmat, &seg, nsegs, size, &virtaddr,
    1658             :             BUS_DMA_NOWAIT);
    1659           0 :         if (error != 0) {
    1660           0 :                 printf("%s: can't map firmware DMA memory\n",
    1661           0 :                     sc->sc_dev.dv_xname);
    1662           0 :                 goto fail3;
    1663             :         }
    1664             : 
    1665           0 :         error = bus_dmamap_load(sc->sc_dmat, map, virtaddr, size, NULL,
    1666             :             BUS_DMA_NOWAIT);
    1667           0 :         if (error != 0) {
    1668           0 :                 printf("%s: could not load firmware DMA map\n",
    1669           0 :                     sc->sc_dev.dv_xname);
    1670           0 :                 goto fail4;
    1671             :         }
    1672             : 
    1673             :         /* copy firmware image to DMA memory */
    1674           0 :         bcopy(data, virtaddr, size);
    1675             : 
    1676             :         /* make sure the adapter will get up-to-date values */
    1677           0 :         bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_PREWRITE);
    1678             : 
    1679             :         /* tell the adapter where the command blocks are stored */
    1680           0 :         MEM_WRITE_4(sc, 0x3000a0, 0x27000);
    1681             : 
    1682             :         /*
    1683             :          * Store command blocks into adapter's internal memory using register
    1684             :          * indirections. The adapter will read the firmware image through DMA
    1685             :          * using information stored in command blocks.
    1686             :          */
    1687           0 :         src = map->dm_segs[0].ds_addr;
    1688           0 :         p = virtaddr;
    1689           0 :         end = p + size;
    1690           0 :         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_ADDR, 0x27000);
    1691             : 
    1692           0 :         while (p < end) {
    1693           0 :                 dst = GETLE32(p); p += 4; src += 4;
    1694           0 :                 len = GETLE32(p); p += 4; src += 4;
    1695           0 :                 p += len;
    1696             : 
    1697           0 :                 while (len > 0) {
    1698           0 :                         mlen = min(len, IWI_CB_MAXDATALEN);
    1699             : 
    1700           0 :                         ctl = IWI_CB_DEFAULT_CTL | mlen;
    1701           0 :                         sum = ctl ^ src ^ dst;
    1702             : 
    1703             :                         /* write a command block */
    1704           0 :                         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, ctl);
    1705           0 :                         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, src);
    1706           0 :                         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, dst);
    1707           0 :                         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, sum);
    1708             : 
    1709           0 :                         src += mlen;
    1710           0 :                         dst += mlen;
    1711           0 :                         len -= mlen;
    1712             :                 }
    1713             :         }
    1714             : 
    1715             :         /* write a fictive final command block (sentinel) */
    1716           0 :         sentinel = CSR_READ_4(sc, IWI_CSR_AUTOINC_ADDR);
    1717           0 :         CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, 0);
    1718             : 
    1719           0 :         tmp = CSR_READ_4(sc, IWI_CSR_RST);
    1720           0 :         tmp &= ~(IWI_RST_MASTER_DISABLED | IWI_RST_STOP_MASTER);
    1721           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, tmp);
    1722             : 
    1723             :         /* tell the adapter to start processing command blocks */
    1724           0 :         MEM_WRITE_4(sc, 0x3000a4, 0x540100);
    1725             : 
    1726             :         /* wait until the adapter has processed all command blocks */
    1727           0 :         for (ntries = 0; ntries < 400; ntries++) {
    1728           0 :                 if (MEM_READ_4(sc, 0x3000d0) >= sentinel)
    1729             :                         break;
    1730           0 :                 DELAY(100);
    1731             :         }
    1732           0 :         if (ntries == 400) {
    1733           0 :                 printf("%s: timeout processing cb\n", sc->sc_dev.dv_xname);
    1734             :                 error = ETIMEDOUT;
    1735           0 :                 goto fail5;
    1736             :         }
    1737             : 
    1738             :         /* we're done with command blocks processing */
    1739           0 :         MEM_WRITE_4(sc, 0x3000a4, 0x540c00);
    1740             : 
    1741             :         /* allow interrupts so we know when the firmware is inited */
    1742           0 :         CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK);
    1743             : 
    1744             :         /* tell the adapter to initialize the firmware */
    1745           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, 0);
    1746             : 
    1747           0 :         tmp = CSR_READ_4(sc, IWI_CSR_CTL);
    1748           0 :         CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_ALLOW_STANDBY);
    1749             : 
    1750             :         /* wait at most one second for firmware initialization to complete */
    1751           0 :         if ((error = tsleep(sc, PCATCH, "iwiinit", hz)) != 0) {
    1752           0 :                 printf("%s: timeout waiting for firmware initialization to "
    1753           0 :                     "complete\n", sc->sc_dev.dv_xname);
    1754           0 :                 goto fail5;
    1755             :         }
    1756             : 
    1757           0 : fail5:  bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_POSTWRITE);
    1758           0 :         bus_dmamap_unload(sc->sc_dmat, map);
    1759           0 : fail4:  bus_dmamem_unmap(sc->sc_dmat, virtaddr, size);
    1760           0 : fail3:  bus_dmamem_free(sc->sc_dmat, &seg, 1);
    1761           0 : fail2:  bus_dmamap_destroy(sc->sc_dmat, map);
    1762           0 : fail1:  return error;
    1763           0 : }
    1764             : 
    1765             : int
    1766           0 : iwi_config(struct iwi_softc *sc)
    1767             : {
    1768           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1769           0 :         struct ifnet *ifp = &ic->ic_if;
    1770           0 :         struct iwi_configuration config;
    1771           0 :         struct iwi_rateset rs;
    1772           0 :         struct iwi_txpower power;
    1773           0 :         uint32_t data;
    1774             :         int error, nchan, i;
    1775             : 
    1776           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    1777             :         DPRINTF(("Setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
    1778           0 :         error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_myaddr,
    1779             :             IEEE80211_ADDR_LEN, 0);
    1780           0 :         if (error != 0)
    1781           0 :                 return error;
    1782             : 
    1783           0 :         bzero(&config, sizeof config);
    1784           0 :         config.multicast_enabled = 1;
    1785           0 :         config.silence_threshold = 30;
    1786           0 :         config.report_noise = 1;
    1787           0 :         config.answer_pbreq =
    1788             : #ifndef IEEE80211_STA_ONLY
    1789           0 :             (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 :
    1790             : #endif
    1791             :             0;
    1792             :         DPRINTF(("Configuring adapter\n"));
    1793           0 :         error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config, 0);
    1794           0 :         if (error != 0)
    1795           0 :                 return error;
    1796             : 
    1797           0 :         data = htole32(IWI_POWER_MODE_CAM);
    1798             :         DPRINTF(("Setting power mode to %u\n", letoh32(data)));
    1799           0 :         error = iwi_cmd(sc, IWI_CMD_SET_POWER_MODE, &data, sizeof data, 0);
    1800           0 :         if (error != 0)
    1801           0 :                 return error;
    1802             : 
    1803           0 :         data = htole32(ic->ic_rtsthreshold);
    1804             :         DPRINTF(("Setting RTS threshold to %u\n", letoh32(data)));
    1805           0 :         error = iwi_cmd(sc, IWI_CMD_SET_RTS_THRESHOLD, &data, sizeof data, 0);
    1806           0 :         if (error != 0)
    1807           0 :                 return error;
    1808             : 
    1809           0 :         data = htole32(ic->ic_fragthreshold);
    1810             :         DPRINTF(("Setting fragmentation threshold to %u\n", letoh32(data)));
    1811           0 :         error = iwi_cmd(sc, IWI_CMD_SET_FRAG_THRESHOLD, &data, sizeof data, 0);
    1812           0 :         if (error != 0)
    1813           0 :                 return error;
    1814             : 
    1815             :         /*
    1816             :          * Set default Tx power for 802.11b/g and 802.11a channels.
    1817             :          */
    1818             :         nchan = 0;
    1819           0 :         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    1820           0 :                 if (!IEEE80211_IS_CHAN_2GHZ(&ic->ic_channels[i]))
    1821             :                         continue;
    1822           0 :                 power.chan[nchan].chan = i;
    1823           0 :                 power.chan[nchan].power = IWI_TXPOWER_MAX;
    1824           0 :                 nchan++;
    1825           0 :         }
    1826           0 :         power.nchan = nchan;
    1827             : 
    1828           0 :         power.mode = IWI_MODE_11G;
    1829             :         DPRINTF(("Setting .11g channels tx power\n"));
    1830           0 :         error = iwi_cmd(sc, IWI_CMD_SET_TX_POWER, &power, sizeof power, 0);
    1831           0 :         if (error != 0)
    1832           0 :                 return error;
    1833             : 
    1834           0 :         power.mode = IWI_MODE_11B;
    1835             :         DPRINTF(("Setting .11b channels tx power\n"));
    1836           0 :         error = iwi_cmd(sc, IWI_CMD_SET_TX_POWER, &power, sizeof power, 0);
    1837           0 :         if (error != 0)
    1838           0 :                 return error;
    1839             : 
    1840             :         nchan = 0;
    1841           0 :         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    1842           0 :                 if (!IEEE80211_IS_CHAN_5GHZ(&ic->ic_channels[i]))
    1843             :                         continue;
    1844           0 :                 power.chan[nchan].chan = i;
    1845           0 :                 power.chan[nchan].power = IWI_TXPOWER_MAX;
    1846           0 :                 nchan++;
    1847           0 :         }
    1848           0 :         power.nchan = nchan;
    1849             : 
    1850           0 :         if (nchan > 0) {     /* 2915ABG only */
    1851           0 :                 power.mode = IWI_MODE_11A;
    1852             :                 DPRINTF(("Setting .11a channels tx power\n"));
    1853           0 :                 error = iwi_cmd(sc, IWI_CMD_SET_TX_POWER, &power, sizeof power,
    1854             :                     0);
    1855           0 :                 if (error != 0)
    1856           0 :                         return error;
    1857             :         }
    1858             : 
    1859           0 :         rs.mode = IWI_MODE_11G;
    1860           0 :         rs.type = IWI_RATESET_TYPE_SUPPORTED;
    1861           0 :         rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates;
    1862           0 :         bcopy(ic->ic_sup_rates[IEEE80211_MODE_11G].rs_rates, rs.rates,
    1863           0 :             rs.nrates);
    1864             :         DPRINTF(("Setting .11bg supported rates (%u)\n", rs.nrates));
    1865           0 :         error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 0);
    1866           0 :         if (error != 0)
    1867           0 :                 return error;
    1868             : 
    1869           0 :         rs.mode = IWI_MODE_11A;
    1870           0 :         rs.type = IWI_RATESET_TYPE_SUPPORTED;
    1871           0 :         rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates;
    1872           0 :         bcopy(ic->ic_sup_rates[IEEE80211_MODE_11A].rs_rates, rs.rates,
    1873           0 :             rs.nrates);
    1874             :         DPRINTF(("Setting .11a supported rates (%u)\n", rs.nrates));
    1875           0 :         error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 0);
    1876           0 :         if (error != 0)
    1877           0 :                 return error;
    1878             : 
    1879             :         /* if we have a desired ESSID, set it now */
    1880           0 :         if (ic->ic_des_esslen != 0) {
    1881             : #ifdef IWI_DEBUG
    1882             :                 if (iwi_debug > 0) {
    1883             :                         printf("Setting desired ESSID to ");
    1884             :                         ieee80211_print_essid(ic->ic_des_essid,
    1885             :                             ic->ic_des_esslen);
    1886             :                         printf("\n");
    1887             :                 }
    1888             : #endif
    1889           0 :                 error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ic->ic_des_essid,
    1890           0 :                     ic->ic_des_esslen, 0);
    1891           0 :                 if (error != 0)
    1892           0 :                         return error;
    1893             :         }
    1894             : 
    1895           0 :         arc4random_buf(&data, sizeof data);
    1896             :         DPRINTF(("Setting random seed to %u\n", data));
    1897           0 :         error = iwi_cmd(sc, IWI_CMD_SET_RANDOM_SEED, &data, sizeof data, 0);
    1898           0 :         if (error != 0)
    1899           0 :                 return error;
    1900             : 
    1901             :         /* enable adapter */
    1902             :         DPRINTF(("Enabling adapter\n"));
    1903           0 :         return iwi_cmd(sc, IWI_CMD_ENABLE, NULL, 0, 0);
    1904           0 : }
    1905             : 
    1906             : void
    1907           0 : iwi_update_edca(struct ieee80211com *ic)
    1908             : {
    1909             : #define IWI_EXP2(v)     htole16((1 << (v)) - 1)
    1910             : #define IWI_TXOP(v)     IEEE80211_TXOP_TO_US(v)
    1911           0 :         struct iwi_softc *sc = ic->ic_softc;
    1912           0 :         struct iwi_qos_cmd cmd;
    1913             :         struct iwi_qos_params *qos;
    1914           0 :         struct ieee80211_edca_ac_params *edca = ic->ic_edca_ac;
    1915             :         int aci;
    1916             : 
    1917             :         /* set default QoS parameters for CCK */
    1918           0 :         qos = &cmd.cck;
    1919           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
    1920           0 :                 qos->cwmin[aci] = IWI_EXP2(iwi_cck[aci].ac_ecwmin);
    1921           0 :                 qos->cwmax[aci] = IWI_EXP2(iwi_cck[aci].ac_ecwmax);
    1922           0 :                 qos->txop [aci] = IWI_TXOP(iwi_cck[aci].ac_txoplimit);
    1923           0 :                 qos->aifsn[aci] = iwi_cck[aci].ac_aifsn;
    1924           0 :                 qos->acm  [aci] = 0;
    1925             :         }
    1926             :         /* set default QoS parameters for OFDM */
    1927           0 :         qos = &cmd.ofdm;
    1928           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
    1929           0 :                 qos->cwmin[aci] = IWI_EXP2(iwi_ofdm[aci].ac_ecwmin);
    1930           0 :                 qos->cwmax[aci] = IWI_EXP2(iwi_ofdm[aci].ac_ecwmax);
    1931           0 :                 qos->txop [aci] = IWI_TXOP(iwi_ofdm[aci].ac_txoplimit);
    1932           0 :                 qos->aifsn[aci] = iwi_ofdm[aci].ac_aifsn;
    1933           0 :                 qos->acm  [aci] = 0;
    1934             :         }
    1935             :         /* set current QoS parameters */
    1936           0 :         qos = &cmd.current;
    1937           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
    1938           0 :                 qos->cwmin[aci] = IWI_EXP2(edca[aci].ac_ecwmin);
    1939           0 :                 qos->cwmax[aci] = IWI_EXP2(edca[aci].ac_ecwmax);
    1940           0 :                 qos->txop [aci] = IWI_TXOP(edca[aci].ac_txoplimit);
    1941           0 :                 qos->aifsn[aci] = edca[aci].ac_aifsn;
    1942           0 :                 qos->acm  [aci] = 0;
    1943             :         }
    1944             : 
    1945             :         DPRINTF(("Setting QoS parameters\n"));
    1946           0 :         (void)iwi_cmd(sc, IWI_CMD_SET_QOS_PARAMS, &cmd, sizeof cmd, 1);
    1947             : #undef IWI_EXP2
    1948             : #undef IWI_TXOP
    1949           0 : }
    1950             : 
    1951             : int
    1952           0 : iwi_set_chan(struct iwi_softc *sc, struct ieee80211_channel *chan)
    1953             : {
    1954           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1955           0 :         struct iwi_scan scan;
    1956             : 
    1957           0 :         bzero(&scan, sizeof scan);
    1958           0 :         memset(scan.type, IWI_SCAN_TYPE_PASSIVE, sizeof scan.type);
    1959           0 :         scan.passive = htole16(2000);
    1960           0 :         scan.channels[0] = 1 |
    1961           0 :             (IEEE80211_IS_CHAN_5GHZ(chan) ? IWI_CHAN_5GHZ : IWI_CHAN_2GHZ);
    1962           0 :         scan.channels[1] = ieee80211_chan2ieee(ic, chan);
    1963             : 
    1964             :         DPRINTF(("Setting channel to %u\n", ieee80211_chan2ieee(ic, chan)));
    1965           0 :         return iwi_cmd(sc, IWI_CMD_SCAN, &scan, sizeof scan, 1);
    1966           0 : }
    1967             : 
    1968             : int
    1969           0 : iwi_scan(struct iwi_softc *sc)
    1970             : {
    1971           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1972           0 :         struct iwi_scan scan;
    1973             :         uint8_t *p;
    1974             :         int i, count;
    1975             : 
    1976           0 :         bzero(&scan, sizeof scan);
    1977             : 
    1978           0 :         if (ic->ic_des_esslen != 0) {
    1979           0 :                 scan.bdirected = htole16(40);
    1980           0 :                 memset(scan.type, IWI_SCAN_TYPE_BDIRECTED, sizeof scan.type);
    1981           0 :         } else {
    1982           0 :                 scan.broadcast = htole16(40);
    1983           0 :                 memset(scan.type, IWI_SCAN_TYPE_BROADCAST, sizeof scan.type);
    1984             :         }
    1985             : 
    1986           0 :         p = scan.channels;
    1987             :         count = 0;
    1988           0 :         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    1989           0 :                 if (IEEE80211_IS_CHAN_5GHZ(&ic->ic_channels[i])) {
    1990           0 :                         *++p = i;
    1991           0 :                         count++;
    1992           0 :                 }
    1993             :         }
    1994           0 :         *(p - count) = IWI_CHAN_5GHZ | count;
    1995             : 
    1996           0 :         p = (count > 0) ? p + 1 : scan.channels;
    1997             :         count = 0;
    1998           0 :         for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
    1999           0 :                 if (IEEE80211_IS_CHAN_2GHZ(&ic->ic_channels[i])) {
    2000           0 :                         *++p = i;
    2001           0 :                         count++;
    2002           0 :                 }
    2003             :         }
    2004           0 :         *(p - count) = IWI_CHAN_2GHZ | count;
    2005             : 
    2006             :         DPRINTF(("Start scanning\n"));
    2007           0 :         return iwi_cmd(sc, IWI_CMD_SCAN, &scan, sizeof scan, 1);
    2008           0 : }
    2009             : 
    2010             : int
    2011           0 : iwi_auth_and_assoc(struct iwi_softc *sc)
    2012             : {
    2013           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2014           0 :         struct ieee80211_node *ni = ic->ic_bss;
    2015           0 :         struct iwi_configuration config;
    2016           0 :         struct iwi_associate assoc;
    2017           0 :         struct iwi_rateset rs;
    2018             :         uint8_t *frm;
    2019           0 :         uint32_t data;
    2020             :         uint16_t capinfo;
    2021           0 :         uint8_t buf[64];        /* XXX max WPA/RSN/WMM IE length */
    2022             :         int error;
    2023             : 
    2024             :         /* update adapter configuration */
    2025           0 :         bzero(&config, sizeof config);
    2026           0 :         config.multicast_enabled = 1;
    2027           0 :         config.disable_unicast_decryption = 1;
    2028           0 :         config.disable_multicast_decryption = 1;
    2029           0 :         config.silence_threshold = 30;
    2030           0 :         config.report_noise = 1;
    2031           0 :         config.allow_mgt = 1;
    2032           0 :         config.answer_pbreq =
    2033             : #ifndef IEEE80211_STA_ONLY
    2034           0 :             (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 :
    2035             : #endif
    2036             :             0;
    2037           0 :         if (ic->ic_curmode == IEEE80211_MODE_11G)
    2038           0 :                 config.bg_autodetection = 1;
    2039             :         DPRINTF(("Configuring adapter\n"));
    2040           0 :         error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config, 1);
    2041           0 :         if (error != 0)
    2042           0 :                 return error;
    2043             : 
    2044             : #ifdef IWI_DEBUG
    2045             :         if (iwi_debug > 0) {
    2046             :                 printf("Setting ESSID to ");
    2047             :                 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
    2048             :                 printf("\n");
    2049             :         }
    2050             : #endif
    2051           0 :         error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ni->ni_essid, ni->ni_esslen, 1);
    2052           0 :         if (error != 0)
    2053           0 :                 return error;
    2054             : 
    2055             :         /* the rate set has already been "negotiated" */
    2056           0 :         rs.mode = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? IWI_MODE_11A :
    2057             :             IWI_MODE_11G;
    2058           0 :         rs.type = IWI_RATESET_TYPE_NEGOTIATED;
    2059           0 :         rs.nrates = ni->ni_rates.rs_nrates;
    2060           0 :         if (rs.nrates > sizeof rs.rates) {
    2061             : #ifdef DIAGNOSTIC
    2062             :                 /* should not happen since the rates are negotiated */
    2063           0 :                 printf("%s: XXX too many rates (count=%d, last=%d)\n",
    2064           0 :                     sc->sc_dev.dv_xname, ni->ni_rates.rs_nrates,
    2065           0 :                     ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates - 1] &
    2066             :                     IEEE80211_RATE_VAL);
    2067             : #endif
    2068           0 :                 rs.nrates = sizeof rs.rates;
    2069           0 :         }
    2070           0 :         bcopy(ni->ni_rates.rs_rates, rs.rates, rs.nrates);
    2071             :         DPRINTF(("Setting negotiated rates (%u)\n", rs.nrates));
    2072           0 :         error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 1);
    2073           0 :         if (error != 0)
    2074           0 :                 return error;
    2075             : 
    2076           0 :         data = htole32(ni->ni_rssi);
    2077             :         DPRINTF(("Setting sensitivity to %d\n", (int8_t)ni->ni_rssi));
    2078           0 :         error = iwi_cmd(sc, IWI_CMD_SET_SENSITIVITY, &data, sizeof data, 1);
    2079           0 :         if (error != 0)
    2080           0 :                 return error;
    2081             : 
    2082           0 :         if (ic->ic_flags & IEEE80211_F_QOS) {
    2083           0 :                 iwi_update_edca(ic);
    2084             : 
    2085           0 :                 frm = ieee80211_add_qos_capability(buf, ic);
    2086             :                 DPRINTF(("Setting QoS Capability IE length %d\n", frm - buf));
    2087           0 :                 error = iwi_cmd(sc, IWI_CMD_SET_QOS_CAP, buf, frm - buf, 1);
    2088           0 :                 if (error != 0)
    2089           0 :                         return error;
    2090             :         }
    2091           0 :         if (ic->ic_flags & IEEE80211_F_RSNON) {
    2092             :                 /* tell firmware to add WPA/RSN IE to (re)assoc request */
    2093           0 :                 if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN)
    2094           0 :                         frm = ieee80211_add_rsn(buf, ic, ni);
    2095             :                 else
    2096           0 :                         frm = ieee80211_add_wpa(buf, ic, ni);
    2097             :                 DPRINTF(("Setting RSN IE length %d\n", frm - buf));
    2098           0 :                 error = iwi_cmd(sc, IWI_CMD_SET_OPTIE, buf, frm - buf, 1);
    2099           0 :                 if (error != 0)
    2100           0 :                         return error;
    2101             :         }
    2102             : 
    2103           0 :         bzero(&assoc, sizeof assoc);
    2104             : #ifndef IEEE80211_STA_ONLY
    2105           0 :         if (ic->ic_flags & IEEE80211_F_SIBSS)
    2106           0 :                 assoc.type = IWI_ASSOC_SIBSS;
    2107             :         else
    2108             : #endif
    2109           0 :                 assoc.type = IWI_ASSOC_ASSOCIATE;
    2110           0 :         assoc.policy = 0;
    2111           0 :         if (ic->ic_flags & IEEE80211_F_RSNON)
    2112           0 :                 assoc.policy |= htole16(IWI_ASSOC_POLICY_RSN);
    2113           0 :         if (ic->ic_flags & IEEE80211_F_QOS)
    2114           0 :                 assoc.policy |= htole16(IWI_ASSOC_POLICY_QOS);
    2115           0 :         if (ic->ic_curmode == IEEE80211_MODE_11A)
    2116           0 :                 assoc.mode = IWI_MODE_11A;
    2117           0 :         else if (ic->ic_curmode == IEEE80211_MODE_11B)
    2118           0 :                 assoc.mode = IWI_MODE_11B;
    2119             :         else    /* assume 802.11b/g */
    2120           0 :                 assoc.mode = IWI_MODE_11G;
    2121           0 :         assoc.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
    2122           0 :         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
    2123           0 :             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
    2124           0 :                 assoc.plen = IWI_ASSOC_SHPREAMBLE;
    2125           0 :         bcopy(ni->ni_tstamp, assoc.tstamp, 8);
    2126             :         capinfo = IEEE80211_CAPINFO_ESS;
    2127           0 :         if (ic->ic_flags & IEEE80211_F_WEPON)
    2128           0 :                 capinfo |= IEEE80211_CAPINFO_PRIVACY;
    2129           0 :         if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
    2130           0 :             IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
    2131           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
    2132           0 :         if (ic->ic_caps & IEEE80211_C_SHSLOT)
    2133           0 :                 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
    2134           0 :         assoc.capinfo = htole16(capinfo);
    2135             : 
    2136           0 :         assoc.lintval = htole16(ic->ic_lintval);
    2137           0 :         assoc.intval = htole16(ni->ni_intval);
    2138           0 :         IEEE80211_ADDR_COPY(assoc.bssid, ni->ni_bssid);
    2139             : #ifndef IEEE80211_STA_ONLY
    2140           0 :         if (ic->ic_opmode == IEEE80211_M_IBSS)
    2141           0 :                 IEEE80211_ADDR_COPY(assoc.dst, etherbroadcastaddr);
    2142             :         else
    2143             : #endif
    2144           0 :                 IEEE80211_ADDR_COPY(assoc.dst, ni->ni_bssid);
    2145             : 
    2146             :         DPRINTF(("Trying to associate to %s channel %u auth %u\n",
    2147             :             ether_sprintf(assoc.bssid), assoc.chan, assoc.auth));
    2148           0 :         return iwi_cmd(sc, IWI_CMD_ASSOCIATE, &assoc, sizeof assoc, 1);
    2149           0 : }
    2150             : 
    2151             : int
    2152           0 : iwi_init(struct ifnet *ifp)
    2153             : {
    2154           0 :         struct iwi_softc *sc = ifp->if_softc;
    2155           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2156             :         struct iwi_firmware_hdr *hdr;
    2157             :         const char *name, *fw;
    2158           0 :         u_char *data;
    2159           0 :         size_t size;
    2160             :         int i, ac, error;
    2161             : 
    2162           0 :         iwi_stop(ifp, 0);
    2163             : 
    2164           0 :         if ((error = iwi_reset(sc)) != 0) {
    2165           0 :                 printf("%s: could not reset adapter\n", sc->sc_dev.dv_xname);
    2166           0 :                 goto fail1;
    2167             :         }
    2168             : 
    2169           0 :         switch (ic->ic_opmode) {
    2170             :         case IEEE80211_M_STA:
    2171             :                 name = "iwi-bss";
    2172           0 :                 break;
    2173             : #ifndef IEEE80211_STA_ONLY
    2174             :         case IEEE80211_M_IBSS:
    2175             :         case IEEE80211_M_AHDEMO:
    2176             :                 name = "iwi-ibss";
    2177           0 :                 break;
    2178             : #endif
    2179             :         case IEEE80211_M_MONITOR:
    2180             :                 name = "iwi-monitor";
    2181           0 :                 break;
    2182             :         default:
    2183             :                 /* should not get there */
    2184             :                 error = EINVAL;
    2185           0 :                 goto fail1;
    2186             :         }
    2187             : 
    2188           0 :         if ((error = loadfirmware(name, &data, &size)) != 0) {
    2189           0 :                 printf("%s: error %d, could not read firmware %s\n",
    2190           0 :                     sc->sc_dev.dv_xname, error, name);
    2191           0 :                 goto fail1;
    2192             :         }
    2193           0 :         if (size < sizeof (struct iwi_firmware_hdr)) {
    2194           0 :                 printf("%s: firmware image too short: %zu bytes\n",
    2195           0 :                     sc->sc_dev.dv_xname, size);
    2196             :                 error = EINVAL;
    2197           0 :                 goto fail2;
    2198             :         }
    2199           0 :         hdr = (struct iwi_firmware_hdr *)data;
    2200             : 
    2201           0 :         if (hdr->vermaj < 3 || hdr->bootsz == 0 || hdr->ucodesz == 0 ||
    2202           0 :             hdr->mainsz == 0) {
    2203           0 :                 printf("%s: firmware image too old (need at least 3.0)\n",
    2204           0 :                     sc->sc_dev.dv_xname);
    2205             :                 error = EINVAL;
    2206           0 :                 goto fail2;
    2207             :         }
    2208             : 
    2209           0 :         if (size < sizeof (struct iwi_firmware_hdr) + letoh32(hdr->bootsz) +
    2210           0 :             letoh32(hdr->ucodesz) + letoh32(hdr->mainsz)) {
    2211           0 :                 printf("%s: firmware image too short: %zu bytes\n",
    2212           0 :                     sc->sc_dev.dv_xname, size);
    2213             :                 error = EINVAL;
    2214           0 :                 goto fail2;
    2215             :         }
    2216             : 
    2217           0 :         fw = (const char *)data + sizeof (struct iwi_firmware_hdr);
    2218           0 :         if ((error = iwi_load_firmware(sc, fw, letoh32(hdr->bootsz))) != 0) {
    2219           0 :                 printf("%s: could not load boot firmware\n",
    2220           0 :                     sc->sc_dev.dv_xname);
    2221           0 :                 goto fail2;
    2222             :         }
    2223             : 
    2224           0 :         fw = (const char *)data + sizeof (struct iwi_firmware_hdr) +
    2225           0 :             letoh32(hdr->bootsz);
    2226           0 :         if ((error = iwi_load_ucode(sc, fw, letoh32(hdr->ucodesz))) != 0) {
    2227           0 :                 printf("%s: could not load microcode\n", sc->sc_dev.dv_xname);
    2228           0 :                 goto fail2;
    2229             :         }
    2230             : 
    2231           0 :         iwi_stop_master(sc);
    2232             : 
    2233           0 :         CSR_WRITE_4(sc, IWI_CSR_CMD_BASE, sc->cmdq.map->dm_segs[0].ds_addr);
    2234           0 :         CSR_WRITE_4(sc, IWI_CSR_CMD_SIZE, IWI_CMD_RING_COUNT);
    2235           0 :         CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.cur);
    2236             : 
    2237           0 :         for (ac = 0; ac < EDCA_NUM_AC; ac++) {
    2238           0 :                 CSR_WRITE_4(sc, IWI_CSR_TX_BASE(ac),
    2239             :                     sc->txq[ac].map->dm_segs[0].ds_addr);
    2240           0 :                 CSR_WRITE_4(sc, IWI_CSR_TX_SIZE(ac), IWI_TX_RING_COUNT);
    2241           0 :                 CSR_WRITE_4(sc, IWI_CSR_TX_WIDX(ac), sc->txq[ac].cur);
    2242             :         }
    2243             : 
    2244           0 :         for (i = 0; i < IWI_RX_RING_COUNT; i++) {
    2245           0 :                 struct iwi_rx_data *data = &sc->rxq.data[i];
    2246           0 :                 CSR_WRITE_4(sc, data->reg, data->map->dm_segs[0].ds_addr);
    2247             :         }
    2248             : 
    2249           0 :         CSR_WRITE_4(sc, IWI_CSR_RX_WIDX, IWI_RX_RING_COUNT - 1);
    2250             : 
    2251           0 :         fw = (const char *)data + sizeof (struct iwi_firmware_hdr) +
    2252           0 :             letoh32(hdr->bootsz) + letoh32(hdr->ucodesz);
    2253           0 :         if ((error = iwi_load_firmware(sc, fw, letoh32(hdr->mainsz))) != 0) {
    2254           0 :                 printf("%s: could not load main firmware\n",
    2255           0 :                     sc->sc_dev.dv_xname);
    2256           0 :                 goto fail2;
    2257             :         }
    2258             : 
    2259           0 :         free(data, M_DEVBUF, size);
    2260             : 
    2261           0 :         if ((error = iwi_config(sc)) != 0) {
    2262           0 :                 printf("%s: device configuration failed\n",
    2263           0 :                     sc->sc_dev.dv_xname);
    2264           0 :                 goto fail1;
    2265             :         }
    2266             : 
    2267           0 :         ifq_clr_oactive(&ifp->if_snd);
    2268           0 :         ifp->if_flags |= IFF_RUNNING;
    2269             : 
    2270           0 :         if (ic->ic_opmode != IEEE80211_M_MONITOR)
    2271           0 :                 ieee80211_begin_scan(ifp);
    2272             :         else
    2273           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2274             : 
    2275           0 :         return 0;
    2276             : 
    2277           0 : fail2:  free(data, M_DEVBUF, size);
    2278           0 : fail1:  iwi_stop(ifp, 0);
    2279           0 :         return error;
    2280           0 : }
    2281             : 
    2282             : void
    2283           0 : iwi_stop(struct ifnet *ifp, int disable)
    2284             : {
    2285           0 :         struct iwi_softc *sc = ifp->if_softc;
    2286           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2287             :         int ac;
    2288             : 
    2289           0 :         sc->sc_tx_timer = 0;
    2290           0 :         ifp->if_timer = 0;
    2291           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2292           0 :         ifq_clr_oactive(&ifp->if_snd);
    2293             : 
    2294           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    2295             : 
    2296           0 :         iwi_stop_master(sc);
    2297             : 
    2298           0 :         CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_SW_RESET);
    2299             : 
    2300             :         /* reset rings */
    2301           0 :         iwi_reset_cmd_ring(sc, &sc->cmdq);
    2302           0 :         for (ac = 0; ac < EDCA_NUM_AC; ac++)
    2303           0 :                 iwi_reset_tx_ring(sc, &sc->txq[ac]);
    2304           0 :         iwi_reset_rx_ring(sc, &sc->rxq);
    2305           0 : }
    2306             : 
    2307             : struct cfdriver iwi_cd = {
    2308             :         NULL, "iwi", DV_IFNET
    2309             : };

Generated by: LCOV version 1.13