The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/wi/if_wi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: wi.c,v 1.109 2003/01/09 08:52:19 dyoung Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998, 1999
    5  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Bill Paul.
   18  * 4. Neither the name of the author nor the names of any co-contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   32  * THE POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 /*
   36  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver.
   37  *
   38  * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
   39  * Electrical Engineering Department
   40  * Columbia University, New York City
   41  */
   42 
   43 /*
   44  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
   45  * from Lucent. Unlike the older cards, the new ones are programmed
   46  * entirely via a firmware-driven controller called the Hermes.
   47  * Unfortunately, Lucent will not release the Hermes programming manual
   48  * without an NDA (if at all). What they do release is an API library
   49  * called the HCF (Hardware Control Functions) which is supposed to
   50  * do the device-specific operations of a device driver for you. The
   51  * publically available version of the HCF library (the 'HCF Light') is 
   52  * a) extremely gross, b) lacks certain features, particularly support
   53  * for 802.11 frames, and c) is contaminated by the GNU Public License.
   54  *
   55  * This driver does not use the HCF or HCF Light at all. Instead, it
   56  * programs the Hermes controller directly, using information gleaned
   57  * from the HCF Light code and corresponding documentation.
   58  *
   59  * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
   60  * WaveLan cards (based on the Hermes chipset), as well as the newer
   61  * Prism 2 chipsets with firmware from Intersil and Symbol.
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 __FBSDID("$FreeBSD$");
   66 
   67 #define WI_HERMES_AUTOINC_WAR   /* Work around data write autoinc bug. */
   68 #define WI_HERMES_STATS_WAR     /* Work around stats counter bug. */
   69 
   70 #define NBPFILTER       1
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/endian.h>
   75 #include <sys/sockio.h>
   76 #include <sys/mbuf.h>
   77 #include <sys/priv.h>
   78 #include <sys/proc.h>
   79 #include <sys/kernel.h>
   80 #include <sys/socket.h>
   81 #include <sys/module.h>
   82 #include <sys/bus.h>
   83 #include <sys/random.h>
   84 #include <sys/syslog.h>
   85 #include <sys/sysctl.h>
   86 
   87 #include <machine/bus.h>
   88 #include <machine/resource.h>
   89 #include <machine/atomic.h>
   90 #include <sys/rman.h>
   91 
   92 #include <net/if.h>
   93 #include <net/if_arp.h>
   94 #include <net/ethernet.h>
   95 #include <net/if_dl.h>
   96 #include <net/if_media.h>
   97 #include <net/if_types.h>
   98 
   99 #include <net80211/ieee80211_var.h>
  100 #include <net80211/ieee80211_ioctl.h>
  101 #include <net80211/ieee80211_radiotap.h>
  102 
  103 #include <netinet/in.h>
  104 #include <netinet/in_systm.h>
  105 #include <netinet/in_var.h>
  106 #include <netinet/ip.h>
  107 #include <netinet/if_ether.h>
  108 
  109 #include <net/bpf.h>
  110 
  111 #include <dev/wi/if_wavelan_ieee.h>
  112 #include <dev/wi/if_wireg.h>
  113 #include <dev/wi/if_wivar.h>
  114 
  115 static void wi_start_locked(struct ifnet *);
  116 static void wi_start(struct ifnet *);
  117 static int  wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
  118                 struct mbuf *m0);
  119 static int  wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
  120                 const struct ieee80211_bpf_params *);
  121 static int  wi_reset(struct ifnet *);
  122 static void wi_watchdog(void *);
  123 static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
  124 static int  wi_media_change(struct ifnet *);
  125 static void wi_media_status(struct ifnet *, struct ifmediareq *);
  126 
  127 static void wi_rx_intr(struct wi_softc *);
  128 static void wi_tx_intr(struct wi_softc *);
  129 static void wi_tx_ex_intr(struct wi_softc *);
  130 static void wi_info_intr(struct wi_softc *);
  131 
  132 static int  wi_key_alloc(struct ieee80211com *, const struct ieee80211_key *,
  133                 ieee80211_keyix *, ieee80211_keyix *);
  134 
  135 #if 0
  136 static int  wi_get_cfg(struct ifnet *, u_long, caddr_t);
  137 static int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
  138 #endif
  139 static int  wi_write_txrate(struct wi_softc *);
  140 static int  wi_write_wep(struct wi_softc *);
  141 static int  wi_write_multi(struct wi_softc *);
  142 static int  wi_alloc_fid(struct wi_softc *, int, int *);
  143 static void wi_read_nicid(struct wi_softc *);
  144 static int  wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
  145 
  146 static int  wi_cmd(struct wi_softc *, int, int, int, int);
  147 static int  wi_seek_bap(struct wi_softc *, int, int);
  148 static int  wi_read_bap(struct wi_softc *, int, int, void *, int);
  149 static int  wi_write_bap(struct wi_softc *, int, int, void *, int);
  150 static int  wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
  151 static int  wi_read_rid(struct wi_softc *, int, void *, int *);
  152 static int  wi_write_rid(struct wi_softc *, int, void *, int);
  153 
  154 static int  wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
  155 
  156 static int  wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
  157 static void wi_scan_result(struct wi_softc *, int, int);
  158 
  159 static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
  160 
  161 #if 0
  162 static int wi_get_debug(struct wi_softc *, struct wi_req *);
  163 static int wi_set_debug(struct wi_softc *, struct wi_req *);
  164 #endif
  165 
  166 /* support to download firmware for symbol CF card */
  167 static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
  168                 const void *, int);
  169 static int wi_symbol_set_hcr(struct wi_softc *, int);
  170 
  171 static void wi_scan_start(struct ieee80211com *);
  172 static void wi_scan_curchan(struct ieee80211com *, unsigned long);
  173 static void wi_scan_mindwell(struct ieee80211com *);
  174 static void wi_scan_end(struct ieee80211com *);
  175 static void wi_set_channel(struct ieee80211com *);
  176 static void wi_update_slot(struct ifnet *);
  177 static struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
  178 static int wi_ioctl_get(struct ifnet *ifp, u_long command, caddr_t data);
  179 static int wi_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data);
  180         
  181 static __inline int
  182 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
  183 {
  184 
  185         val = htole16(val);
  186         return wi_write_rid(sc, rid, &val, sizeof(val));
  187 }
  188 
  189 SYSCTL_NODE(_hw, OID_AUTO, wi, CTLFLAG_RD, 0, "Wireless driver parameters");
  190 
  191 static  struct timeval lasttxerror;     /* time of last tx error msg */
  192 static  int curtxeps;                   /* current tx error msgs/sec */
  193 static  int wi_txerate = 0;             /* tx error rate: max msgs/sec */
  194 SYSCTL_INT(_hw_wi, OID_AUTO, txerate, CTLFLAG_RW, &wi_txerate,
  195             0, "max tx error msgs/sec; 0 to disable msgs");
  196 
  197 #define WI_DEBUG
  198 #ifdef WI_DEBUG
  199 static  int wi_debug = 0;
  200 SYSCTL_INT(_hw_wi, OID_AUTO, debug, CTLFLAG_RW, &wi_debug,
  201             0, "control debugging printfs");
  202 
  203 #define DPRINTF(X)      if (wi_debug) printf X
  204 #define DPRINTF2(X)     if (wi_debug > 1) printf X
  205 #define IFF_DUMPPKTS(_ifp) \
  206         (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
  207 #else
  208 #define DPRINTF(X)
  209 #define DPRINTF2(X)
  210 #define IFF_DUMPPKTS(_ifp)      0
  211 #endif
  212 
  213 #define WI_INTRS        (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
  214 
  215 struct wi_card_ident wi_card_ident[] = {
  216         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
  217         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
  218         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
  219         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
  220         { WI_NIC_EVB2_ID,               WI_NIC_EVB2_STR,        WI_INTERSIL },
  221         { WI_NIC_HWB3763_ID,            WI_NIC_HWB3763_STR,     WI_INTERSIL },
  222         { WI_NIC_HWB3163_ID,            WI_NIC_HWB3163_STR,     WI_INTERSIL },
  223         { WI_NIC_HWB3163B_ID,           WI_NIC_HWB3163B_STR,    WI_INTERSIL },
  224         { WI_NIC_EVB3_ID,               WI_NIC_EVB3_STR,        WI_INTERSIL },
  225         { WI_NIC_HWB1153_ID,            WI_NIC_HWB1153_STR,     WI_INTERSIL },
  226         { WI_NIC_P2_SST_ID,             WI_NIC_P2_SST_STR,      WI_INTERSIL },
  227         { WI_NIC_EVB2_SST_ID,           WI_NIC_EVB2_SST_STR,    WI_INTERSIL },
  228         { WI_NIC_3842_EVA_ID,           WI_NIC_3842_EVA_STR,    WI_INTERSIL },
  229         { WI_NIC_3842_PCMCIA_AMD_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  230         { WI_NIC_3842_PCMCIA_SST_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  231         { WI_NIC_3842_PCMCIA_ATL_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  232         { WI_NIC_3842_PCMCIA_ATS_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  233         { WI_NIC_3842_MINI_AMD_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  234         { WI_NIC_3842_MINI_SST_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  235         { WI_NIC_3842_MINI_ATL_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  236         { WI_NIC_3842_MINI_ATS_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  237         { WI_NIC_3842_PCI_AMD_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  238         { WI_NIC_3842_PCI_SST_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  239         { WI_NIC_3842_PCI_ATS_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  240         { WI_NIC_3842_PCI_ATL_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  241         { WI_NIC_P3_PCMCIA_AMD_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  242         { WI_NIC_P3_PCMCIA_SST_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  243         { WI_NIC_P3_PCMCIA_ATL_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  244         { WI_NIC_P3_PCMCIA_ATS_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  245         { WI_NIC_P3_MINI_AMD_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  246         { WI_NIC_P3_MINI_SST_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  247         { WI_NIC_P3_MINI_ATL_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  248         { WI_NIC_P3_MINI_ATS_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  249         { 0,    NULL,   0 },
  250 };
  251 
  252 devclass_t wi_devclass;
  253 
  254 int
  255 wi_attach(device_t dev)
  256 {
  257         struct wi_softc *sc = device_get_softc(dev);
  258         struct ieee80211com *ic = &sc->sc_ic;
  259         struct ifnet *ifp;
  260         int i, nrates, buflen;
  261         u_int16_t val;
  262         u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
  263         struct ieee80211_rateset *rs;
  264         static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
  265                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  266         };
  267         int error;
  268 
  269         ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
  270         if (ifp == NULL) {
  271                 device_printf(dev, "can not if_alloc\n");
  272                 wi_free(dev);
  273                 return (ENOSPC);
  274         }
  275         ifp->if_softc = sc;
  276 
  277         /*
  278          * NB: no locking is needed here; don't put it here
  279          *     unless you can prove it!
  280          */
  281         error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
  282             NULL, wi_intr, sc, &sc->wi_intrhand);
  283 
  284         if (error) {
  285                 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
  286                 wi_free(dev);
  287                 return (error);
  288         }
  289 
  290         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  291             MTX_DEF | MTX_RECURSE);
  292         callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
  293 
  294         sc->sc_firmware_type = WI_NOTYPE;
  295         sc->wi_cmd_count = 500;
  296         /* Reset the NIC. */
  297         if (wi_reset(ifp) != 0)
  298                 return ENXIO;           /* XXX */
  299 
  300         /*
  301          * Read the station address.
  302          * And do it twice. I've seen PRISM-based cards that return
  303          * an error when trying to read it the first time, which causes
  304          * the probe to fail.
  305          */
  306         buflen = IEEE80211_ADDR_LEN;
  307         error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
  308         if (error != 0) {
  309                 buflen = IEEE80211_ADDR_LEN;
  310                 error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
  311         }
  312         if (error || IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
  313                 if (error != 0)
  314                         device_printf(dev, "mac read failed %d\n", error);
  315                 else {
  316                         device_printf(dev, "mac read failed (all zeros)\n");
  317                         error = ENXIO;
  318                 }
  319                 wi_free(dev);
  320                 return (error);
  321         }
  322 
  323         /* Read NIC identification */
  324         wi_read_nicid(sc);
  325 
  326         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  327         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  328         ifp->if_ioctl = wi_ioctl;
  329         ifp->if_start = wi_start;
  330         ifp->if_init = wi_init;
  331         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
  332         ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
  333         IFQ_SET_READY(&ifp->if_snd);
  334 
  335         ic->ic_ifp = ifp;
  336         ic->ic_phytype = IEEE80211_T_DS;
  337         ic->ic_opmode = IEEE80211_M_STA;
  338         ic->ic_state = IEEE80211_S_INIT;
  339         ic->ic_caps = IEEE80211_C_PMGT
  340                     | IEEE80211_C_WEP           /* everyone supports WEP */
  341                     ;
  342         ic->ic_max_aid = WI_MAX_AID;
  343 
  344         /*
  345          * Query the card for available channels and setup the
  346          * channel table.  We assume these are all 11b channels.
  347          */
  348         buflen = sizeof(val);
  349         if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0)
  350                 val = htole16(0x1fff);  /* assume 1-11 */
  351         KASSERT(val != 0, ("wi_attach: no available channels listed!"));
  352 
  353         val <<= 1;                      /* shift for base 1 indices */
  354         for (i = 1; i < 16; i++) {
  355                 struct ieee80211_channel *c;
  356 
  357                 if (!isset((u_int8_t*)&val, i))
  358                         continue;
  359                 c = &ic->ic_channels[ic->ic_nchans++];
  360                 c->ic_freq = ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
  361                 c->ic_flags = IEEE80211_CHAN_B;
  362                 c->ic_ieee = i;
  363         }
  364 
  365         /*
  366          * Read the default channel from the NIC. This may vary
  367          * depending on the country where the NIC was purchased, so
  368          * we can't hard-code a default and expect it to work for
  369          * everyone.
  370          *
  371          * If no channel is specified, let the 802.11 code select.
  372          */
  373         buflen = sizeof(val);
  374         if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
  375                 val = le16toh(val);
  376                 ic->ic_bsschan = ieee80211_find_channel(ic,
  377                         ieee80211_ieee2mhz(val, IEEE80211_CHAN_B),
  378                         IEEE80211_CHAN_B);
  379                 if (ic->ic_bsschan == NULL)
  380                         ic->ic_bsschan = &ic->ic_channels[0];
  381         } else {
  382                 device_printf(dev,
  383                         "WI_RID_OWN_CHNL failed, using first channel!\n");
  384                 ic->ic_bsschan = &ic->ic_channels[0];
  385         }
  386 
  387         /*
  388          * Set flags based on firmware version.
  389          */
  390         switch (sc->sc_firmware_type) {
  391         case WI_LUCENT:
  392                 sc->sc_ntxbuf = 1;
  393                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
  394 #ifdef WI_HERMES_AUTOINC_WAR
  395                 /* XXX: not confirmed, but never seen for recent firmware */
  396                 if (sc->sc_sta_firmware_ver <  40000) {
  397                         sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
  398                 }
  399 #endif
  400                 if (sc->sc_sta_firmware_ver >= 60000)
  401                         sc->sc_flags |= WI_FLAGS_HAS_MOR;
  402                 if (sc->sc_sta_firmware_ver >= 60006) {
  403                         ic->ic_caps |= IEEE80211_C_IBSS;
  404                         ic->ic_caps |= IEEE80211_C_MONITOR;
  405                 }
  406                 sc->sc_ibss_port = htole16(1);
  407 
  408                 sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
  409                 sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
  410                 sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
  411                 break;
  412 
  413         case WI_INTERSIL:
  414                 sc->sc_ntxbuf = WI_NTXBUF;
  415                 sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
  416                 sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
  417                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
  418                 /*
  419                  * Old firmware are slow, so give peace a chance.
  420                  */
  421                 if (sc->sc_sta_firmware_ver < 10000)
  422                         sc->wi_cmd_count = 5000;
  423                 if (sc->sc_sta_firmware_ver > 10101)
  424                         sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
  425                 if (sc->sc_sta_firmware_ver >= 800) {
  426                         ic->ic_caps |= IEEE80211_C_IBSS;
  427                         ic->ic_caps |= IEEE80211_C_MONITOR;
  428                 }
  429                 /*
  430                  * version 0.8.3 and newer are the only ones that are known
  431                  * to currently work.  Earlier versions can be made to work,
  432                  * at least according to the Linux driver.
  433                  */
  434                 if (sc->sc_sta_firmware_ver >= 803)
  435                         ic->ic_caps |= IEEE80211_C_HOSTAP;
  436                 sc->sc_ibss_port = htole16(0);
  437 
  438                 sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
  439                 sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
  440                 sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
  441                 break;
  442 
  443         case WI_SYMBOL:
  444                 sc->sc_ntxbuf = 1;
  445                 sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
  446                 if (sc->sc_sta_firmware_ver >= 25000)
  447                         ic->ic_caps |= IEEE80211_C_IBSS;
  448                 sc->sc_ibss_port = htole16(4);
  449 
  450                 sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
  451                 sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
  452                 sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
  453                 break;
  454         }
  455 
  456         /*
  457          * Find out if we support WEP on this card.
  458          */
  459         buflen = sizeof(val);
  460         if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
  461             val != htole16(0))
  462                 ic->ic_caps |= IEEE80211_C_WEP;
  463 
  464         /* Find supported rates. */
  465         buflen = sizeof(ratebuf);
  466         rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
  467         if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) {
  468                 nrates = le16toh(*(u_int16_t *)ratebuf);
  469                 if (nrates > IEEE80211_RATE_MAXSIZE)
  470                         nrates = IEEE80211_RATE_MAXSIZE;
  471                 rs->rs_nrates = 0;
  472                 for (i = 0; i < nrates; i++)
  473                         if (ratebuf[2+i])
  474                                 rs->rs_rates[rs->rs_nrates++] = ratebuf[2+i];
  475         } else {
  476                 /* XXX fallback on error? */
  477         }
  478 
  479         buflen = sizeof(val);
  480         if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
  481             wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
  482                 sc->sc_dbm_offset = le16toh(val);
  483         }
  484 
  485         sc->sc_max_datalen = 2304;
  486         sc->sc_system_scale = 1;
  487         sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
  488         sc->sc_roaming_mode = 1;
  489         sc->wi_channel = IEEE80211_CHAN_ANYC;
  490         sc->sc_portnum = WI_DEFAULT_PORT;
  491         sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
  492 
  493         bzero(sc->sc_nodename, sizeof(sc->sc_nodename));
  494         sc->sc_nodelen = sizeof(WI_DEFAULT_NODENAME) - 1;
  495         bcopy(WI_DEFAULT_NODENAME, sc->sc_nodename, sc->sc_nodelen);
  496 
  497         bzero(sc->sc_net_name, sizeof(sc->sc_net_name));
  498         bcopy(WI_DEFAULT_NETNAME, sc->sc_net_name,
  499             sizeof(WI_DEFAULT_NETNAME) - 1);
  500 
  501         /*
  502          * Call MI attach routine.
  503          */
  504         ieee80211_ifattach(ic);
  505         /* override state transition method */
  506         sc->sc_newstate = ic->ic_newstate;
  507         sc->sc_key_alloc = ic->ic_crypto.cs_key_alloc;
  508         ic->ic_crypto.cs_key_alloc = wi_key_alloc;
  509         ic->ic_newstate = wi_newstate;
  510         ic->ic_raw_xmit = wi_raw_xmit;
  511 
  512         ic->ic_scan_start = wi_scan_start;
  513         ic->ic_scan_curchan = wi_scan_curchan;
  514         ic->ic_scan_mindwell = wi_scan_mindwell;
  515         ic->ic_scan_end = wi_scan_end;
  516         ic->ic_set_channel = wi_set_channel;
  517         ic->ic_node_alloc = wi_node_alloc;
  518         ic->ic_updateslot = wi_update_slot;
  519         ic->ic_reset = wi_reset;
  520 
  521         ieee80211_media_init(ic, wi_media_change, wi_media_status);
  522 
  523 #if NBPFILTER > 0
  524         bpfattach2(ifp, DLT_IEEE802_11_RADIO,
  525                 sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
  526                 &sc->sc_drvbpf);
  527         /*
  528          * Initialize constant fields.
  529          * XXX make header lengths a multiple of 32-bits so subsequent
  530          *     headers are properly aligned; this is a kludge to keep
  531          *     certain applications happy.
  532          *
  533          * NB: the channel is setup each time we transition to the
  534          *     RUN state to avoid filling it in for each frame.
  535          */
  536         sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(u_int32_t));
  537         sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
  538         sc->sc_tx_th.wt_ihdr.it_present = htole32(WI_TX_RADIOTAP_PRESENT);
  539 
  540         sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
  541         sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
  542         sc->sc_rx_th.wr_ihdr.it_present = htole32(WI_RX_RADIOTAP_PRESENT);
  543 #endif
  544 
  545         if (bootverbose)
  546                 ieee80211_announce(ic);
  547 
  548         return (0);
  549 }
  550 
  551 int
  552 wi_detach(device_t dev)
  553 {
  554         struct wi_softc *sc = device_get_softc(dev);
  555         struct ifnet *ifp = sc->sc_ifp;
  556 
  557         WI_LOCK(sc);
  558 
  559         /* check if device was removed */
  560         sc->wi_gone |= !bus_child_present(dev);
  561 
  562         wi_stop(ifp, 0);
  563         WI_UNLOCK(sc);
  564 
  565 #if NBPFILTER > 0
  566         bpfdetach(ifp);
  567 #endif
  568         ieee80211_ifdetach(&sc->sc_ic);
  569         bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
  570         if_free(sc->sc_ifp);
  571         wi_free(dev);
  572         mtx_destroy(&sc->sc_mtx);
  573         return (0);
  574 }
  575 
  576 #ifdef __NetBSD__
  577 int
  578 wi_activate(struct device *self, enum devact act)
  579 {
  580         struct wi_softc *sc = (struct wi_softc *)self;
  581         int rv = 0, s;
  582 
  583         s = splnet();
  584         switch (act) {
  585         case DVACT_ACTIVATE:
  586                 rv = EOPNOTSUPP;
  587                 break;
  588 
  589         case DVACT_DEACTIVATE:
  590                 if_deactivate(sc->sc_ifp);
  591                 break;
  592         }
  593         splx(s);
  594         return rv;
  595 }
  596 
  597 void
  598 wi_power(struct wi_softc *sc, int why)
  599 {
  600         struct ifnet *ifp = sc->sc_ifp;
  601         int s;
  602 
  603         s = splnet();
  604         switch (why) {
  605         case PWR_SUSPEND:
  606         case PWR_STANDBY:
  607                 wi_stop(ifp, 1);
  608                 break;
  609         case PWR_RESUME:
  610                 if (ifp->if_flags & IFF_UP) {
  611                         wi_init(sc);
  612                         (void)wi_intr(sc);
  613                 }
  614                 break;
  615         case PWR_SOFTSUSPEND:
  616         case PWR_SOFTSTANDBY:
  617         case PWR_SOFTRESUME:
  618                 break;
  619         }
  620         splx(s);
  621 }
  622 #endif /* __NetBSD__ */
  623 
  624 void
  625 wi_shutdown(device_t dev)
  626 {
  627         struct wi_softc *sc = device_get_softc(dev);
  628 
  629         wi_stop(sc->sc_ifp, 1);
  630 }
  631 
  632 void
  633 wi_intr(void *arg)
  634 {
  635         struct wi_softc *sc = arg;
  636         struct ifnet *ifp = sc->sc_ifp;
  637         u_int16_t status;
  638 
  639         WI_LOCK(sc);
  640 
  641         if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
  642                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  643                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
  644                 WI_UNLOCK(sc);
  645                 return;
  646         }
  647 
  648         /* Disable interrupts. */
  649         CSR_WRITE_2(sc, WI_INT_EN, 0);
  650 
  651         status = CSR_READ_2(sc, WI_EVENT_STAT);
  652         if (status & WI_EV_RX)
  653                 wi_rx_intr(sc);
  654         if (status & WI_EV_ALLOC)
  655                 wi_tx_intr(sc);
  656         if (status & WI_EV_TX_EXC)
  657                 wi_tx_ex_intr(sc);
  658         if (status & WI_EV_INFO)
  659                 wi_info_intr(sc);
  660         if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
  661             (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
  662             !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
  663                 wi_start_locked(ifp);
  664 
  665         /* Re-enable interrupts. */
  666         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  667 
  668         WI_UNLOCK(sc);
  669 
  670         return;
  671 }
  672 
  673 void
  674 wi_init(void *arg)
  675 {
  676         struct wi_softc *sc = arg;
  677         struct ifnet *ifp = sc->sc_ifp;
  678         struct ieee80211com *ic = &sc->sc_ic;
  679         struct wi_joinreq join;
  680         struct ieee80211_channel *chan;
  681         int i;
  682         int error = 0, wasenabled;
  683 
  684 
  685 
  686         if (sc->wi_gone) 
  687                 return;
  688 
  689         if ((wasenabled = sc->sc_enabled))
  690                 wi_stop(ifp, 1);
  691 
  692         WI_LOCK(sc);
  693         wi_reset(ifp);
  694 
  695         /* common 802.11 configuration */
  696         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  697         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
  698         switch (ic->ic_opmode) {
  699         case IEEE80211_M_STA:
  700                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
  701                 break;
  702         case IEEE80211_M_IBSS:
  703                 wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
  704                 ic->ic_flags |= IEEE80211_F_IBSSON;
  705                 break;
  706         case IEEE80211_M_AHDEMO:
  707                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
  708                 break;
  709         case IEEE80211_M_HOSTAP:
  710                 /*
  711                  * For PRISM cards, override the empty SSID, because in
  712                  * HostAP mode the controller will lock up otherwise.
  713                  */
  714                 if (sc->sc_firmware_type == WI_INTERSIL &&
  715                     ic->ic_des_ssid[0].len == 0) {
  716                         ic->ic_des_ssid[0].ssid[0] = ' ';
  717                         ic->ic_des_ssid[0].len = 1;
  718                 }
  719                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
  720                 break;
  721         case IEEE80211_M_MONITOR:
  722                 switch (sc->sc_firmware_type) {
  723                 case WI_LUCENT:
  724                         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
  725                         break;
  726                 
  727                 case WI_INTERSIL:
  728                         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_APSILENT);
  729                         break;
  730                 }
  731 
  732                 wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
  733                 break;
  734         case IEEE80211_M_WDS:
  735                 /* XXXX */
  736                 break;
  737         }
  738 
  739         /* Intersil interprets this RID as joining ESS even in IBSS mode */
  740         if (sc->sc_firmware_type == WI_LUCENT &&
  741             (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_ssid[0].len > 0)
  742                 wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
  743         else
  744                 wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
  745         wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
  746         wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_ssid[0].ssid,
  747             ic->ic_des_ssid[0].len);
  748         wi_write_val(sc, WI_RID_OWN_CHNL,
  749                 ieee80211_chan2ieee(ic, ic->ic_bsschan));
  750         wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_ssid[0].ssid,
  751                 ic->ic_des_ssid[0].len);
  752 
  753         IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
  754         wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
  755 
  756         if (ic->ic_caps & IEEE80211_C_PMGT)
  757                 wi_write_val(sc, WI_RID_PM_ENABLED,
  758                     (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
  759 
  760         /* not yet common 802.11 configuration */
  761         wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
  762         wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold);
  763         if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
  764                 wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold);
  765 
  766         /* driver specific 802.11 configuration */
  767         if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
  768                 wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
  769         if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
  770                 wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
  771         if (sc->sc_flags & WI_FLAGS_HAS_MOR)
  772                 wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
  773         wi_write_txrate(sc);
  774         wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
  775         wi_write_val(sc, WI_RID_ALT_RETRY_CNT, 0); /* for IEEE80211_BPF_NOACK */
  776 
  777         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  778             sc->sc_firmware_type == WI_INTERSIL) {
  779                 wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval);
  780                 wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
  781                 wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
  782                 wi_write_val(sc, WI_RID_DTIM_PERIOD, ic->ic_dtim_period);
  783         }
  784 
  785         /*
  786          * Initialize promisc mode.
  787          *      Being in the Host-AP mode causes a great
  788          *      deal of pain if primisc mode is set.
  789          *      Therefore we avoid confusing the firmware
  790          *      and always reset promisc mode in Host-AP
  791          *      mode.  Host-AP sees all the packets anyway.
  792          */
  793         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
  794             (ifp->if_flags & IFF_PROMISC) != 0) {
  795                 wi_write_val(sc, WI_RID_PROMISC, 1);
  796         } else {
  797                 wi_write_val(sc, WI_RID_PROMISC, 0);
  798         }
  799 
  800         /* Configure WEP. */
  801         if (ic->ic_caps & IEEE80211_C_WEP) {
  802                 sc->sc_cnfauthmode = ic->ic_bss->ni_authmode;
  803                 wi_write_wep(sc);
  804         } else
  805                 sc->sc_encryption = 0;
  806 
  807         /* Set multicast filter. */
  808         wi_write_multi(sc);
  809 
  810         /* Allocate fids for the card */
  811         if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
  812                 sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
  813                 if (sc->sc_firmware_type == WI_SYMBOL)
  814                         sc->sc_buflen = 1585;   /* XXX */
  815                 for (i = 0; i < sc->sc_ntxbuf; i++) {
  816                         error = wi_alloc_fid(sc, sc->sc_buflen,
  817                             &sc->sc_txd[i].d_fid);
  818                         if (error) {
  819                                 device_printf(sc->sc_dev,
  820                                     "tx buffer allocation failed (error %u)\n",
  821                                     error);
  822                                 goto out;
  823                         }
  824                         sc->sc_txd[i].d_len = 0;
  825                 }
  826         }
  827         sc->sc_txcur = sc->sc_txnext = 0;
  828 
  829         /* Enable desired port */
  830         wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
  831 
  832         sc->sc_enabled = 1;
  833         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  834         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  835         if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
  836             ic->ic_opmode == IEEE80211_M_IBSS ||
  837             ic->ic_opmode == IEEE80211_M_MONITOR ||
  838             ic->ic_opmode == IEEE80211_M_HOSTAP) {
  839                 chan = (sc->wi_channel == IEEE80211_CHAN_ANYC) ? 
  840                         ic->ic_curchan : sc->wi_channel;
  841                 ieee80211_create_ibss(ic, chan);
  842         }
  843         /* Enable interrupts */
  844         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  845 
  846         if (!wasenabled &&
  847             ic->ic_opmode == IEEE80211_M_HOSTAP &&
  848             sc->sc_firmware_type == WI_INTERSIL) {
  849                 /* XXX: some card need to be re-enabled for hostap */
  850                 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
  851                 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
  852         }
  853 
  854         if (ic->ic_opmode == IEEE80211_M_STA &&
  855             ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
  856             ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
  857                 memset(&join, 0, sizeof(join));
  858                 if (ic->ic_flags & IEEE80211_F_DESBSSID)
  859                         IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
  860                 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
  861                         join.wi_chan = htole16(
  862                                 ieee80211_chan2ieee(ic, ic->ic_des_chan));
  863                 /* Lucent firmware does not support the JOIN RID. */
  864                 if (sc->sc_firmware_type != WI_LUCENT)
  865                         wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
  866         }
  867 
  868         callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
  869 
  870         WI_UNLOCK(sc);
  871         return;
  872 out:
  873         if (error) {
  874                 if_printf(ifp, "interface not running\n");
  875                 wi_stop(ifp, 1);
  876         }
  877         WI_UNLOCK(sc);
  878         DPRINTF(("wi_init: return %d\n", error));
  879         return;
  880 }
  881 
  882 void
  883 wi_stop(struct ifnet *ifp, int disable)
  884 {
  885         struct wi_softc *sc = ifp->if_softc;
  886         struct ieee80211com *ic = &sc->sc_ic;
  887 
  888         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
  889 
  890         DELAY(100000);
  891         WI_LOCK(sc);
  892         if (sc->sc_enabled && !sc->wi_gone) {
  893                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  894                 wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
  895                 if (disable) {
  896 #ifdef __NetBSD__
  897                         if (sc->sc_disable)
  898                                 (*sc->sc_disable)(sc);
  899 #endif
  900                         sc->sc_enabled = 0;
  901                 }
  902         } else if (sc->wi_gone && disable)      /* gone --> not enabled */
  903             sc->sc_enabled = 0;
  904 
  905         callout_stop(&sc->sc_watchdog);         /* XXX drain */
  906         sc->sc_tx_timer = 0;
  907         sc->sc_scan_timer = 0;
  908         sc->sc_false_syns = 0;
  909         sc->sc_naps = 0;
  910         ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
  911 
  912         WI_UNLOCK(sc);
  913 }
  914 
  915 static void
  916 wi_start_locked(struct ifnet *ifp)
  917 {
  918         struct wi_softc *sc = ifp->if_softc;
  919         struct ieee80211com *ic = &sc->sc_ic;
  920         struct ieee80211_node *ni;
  921         struct ieee80211_frame *wh;
  922         struct ether_header *eh;
  923         struct mbuf *m0;
  924         struct wi_frame frmhdr;
  925         int cur;
  926 
  927         WI_LOCK_ASSERT(sc);
  928 
  929         if (sc->wi_gone)
  930                 return;
  931         if (sc->sc_flags & WI_FLAGS_OUTRANGE)
  932                 return;
  933 
  934         memset(&frmhdr, 0, sizeof(frmhdr));
  935         cur = sc->sc_txnext;
  936         for (;;) {
  937                 IF_POLL(&ic->ic_mgtq, m0);
  938                 if (m0 != NULL) {
  939                         if (sc->sc_txd[cur].d_len != 0) {
  940                                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  941                                 break;
  942                         }
  943                         IF_DEQUEUE(&ic->ic_mgtq, m0);
  944                         /*
  945                          * Hack!  The referenced node pointer is in the
  946                          * rcvif field of the packet header.  This is
  947                          * placed there by ieee80211_mgmt_output because
  948                          * we need to hold the reference with the frame
  949                          * and there's no other way (other than packet
  950                          * tags which we consider too expensive to use)
  951                          * to pass it along.
  952                          */
  953                         ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
  954                         m0->m_pkthdr.rcvif = NULL;
  955 
  956                         m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
  957                             (caddr_t)&frmhdr.wi_ehdr);
  958                         frmhdr.wi_ehdr.ether_type = 0;
  959                         wh = mtod(m0, struct ieee80211_frame *);
  960                 } else {
  961                         if (ic->ic_state != IEEE80211_S_RUN)
  962                                 break;
  963                         IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
  964                         if (m0 == NULL)
  965                                 break;
  966                         if (sc->sc_txd[cur].d_len != 0) {
  967                                 IFQ_DRV_PREPEND(&ifp->if_snd, m0);
  968                                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  969                                 break;
  970                         }
  971                         if (m0->m_len < sizeof(struct ether_header) &&
  972                             (m0 = m_pullup(m0, sizeof(struct ether_header))) == NULL) {
  973                                 ifp->if_oerrors++;
  974                                 continue;
  975                         }
  976                         eh = mtod(m0, struct ether_header *);
  977                         ni = ieee80211_find_txnode(ic, eh->ether_dhost);
  978                         if (ni == NULL) {
  979                                 m_freem(m0);
  980                                 continue;
  981                         }
  982                         ifp->if_opackets++;
  983                         m_copydata(m0, 0, ETHER_HDR_LEN, 
  984                             (caddr_t)&frmhdr.wi_ehdr);
  985 #if NBPFILTER > 0
  986                         BPF_MTAP(ifp, m0);
  987 #endif
  988 
  989                         m0 = ieee80211_encap(ic, m0, ni);
  990                         if (m0 == NULL) {
  991                                 ifp->if_oerrors++;
  992                                 ieee80211_free_node(ni);
  993                                 continue;
  994                         }
  995                         wh = mtod(m0, struct ieee80211_frame *);
  996                 }
  997 #if NBPFILTER > 0
  998                 if (bpf_peers_present(ic->ic_rawbpf))
  999                         bpf_mtap(ic->ic_rawbpf, m0);
 1000 #endif
 1001                 frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
 1002                 /* XXX check key for SWCRYPT instead of using operating mode */
 1003                 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
 1004                     (sc->sc_encryption & HOST_ENCRYPT)) {
 1005                         struct ieee80211_key *k;
 1006 
 1007                         k = ieee80211_crypto_encap(ic, ni, m0);
 1008                         if (k == NULL) {
 1009                                 ieee80211_free_node(ni);
 1010                                 m_freem(m0);
 1011                                 continue;
 1012                         }
 1013                         frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
 1014                 }
 1015 #if NBPFILTER > 0
 1016                 if (bpf_peers_present(sc->sc_drvbpf)) {
 1017                         sc->sc_tx_th.wt_rate =
 1018                                 ni->ni_rates.rs_rates[ni->ni_txrate];
 1019                         bpf_mtap2(sc->sc_drvbpf,
 1020                                 &sc->sc_tx_th, sc->sc_tx_th_len, m0);
 1021                 }
 1022 #endif
 1023                 m_copydata(m0, 0, sizeof(struct ieee80211_frame),
 1024                     (caddr_t)&frmhdr.wi_whdr);
 1025                 m_adj(m0, sizeof(struct ieee80211_frame));
 1026                 frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
 1027                 if (IFF_DUMPPKTS(ifp))
 1028                         wi_dump_pkt(&frmhdr, NULL, -1);
 1029                 ieee80211_free_node(ni);
 1030                 if (wi_start_tx(ifp, &frmhdr, m0))
 1031                         continue;
 1032                 sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
 1033         }
 1034 }
 1035 
 1036 static void
 1037 wi_start(struct ifnet *ifp)
 1038 {
 1039         struct wi_softc *sc = ifp->if_softc;
 1040 
 1041         WI_LOCK(sc);
 1042         wi_start_locked(ifp);
 1043         WI_UNLOCK(sc);
 1044 }
 1045 
 1046 static int
 1047 wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
 1048 {
 1049         struct wi_softc *sc = ifp->if_softc;
 1050         int cur = sc->sc_txnext;
 1051         int fid, off, error;
 1052 
 1053         fid = sc->sc_txd[cur].d_fid;
 1054         off = sizeof(*frmhdr);
 1055         error = wi_write_bap(sc, fid, 0, frmhdr, sizeof(*frmhdr)) != 0
 1056              || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
 1057         m_freem(m0);
 1058         if (error) {
 1059                 ifp->if_oerrors++;
 1060                 return -1;
 1061         }
 1062         sc->sc_txd[cur].d_len = off;
 1063         if (sc->sc_txcur == cur) {
 1064                 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
 1065                         if_printf(ifp, "xmit failed\n");
 1066                         sc->sc_txd[cur].d_len = 0;
 1067                         return -1;
 1068                 }
 1069                 sc->sc_tx_timer = 5;
 1070         }
 1071         return 0;
 1072 }
 1073 
 1074 static int
 1075 wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
 1076             const struct ieee80211_bpf_params *params)
 1077 {
 1078         struct ieee80211com *ic = ni->ni_ic;
 1079         struct ifnet *ifp = ic->ic_ifp;
 1080         struct wi_softc *sc = ifp->if_softc;
 1081         struct ieee80211_frame *wh;
 1082         struct wi_frame frmhdr;
 1083         int cur;
 1084         int rc = 0;
 1085 
 1086         WI_LOCK(sc);
 1087 
 1088         if (sc->wi_gone) {
 1089                 rc = ENETDOWN;
 1090                 goto out;
 1091         }
 1092         if (sc->sc_flags & WI_FLAGS_OUTRANGE) {
 1093                 rc = ENETDOWN;
 1094                 goto out;
 1095         }
 1096 
 1097         memset(&frmhdr, 0, sizeof(frmhdr));
 1098         cur = sc->sc_txnext;
 1099         if (sc->sc_txd[cur].d_len != 0) {
 1100                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 1101                 rc = ENOBUFS;
 1102                 goto out;
 1103         }
 1104         m0->m_pkthdr.rcvif = NULL;
 1105 
 1106         m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
 1107             (caddr_t)&frmhdr.wi_ehdr);
 1108         frmhdr.wi_ehdr.ether_type = 0;
 1109         wh = mtod(m0, struct ieee80211_frame *);
 1110                         
 1111 #if NBPFILTER > 0
 1112         if (bpf_peers_present(ic->ic_rawbpf))
 1113                 bpf_mtap(ic->ic_rawbpf, m0);
 1114 #endif
 1115         frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
 1116         if (params && (params->ibp_flags & IEEE80211_BPF_NOACK))
 1117                 frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_ALTRTRY);
 1118         /* XXX check key for SWCRYPT instead of using operating mode */
 1119         if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
 1120             (sc->sc_encryption & HOST_ENCRYPT)) {
 1121                 if (!params ||
 1122                     (params && (params->ibp_flags & IEEE80211_BPF_CRYPTO))) {
 1123                         struct ieee80211_key *k;
 1124 
 1125                         k = ieee80211_crypto_encap(ic, ni, m0);
 1126                         if (k == NULL) {
 1127                                 rc = ENOMEM;
 1128                                 goto out;
 1129                         }
 1130                         frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
 1131                 }
 1132         }
 1133 #if NBPFILTER > 0
 1134         if (bpf_peers_present(sc->sc_drvbpf)) {
 1135                 sc->sc_tx_th.wt_rate =
 1136                         ni->ni_rates.rs_rates[ni->ni_txrate];
 1137                 bpf_mtap2(sc->sc_drvbpf,
 1138                         &sc->sc_tx_th, sc->sc_tx_th_len, m0);
 1139         }
 1140 #endif
 1141         m_copydata(m0, 0, sizeof(struct ieee80211_frame),
 1142             (caddr_t)&frmhdr.wi_whdr);
 1143         m_adj(m0, sizeof(struct ieee80211_frame));
 1144         frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
 1145         if (IFF_DUMPPKTS(ifp))
 1146                 wi_dump_pkt(&frmhdr, NULL, -1);
 1147         if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
 1148                 m0 = NULL;
 1149                 rc = EIO;
 1150                 goto out;
 1151         }
 1152         m0 = NULL;
 1153 
 1154         sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
 1155 out:
 1156         WI_UNLOCK(sc);
 1157 
 1158         if (m0 != NULL)
 1159                 m_freem(m0);
 1160         ieee80211_free_node(ni);
 1161         return rc;
 1162 }
 1163 
 1164 static int
 1165 wi_reset(struct ifnet *ifp)
 1166 {
 1167         struct wi_softc *sc = ifp->if_softc;
 1168 #define WI_INIT_TRIES 3
 1169         int i;
 1170         int error = 0;
 1171         int tries;
 1172         
 1173         /* Symbol firmware cannot be initialized more than once */
 1174         if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset)
 1175                 return (0);
 1176         if (sc->sc_firmware_type == WI_SYMBOL)
 1177                 tries = 1;
 1178         else
 1179                 tries = WI_INIT_TRIES;
 1180 
 1181         for (i = 0; i < tries; i++) {
 1182                 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
 1183                         break;
 1184                 DELAY(WI_DELAY * 1000);
 1185         }
 1186         sc->sc_reset = 1;
 1187 
 1188         if (i == tries) {
 1189                 if_printf(ifp, "init failed\n");
 1190                 return (error);
 1191         }
 1192 
 1193         CSR_WRITE_2(sc, WI_INT_EN, 0);
 1194         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
 1195 
 1196         /* Calibrate timer. */
 1197         wi_write_val(sc, WI_RID_TICK_TIME, 8);
 1198 
 1199         return (0);
 1200 #undef WI_INIT_TRIES
 1201 }
 1202 
 1203 static void
 1204 wi_watchdog(void *arg)
 1205 {
 1206         struct wi_softc *sc = arg;
 1207         struct ifnet *ifp = sc->sc_ifp;
 1208 
 1209         if (!sc->sc_enabled)
 1210                 return;
 1211 
 1212         if (sc->sc_tx_timer) {
 1213                 if (--sc->sc_tx_timer == 0) {
 1214                         if_printf(ifp, "device timeout\n");
 1215                         ifp->if_oerrors++;
 1216                         wi_init(ifp->if_softc);
 1217                         return;
 1218                 }
 1219         }
 1220 
 1221         if (sc->sc_scan_timer) {
 1222                 if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
 1223                     sc->sc_firmware_type == WI_INTERSIL) {
 1224                         DPRINTF(("wi_watchdog: inquire scan\n"));
 1225                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 1226                 }
 1227         }
 1228 
 1229         /* TODO: rate control */
 1230 
 1231         callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
 1232 }
 1233 
 1234 static int
 1235 wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1236 {
 1237         struct wi_softc *sc = ifp->if_softc;
 1238         struct ieee80211com *ic = &sc->sc_ic;
 1239         int error = 0;
 1240         struct thread *td = curthread;
 1241 #if 0
 1242         struct ifreq *ifr = (struct ifreq *)data;
 1243         struct wi_req wreq;
 1244 #endif
 1245 
 1246         if (sc->wi_gone)
 1247                 return (ENODEV);
 1248 
 1249         switch (cmd) {
 1250         case SIOCSIFFLAGS:
 1251                 /*
 1252                  * Can't do promisc and hostap at the same time.  If all that's
 1253                  * changing is the promisc flag, try to short-circuit a call to
 1254                  * wi_init() by just setting PROMISC in the hardware.
 1255                  */
 1256                 WI_LOCK(sc);
 1257                 if (ifp->if_flags & IFF_UP) {
 1258                         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
 1259                             ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1260                                 if (ifp->if_flags & IFF_PROMISC &&
 1261                                     !(sc->sc_if_flags & IFF_PROMISC)) {
 1262                                         wi_write_val(sc, WI_RID_PROMISC, 1);
 1263                                 } else if (!(ifp->if_flags & IFF_PROMISC) &&
 1264                                     sc->sc_if_flags & IFF_PROMISC) {
 1265                                         wi_write_val(sc, WI_RID_PROMISC, 0);
 1266                                 } else {
 1267                                         wi_init(sc);
 1268                                 }
 1269                         } else {
 1270                                 wi_init(sc);
 1271                         }
 1272                 } else {
 1273                         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1274                                 wi_stop(ifp, 1);
 1275                         }
 1276                         sc->wi_gone = 0;
 1277                 }
 1278                 sc->sc_if_flags = ifp->if_flags;
 1279                 WI_UNLOCK(sc);
 1280                 error = 0;
 1281                 break;
 1282         case SIOCADDMULTI:
 1283         case SIOCDELMULTI:
 1284                 WI_LOCK(sc);
 1285                 error = wi_write_multi(sc);
 1286                 WI_UNLOCK(sc);
 1287                 break;
 1288 #if 0
 1289         case SIOCGIFGENERIC:
 1290                 WI_LOCK(sc);
 1291                 error = wi_get_cfg(ifp, cmd, data);
 1292                 WI_UNLOCK(sc);
 1293                 break;
 1294         case SIOCSIFGENERIC:
 1295                 error = priv_check(td, PRIV_DRIVER);
 1296                 if (error == 0)
 1297                         error = wi_set_cfg(ifp, cmd, data);
 1298                 break;
 1299         case SIOCGPRISM2DEBUG:
 1300                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1301                 if (error)
 1302                         break;
 1303                 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) ||
 1304                     sc->sc_firmware_type == WI_LUCENT) {
 1305                         error = EIO;
 1306                         break;
 1307                 }
 1308                 error = wi_get_debug(sc, &wreq);
 1309                 if (error == 0)
 1310                         error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
 1311                 break;
 1312         case SIOCSPRISM2DEBUG:
 1313                 if ((error = priv_check(td, PRIV_DRIVER)))
 1314                         return (error);
 1315                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1316                 if (error)
 1317                         break;
 1318                 WI_LOCK(sc);
 1319                 error = wi_set_debug(sc, &wreq);
 1320                 WI_UNLOCK(sc);
 1321                 break;
 1322 #endif
 1323         case SIOCG80211:
 1324                 error = wi_ioctl_get(ifp, cmd, data);
 1325                 break;
 1326         case SIOCS80211:
 1327                 error = priv_check(td, PRIV_NET80211_MANAGE);
 1328                 if (error)
 1329                         break;
 1330                 error = wi_ioctl_set(ifp, cmd, data);
 1331 
 1332 
 1333                         break;
 1334         default:
 1335                 error = ieee80211_ioctl(ic, cmd, data);
 1336                 WI_LOCK(sc);
 1337                 if (error == ENETRESET) {
 1338                         if (sc->sc_enabled)
 1339                                 wi_init(sc);    /* XXX no error return */
 1340                         error = 0;
 1341                 }
 1342                 WI_UNLOCK(sc);
 1343                 break;
 1344         }
 1345         return (error);
 1346 }
 1347 
 1348 static int
 1349 wi_ioctl_get(struct ifnet *ifp, u_long cmd, caddr_t data)
 1350 {
 1351         int                 error;
 1352         struct wi_softc     *sc;
 1353         struct ieee80211req *ireq;
 1354         struct ieee80211com *ic;
 1355 
 1356 
 1357         sc = ifp->if_softc;
 1358         ic = &sc->sc_ic;
 1359         ireq = (struct ieee80211req *) data;
 1360 
 1361         switch (ireq->i_type) {
 1362         case IEEE80211_IOC_STATIONNAME:
 1363                 ireq->i_len = sc->sc_nodelen + 1;
 1364                 error = copyout(sc->sc_nodename, ireq->i_data,
 1365                                 ireq->i_len);
 1366                 break;
 1367         default:
 1368                 error = ieee80211_ioctl(ic, cmd, data);
 1369                 WI_LOCK(sc);
 1370                 if (error == ENETRESET) {
 1371                         if (sc->sc_enabled)
 1372                                 wi_init(sc);    /* XXX no error return */
 1373                         error = 0;
 1374                 }
 1375                 WI_UNLOCK(sc);
 1376 
 1377                 break;
 1378         }
 1379         
 1380         return (error);
 1381 }
 1382 
 1383 static int
 1384 wi_ioctl_set(struct ifnet *ifp, u_long cmd, caddr_t data)
 1385 {
 1386         int                 error;
 1387         struct wi_softc     *sc;
 1388         struct ieee80211req *ireq;
 1389         u_int8_t nodename[IEEE80211_NWID_LEN];
 1390                 
 1391         sc = ifp->if_softc;
 1392         ireq = (struct ieee80211req *) data;
 1393         switch (ireq->i_type) {
 1394         case IEEE80211_IOC_STATIONNAME:
 1395                 if (ireq->i_val != 0 ||
 1396                     ireq->i_len > IEEE80211_NWID_LEN) {
 1397                         error = EINVAL;
 1398                         break;
 1399                 }
 1400                 memset(nodename, 0, IEEE80211_NWID_LEN);
 1401                 error = copyin(ireq->i_data, nodename, ireq->i_len);
 1402                 if (error)
 1403                         break;
 1404                 WI_LOCK(sc);
 1405                 if (sc->sc_enabled) {
 1406                         error = wi_write_ssid(sc, WI_RID_NODENAME,
 1407                                               nodename, ireq->i_len);
 1408                 }
 1409                 if (error == 0) {
 1410                         memcpy(sc->sc_nodename, nodename,
 1411                                IEEE80211_NWID_LEN);
 1412                         sc->sc_nodelen = ireq->i_len;
 1413                 }
 1414                 WI_UNLOCK(sc);
 1415                 
 1416                 break;
 1417         default:
 1418                 error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
 1419                 WI_LOCK(sc);
 1420                 if (error == ENETRESET) {
 1421                         if (sc->sc_enabled)
 1422                                 wi_init(sc);    /* XXX no error return */
 1423                         error = 0;
 1424                 }
 1425                 WI_UNLOCK(sc);
 1426                 break;
 1427         }
 1428 
 1429         return (error);
 1430 }
 1431 
 1432 static struct ieee80211_node *
 1433 wi_node_alloc(struct ieee80211_node_table *nt)
 1434 {
 1435         struct wi_node *rn;
 1436 
 1437         rn = malloc(sizeof (struct wi_node), M_80211_NODE,
 1438             M_NOWAIT | M_ZERO);
 1439 
 1440         return (rn != NULL) ? &rn->ni : NULL;
 1441 }
 1442 
 1443 static int
 1444 wi_media_change(struct ifnet *ifp)
 1445 {
 1446         struct wi_softc *sc = ifp->if_softc;
 1447         int error;
 1448 
 1449         error = ieee80211_media_change(ifp);
 1450         if (error == ENETRESET) {
 1451                 if (sc->sc_enabled)
 1452                         wi_init(sc);    /* XXX no error return */
 1453                 error = 0;
 1454         }
 1455         return error;
 1456 }
 1457 
 1458 static void
 1459 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 1460 {
 1461         struct wi_softc *sc = ifp->if_softc;
 1462         struct ieee80211com *ic = &sc->sc_ic;
 1463         u_int16_t val;
 1464         int rate, len;
 1465 
 1466         if (sc->wi_gone) {              /* hardware gone (e.g. ejected) */
 1467                 imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
 1468                 imr->ifm_status = 0;
 1469                 return;
 1470         }
 1471 
 1472         imr->ifm_status = IFM_AVALID;
 1473         imr->ifm_active = IFM_IEEE80211;
 1474         if (!sc->sc_enabled) {          /* port !enabled, have no status */
 1475                 imr->ifm_active |= IFM_NONE;
 1476                 imr->ifm_status = IFM_AVALID;
 1477                 return;
 1478         }
 1479         if (ic->ic_state == IEEE80211_S_RUN &&
 1480             (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
 1481                 imr->ifm_status |= IFM_ACTIVE;
 1482         len = sizeof(val);
 1483         if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) == 0 &&
 1484             len == sizeof(val)) {
 1485                 /* convert to 802.11 rate */
 1486                 val = le16toh(val);
 1487                 rate = val * 2;
 1488                 if (sc->sc_firmware_type == WI_LUCENT) {
 1489                         if (rate == 10)
 1490                                 rate = 11;      /* 5.5Mbps */
 1491                 } else {
 1492                         if (rate == 4*2)
 1493                                 rate = 11;      /* 5.5Mbps */
 1494                         else if (rate == 8*2)
 1495                                 rate = 22;      /* 11Mbps */
 1496                 }
 1497         } else
 1498                 rate = 0;
 1499         imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
 1500         switch (ic->ic_opmode) {
 1501         case IEEE80211_M_STA:
 1502                 break;
 1503         case IEEE80211_M_IBSS:
 1504                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
 1505                 break;
 1506         case IEEE80211_M_AHDEMO:
 1507                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
 1508                 break;
 1509         case IEEE80211_M_HOSTAP:
 1510                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 1511                 break;
 1512         case IEEE80211_M_MONITOR:
 1513                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
 1514                 break;
 1515         case IEEE80211_M_WDS:
 1516                 /* XXXX */
 1517                 break;
 1518         }
 1519 }
 1520 
 1521 static void
 1522 wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
 1523 {
 1524         struct ieee80211com *ic = &sc->sc_ic;
 1525         struct ieee80211_node *ni = ic->ic_bss;
 1526         struct ifnet *ifp = sc->sc_ifp;
 1527 
 1528         if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
 1529                 return;
 1530 
 1531         DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
 1532         DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
 1533 
 1534         /* In promiscuous mode, the BSSID field is not a reliable
 1535          * indicator of the firmware's BSSID. Damp spurious
 1536          * change-of-BSSID indications.
 1537          */
 1538         if ((ifp->if_flags & IFF_PROMISC) != 0 &&
 1539             !ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
 1540                          WI_MAX_FALSE_SYNS))
 1541                 return;
 1542 
 1543         sc->sc_false_syns = MAX(0, sc->sc_false_syns - 1);
 1544 #if 0
 1545         /*
 1546          * XXX hack; we should create a new node with the new bssid
 1547          * and replace the existing ic_bss with it but since we don't
 1548          * process management frames to collect state we cheat by
 1549          * reusing the existing node as we know wi_newstate will be
 1550          * called and it will overwrite the node state.
 1551          */
 1552         ieee80211_sta_join(ic, ieee80211_ref_node(ni));
 1553 #endif
 1554 }
 1555 
 1556 static void
 1557 wi_rx_monitor(struct wi_softc *sc, int fid)
 1558 {
 1559         struct ifnet *ifp = sc->sc_ifp;
 1560         struct wi_frame *rx_frame;
 1561         struct mbuf *m;
 1562         int datlen, hdrlen;
 1563 
 1564         /* first allocate mbuf for packet storage */
 1565         m = m_getcl(M_DONTWAIT, MT_DATA, 0);
 1566         if (m == NULL) {
 1567                 ifp->if_ierrors++;
 1568                 return;
 1569         }
 1570 
 1571         m->m_pkthdr.rcvif = ifp;
 1572 
 1573         /* now read wi_frame first so we know how much data to read */
 1574         if (wi_read_bap(sc, fid, 0, mtod(m, caddr_t), sizeof(*rx_frame))) {
 1575                 ifp->if_ierrors++;
 1576                 goto done;
 1577         }
 1578 
 1579         rx_frame = mtod(m, struct wi_frame *);
 1580 
 1581         switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
 1582         case 7:
 1583                 switch (rx_frame->wi_whdr.i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
 1584                 case IEEE80211_FC0_TYPE_DATA:
 1585                         hdrlen = WI_DATA_HDRLEN;
 1586                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
 1587                         break;
 1588                 case IEEE80211_FC0_TYPE_MGT:
 1589                         hdrlen = WI_MGMT_HDRLEN;
 1590                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
 1591                         break;
 1592                 case IEEE80211_FC0_TYPE_CTL:
 1593                         /*
 1594                          * prism2 cards don't pass control packets
 1595                          * down properly or consistently, so we'll only
 1596                          * pass down the header.
 1597                          */
 1598                         hdrlen = WI_CTL_HDRLEN;
 1599                         datlen = 0;
 1600                         break;
 1601                 default:
 1602                         if_printf(ifp, "received packet of unknown type "
 1603                                 "on port 7\n");
 1604                         ifp->if_ierrors++;
 1605                         goto done;
 1606                 }
 1607                 break;
 1608         case 0:
 1609                 hdrlen = WI_DATA_HDRLEN;
 1610                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
 1611                 break;
 1612         default:
 1613                 if_printf(ifp, "received packet on invalid "
 1614                     "port (wi_status=0x%x)\n", rx_frame->wi_status);
 1615                 ifp->if_ierrors++;
 1616                 goto done;
 1617         }
 1618 
 1619         if (hdrlen + datlen + 2 > MCLBYTES) {
 1620                 if_printf(ifp, "oversized packet received "
 1621                     "(wi_dat_len=%d, wi_status=0x%x)\n",
 1622                     datlen, rx_frame->wi_status);
 1623                 ifp->if_ierrors++;
 1624                 goto done;
 1625         }
 1626 
 1627         if (wi_read_bap(sc, fid, hdrlen, mtod(m, caddr_t) + hdrlen,
 1628             datlen + 2) == 0) {
 1629                 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
 1630                 ifp->if_ipackets++;
 1631                 BPF_MTAP(ifp, m);       /* Handle BPF listeners. */
 1632         } else
 1633                 ifp->if_ierrors++;
 1634 done:
 1635         m_freem(m);
 1636 }
 1637 
 1638 static void
 1639 wi_rx_intr(struct wi_softc *sc)
 1640 {
 1641         struct ieee80211com *ic = &sc->sc_ic;
 1642         struct ifnet *ifp = sc->sc_ifp;
 1643         struct wi_frame frmhdr;
 1644         struct mbuf *m;
 1645         struct ieee80211_frame *wh;
 1646         struct ieee80211_node *ni;
 1647         int fid, len, off, rssi;
 1648         u_int8_t dir;
 1649         u_int16_t status;
 1650         u_int32_t rstamp;
 1651 
 1652         fid = CSR_READ_2(sc, WI_RX_FID);
 1653 
 1654         if (sc->wi_debug.wi_monitor) {
 1655                 /*
 1656                  * If we are in monitor mode just
 1657                  * read the data from the device.
 1658                  */
 1659                 wi_rx_monitor(sc, fid);
 1660                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1661                 return;
 1662         }
 1663 
 1664         /* First read in the frame header */
 1665         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
 1666                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1667                 ifp->if_ierrors++;
 1668                 DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
 1669                 return;
 1670         }
 1671 
 1672         if (IFF_DUMPPKTS(ifp))
 1673                 wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
 1674 
 1675         /*
 1676          * Drop undecryptable or packets with receive errors here
 1677          */
 1678         status = le16toh(frmhdr.wi_status);
 1679         if (status & WI_STAT_ERRSTAT) {
 1680                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1681                 ifp->if_ierrors++;
 1682                 DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
 1683                 return;
 1684         }
 1685         rssi = frmhdr.wi_rx_signal;
 1686         rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
 1687             le16toh(frmhdr.wi_rx_tstamp1);
 1688 
 1689         len = le16toh(frmhdr.wi_dat_len);
 1690         off = ALIGN(sizeof(struct ieee80211_frame));
 1691 
 1692         /*
 1693          * Sometimes the PRISM2.x returns bogusly large frames. Except
 1694          * in monitor mode, just throw them away.
 1695          */
 1696         if (off + len > MCLBYTES) {
 1697                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
 1698                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1699                         ifp->if_ierrors++;
 1700                         DPRINTF(("wi_rx_intr: oversized packet\n"));
 1701                         return;
 1702                 } else
 1703                         len = 0;
 1704         }
 1705 
 1706         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1707         if (m == NULL) {
 1708                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1709                 ifp->if_ierrors++;
 1710                 DPRINTF(("wi_rx_intr: MGET failed\n"));
 1711                 return;
 1712         }
 1713         if (off + len > MHLEN) {
 1714                 MCLGET(m, M_DONTWAIT);
 1715                 if ((m->m_flags & M_EXT) == 0) {
 1716                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1717                         m_freem(m);
 1718                         ifp->if_ierrors++;
 1719                         DPRINTF(("wi_rx_intr: MCLGET failed\n"));
 1720                         return;
 1721                 }
 1722         }
 1723 
 1724         m->m_data += off - sizeof(struct ieee80211_frame);
 1725         memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
 1726         wi_read_bap(sc, fid, sizeof(frmhdr),
 1727             m->m_data + sizeof(struct ieee80211_frame), len);
 1728         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
 1729         m->m_pkthdr.rcvif = ifp;
 1730 
 1731         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
 1732 
 1733 #if NBPFILTER > 0
 1734         if (bpf_peers_present(sc->sc_drvbpf)) {
 1735                 /* XXX replace divide by table */
 1736                 sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
 1737                 sc->sc_rx_th.wr_antsignal = frmhdr.wi_rx_signal;
 1738                 sc->sc_rx_th.wr_antnoise = frmhdr.wi_rx_silence;
 1739                 sc->sc_rx_th.wr_flags = 0;
 1740                 if (frmhdr.wi_status & WI_STAT_PCF)
 1741                         sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_CFP;
 1742                 /* XXX IEEE80211_RADIOTAP_F_WEP */
 1743                 bpf_mtap2(sc->sc_drvbpf,
 1744                         &sc->sc_rx_th, sc->sc_rx_th_len, m);
 1745         }
 1746 #endif
 1747         wh = mtod(m, struct ieee80211_frame *);
 1748         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 1749                 /*
 1750                  * WEP is decrypted by hardware and the IV
 1751                  * is stripped.  Clear WEP bit so we don't
 1752                  * try to process it in ieee80211_input.
 1753                  * XXX fix for TKIP, et. al.
 1754                  */
 1755                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
 1756         }
 1757 
 1758         /* synchronize driver's BSSID with firmware's BSSID */
 1759         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
 1760         if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
 1761                 wi_sync_bssid(sc, wh->i_addr3);
 1762 
 1763         WI_UNLOCK(sc);
 1764         /*
 1765          * Locate the node for sender, track state, and
 1766          * then pass this node (referenced) up to the 802.11
 1767          * layer for its use.
 1768          */
 1769         ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *) wh);
 1770         /*
 1771          * Send frame up for processing.
 1772          */
 1773         ieee80211_input(ic, m, ni, rssi, -95/*XXXXwi_rx_silence?*/, rstamp);
 1774         /*
 1775          * The frame may have caused the node to be marked for
 1776          * reclamation (e.g. in response to a DEAUTH message)
 1777          * so use free_node here instead of unref_node.
 1778          */
 1779         ieee80211_free_node(ni);
 1780 
 1781         WI_LOCK(sc);
 1782 }
 1783 
 1784 static void
 1785 wi_tx_ex_intr(struct wi_softc *sc)
 1786 {
 1787         struct ifnet *ifp = sc->sc_ifp;
 1788         struct wi_frame frmhdr;
 1789         int fid;
 1790 
 1791         fid = CSR_READ_2(sc, WI_TX_CMP_FID);
 1792         /* Read in the frame header */
 1793         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) == 0) {
 1794                 u_int16_t status = le16toh(frmhdr.wi_status);
 1795 
 1796                 /*
 1797                  * Spontaneous station disconnects appear as xmit
 1798                  * errors.  Don't announce them and/or count them
 1799                  * as an output error.
 1800                  */
 1801                 if ((status & WI_TXSTAT_DISCONNECT) == 0) {
 1802                         if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
 1803                                 if_printf(ifp, "tx failed");
 1804                                 if (status & WI_TXSTAT_RET_ERR)
 1805                                         printf(", retry limit exceeded");
 1806                                 if (status & WI_TXSTAT_AGED_ERR)
 1807                                         printf(", max transmit lifetime exceeded");
 1808                                 if (status & WI_TXSTAT_DISCONNECT)
 1809                                         printf(", port disconnected");
 1810                                 if (status & WI_TXSTAT_FORM_ERR)
 1811                                         printf(", invalid format (data len %u src %6D)",
 1812                                                 le16toh(frmhdr.wi_dat_len),
 1813                                                 frmhdr.wi_ehdr.ether_shost, ":");
 1814                                 if (status & ~0xf)
 1815                                         printf(", status=0x%x", status);
 1816                                 printf("\n");
 1817                         }
 1818                         ifp->if_oerrors++;
 1819                 } else {
 1820                         DPRINTF(("port disconnected\n"));
 1821                         ifp->if_collisions++;   /* XXX */
 1822                 }
 1823         } else
 1824                 DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid));
 1825         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
 1826 }
 1827 
 1828 static void
 1829 wi_tx_intr(struct wi_softc *sc)
 1830 {
 1831         struct ifnet *ifp = sc->sc_ifp;
 1832         int fid, cur;
 1833 
 1834         if (sc->wi_gone)
 1835                 return;
 1836 
 1837         fid = CSR_READ_2(sc, WI_ALLOC_FID);
 1838         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 1839 
 1840         cur = sc->sc_txcur;
 1841         if (sc->sc_txd[cur].d_fid != fid) {
 1842                 if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
 1843                     fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
 1844                 return;
 1845         }
 1846         sc->sc_tx_timer = 0;
 1847         sc->sc_txd[cur].d_len = 0;
 1848         sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
 1849         if (sc->sc_txd[cur].d_len == 0)
 1850                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 1851         else {
 1852                 if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
 1853                     0, 0)) {
 1854                         if_printf(ifp, "xmit failed\n");
 1855                         sc->sc_txd[cur].d_len = 0;
 1856                 } else {
 1857                         sc->sc_tx_timer = 5;
 1858                 }
 1859         }
 1860 }
 1861 
 1862 static void
 1863 wi_info_intr(struct wi_softc *sc)
 1864 {
 1865         struct ieee80211com *ic = &sc->sc_ic;
 1866         struct ifnet *ifp = sc->sc_ifp;
 1867         int i, fid, len, off;
 1868         u_int16_t ltbuf[2];
 1869         u_int16_t stat;
 1870         u_int32_t *ptr;
 1871 
 1872         fid = CSR_READ_2(sc, WI_INFO_FID);
 1873         wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
 1874 
 1875         switch (le16toh(ltbuf[1])) {
 1876 
 1877         case WI_INFO_LINK_STAT:
 1878                 wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
 1879                 DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
 1880                 switch (le16toh(stat)) {
 1881                 case WI_INFO_LINK_STAT_CONNECTED:
 1882                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 1883                         if (ic->ic_state == IEEE80211_S_RUN &&
 1884                             ic->ic_opmode != IEEE80211_M_IBSS)
 1885                                 break;
 1886                         /* FALLTHROUGH */
 1887                 case WI_INFO_LINK_STAT_AP_CHG:
 1888                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 1889                         break;
 1890                 case WI_INFO_LINK_STAT_AP_INR:
 1891                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 1892                         break;
 1893                 case WI_INFO_LINK_STAT_AP_OOR:
 1894                         if (sc->sc_firmware_type == WI_SYMBOL &&
 1895                             sc->sc_scan_timer > 0) {
 1896                                 if (wi_cmd(sc, WI_CMD_INQUIRE,
 1897                                     WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
 1898                                         sc->sc_scan_timer = 0;
 1899                                 break;
 1900                         }
 1901                         if (ic->ic_opmode == IEEE80211_M_STA)
 1902                                 sc->sc_flags |= WI_FLAGS_OUTRANGE;
 1903                         break;
 1904                 case WI_INFO_LINK_STAT_DISCONNECTED:
 1905                 case WI_INFO_LINK_STAT_ASSOC_FAILED:
 1906                         if (ic->ic_opmode == IEEE80211_M_STA)
 1907                                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 1908                         break;
 1909                 }
 1910                 break;
 1911 
 1912         case WI_INFO_COUNTERS:
 1913                 /* some card versions have a larger stats structure */
 1914                 len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
 1915                 ptr = (u_int32_t *)&sc->sc_stats;
 1916                 off = sizeof(ltbuf);
 1917                 for (i = 0; i < len; i++, off += 2, ptr++) {
 1918                         wi_read_bap(sc, fid, off, &stat, sizeof(stat));
 1919 #ifdef WI_HERMES_STATS_WAR
 1920                         if (stat & 0xf000)
 1921                                 stat = ~stat;
 1922 #endif
 1923                         *ptr += stat;
 1924                 }
 1925                 ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
 1926                     sc->sc_stats.wi_tx_multi_retries +
 1927                     sc->sc_stats.wi_tx_retry_limit;
 1928                 break;
 1929 
 1930         case WI_INFO_SCAN_RESULTS:
 1931         case WI_INFO_HOST_SCAN_RESULTS:
 1932                 wi_scan_result(sc, fid, le16toh(ltbuf[0]));
 1933                 ieee80211_scan_done(ic);
 1934                 break;
 1935 
 1936         default:
 1937                 DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
 1938                     le16toh(ltbuf[1]), le16toh(ltbuf[0])));
 1939                 break;
 1940         }
 1941         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
 1942 }
 1943 
 1944 static int
 1945 wi_write_multi(struct wi_softc *sc)
 1946 {
 1947         struct ifnet *ifp = sc->sc_ifp;
 1948         int n;
 1949         struct ifmultiaddr *ifma;
 1950         struct wi_mcast mlist;
 1951 
 1952         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
 1953 allmulti:
 1954                 memset(&mlist, 0, sizeof(mlist));
 1955                 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
 1956                     sizeof(mlist));
 1957         }
 1958 
 1959         n = 0;
 1960         IF_ADDR_LOCK(ifp);
 1961         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1962                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1963                         continue;
 1964                 if (n >= 16)
 1965                         goto allmulti;
 1966                 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
 1967                     (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
 1968                 n++;
 1969         }
 1970         IF_ADDR_UNLOCK(ifp);
 1971         return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
 1972             IEEE80211_ADDR_LEN * n);
 1973 }
 1974 
 1975 static void
 1976 wi_read_nicid(struct wi_softc *sc)
 1977 {
 1978         struct wi_card_ident *id;
 1979         char *p;
 1980         int len;
 1981         u_int16_t ver[4];
 1982 
 1983         /* getting chip identity */
 1984         memset(ver, 0, sizeof(ver));
 1985         len = sizeof(ver);
 1986         wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
 1987         device_printf(sc->sc_dev, "using ");
 1988 
 1989         sc->sc_firmware_type = WI_NOTYPE;
 1990         for (id = wi_card_ident; id->card_name != NULL; id++) {
 1991                 if (le16toh(ver[0]) == id->card_id) {
 1992                         printf("%s", id->card_name);
 1993                         sc->sc_firmware_type = id->firm_type;
 1994                         break;
 1995                 }
 1996         }
 1997         if (sc->sc_firmware_type == WI_NOTYPE) {
 1998                 if (le16toh(ver[0]) & 0x8000) {
 1999                         printf("Unknown PRISM2 chip");
 2000                         sc->sc_firmware_type = WI_INTERSIL;
 2001                 } else {
 2002                         printf("Unknown Lucent chip");
 2003                         sc->sc_firmware_type = WI_LUCENT;
 2004                 }
 2005         }
 2006 
 2007         /* get primary firmware version (Only Prism chips) */
 2008         if (sc->sc_firmware_type != WI_LUCENT) {
 2009                 memset(ver, 0, sizeof(ver));
 2010                 len = sizeof(ver);
 2011                 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
 2012                 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
 2013                     le16toh(ver[3]) * 100 + le16toh(ver[1]);
 2014         }
 2015 
 2016         /* get station firmware version */
 2017         memset(ver, 0, sizeof(ver));
 2018         len = sizeof(ver);
 2019         wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
 2020         sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
 2021             le16toh(ver[3]) * 100 + le16toh(ver[1]);
 2022         if (sc->sc_firmware_type == WI_INTERSIL &&
 2023             (sc->sc_sta_firmware_ver == 10102 ||
 2024              sc->sc_sta_firmware_ver == 20102)) {
 2025                 char ident[12];
 2026                 memset(ident, 0, sizeof(ident));
 2027                 len = sizeof(ident);
 2028                 /* value should be the format like "V2.00-11" */
 2029                 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
 2030                     *(p = (char *)ident) >= 'A' &&
 2031                     p[2] == '.' && p[5] == '-' && p[8] == '\0') {
 2032                         sc->sc_firmware_type = WI_SYMBOL;
 2033                         sc->sc_sta_firmware_ver = (p[1] - '') * 10000 +
 2034                             (p[3] - '') * 1000 + (p[4] - '') * 100 +
 2035                             (p[6] - '') * 10 + (p[7] - '');
 2036                 }
 2037         }
 2038         printf("\n");
 2039         device_printf(sc->sc_dev, "%s Firmware: ",
 2040              sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
 2041             (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
 2042         if (sc->sc_firmware_type != WI_LUCENT)  /* XXX */
 2043                 printf("Primary (%u.%u.%u), ",
 2044                     sc->sc_pri_firmware_ver / 10000,
 2045                     (sc->sc_pri_firmware_ver % 10000) / 100,
 2046                     sc->sc_pri_firmware_ver % 100);
 2047         printf("Station (%u.%u.%u)\n",
 2048             sc->sc_sta_firmware_ver / 10000,
 2049             (sc->sc_sta_firmware_ver % 10000) / 100,
 2050             sc->sc_sta_firmware_ver % 100);
 2051 }
 2052 
 2053 static int
 2054 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
 2055 {
 2056         struct wi_ssid ssid;
 2057 
 2058         if (buflen > IEEE80211_NWID_LEN)
 2059                 return ENOBUFS;
 2060         memset(&ssid, 0, sizeof(ssid));
 2061         ssid.wi_len = htole16(buflen);
 2062         memcpy(ssid.wi_ssid, buf, buflen);
 2063         return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
 2064 }
 2065 
 2066 #if 0
 2067 static int
 2068 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
 2069 {
 2070         struct wi_softc *sc = ifp->if_softc;
 2071         struct ieee80211com *ic = &sc->sc_ic;
 2072         struct ifreq *ifr = (struct ifreq *)data;
 2073         struct wi_req wreq;
 2074         struct wi_scan_res *res;
 2075         size_t reslen;
 2076         int len, n, error, mif, val, off, i;
 2077 
 2078         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 2079         if (error)
 2080                 return error;
 2081         len = (wreq.wi_len - 1) * 2;
 2082         if (len < sizeof(u_int16_t))
 2083                 return ENOSPC;
 2084         if (len > sizeof(wreq.wi_val))
 2085                 len = sizeof(wreq.wi_val);
 2086 
 2087         switch (wreq.wi_type) {
 2088 
 2089         case WI_RID_IFACE_STATS:
 2090                 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
 2091                 if (len < sizeof(sc->sc_stats))
 2092                         error = ENOSPC;
 2093                 else
 2094                         len = sizeof(sc->sc_stats);
 2095                 break;
 2096 
 2097         case WI_RID_ENCRYPTION:
 2098         case WI_RID_TX_CRYPT_KEY:
 2099         case WI_RID_DEFLT_CRYPT_KEYS:
 2100         case WI_RID_TX_RATE:
 2101                 return ieee80211_ioctl(ic, cmd, data);
 2102 
 2103         case WI_RID_MICROWAVE_OVEN:
 2104                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
 2105                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2106                             &len);
 2107                         break;
 2108                 }
 2109                 wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
 2110                 len = sizeof(u_int16_t);
 2111                 break;
 2112 
 2113         case WI_RID_DBM_ADJUST:
 2114                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
 2115                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2116                             &len);
 2117                         break;
 2118                 }
 2119                 wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
 2120                 len = sizeof(u_int16_t);
 2121                 break;
 2122 
 2123         case WI_RID_ROAMING_MODE:
 2124                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
 2125                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2126                             &len);
 2127                         break;
 2128                 }
 2129                 wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
 2130                 len = sizeof(u_int16_t);
 2131                 break;
 2132 
 2133         case WI_RID_SYSTEM_SCALE:
 2134                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
 2135                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2136                             &len);
 2137                         break;
 2138                 }
 2139                 wreq.wi_val[0] = htole16(sc->sc_system_scale);
 2140                 len = sizeof(u_int16_t);
 2141                 break;
 2142 
 2143         case WI_RID_FRAG_THRESH:
 2144                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
 2145                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2146                             &len);
 2147                         break;
 2148                 }
 2149                 wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
 2150                 len = sizeof(u_int16_t);
 2151                 break;
 2152 
 2153         case WI_RID_READ_APS:
 2154                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 2155                         return ieee80211_ioctl(ic, cmd, data);
 2156                 if (sc->sc_scan_timer > 0) {
 2157                         error = EINPROGRESS;
 2158                         break;
 2159                 }
 2160                 n = sc->sc_naps;
 2161                 if (len < sizeof(n)) {
 2162                         error = ENOSPC;
 2163                         break;
 2164                 }
 2165                 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
 2166                         n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
 2167                 len = sizeof(n) + sizeof(struct wi_apinfo) * n;
 2168                 memcpy(wreq.wi_val, &n, sizeof(n));
 2169                 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
 2170                     sizeof(struct wi_apinfo) * n);
 2171                 break;
 2172 
 2173         case WI_RID_PRISM2:
 2174                 wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
 2175                 len = sizeof(u_int16_t);
 2176                 break;
 2177 
 2178         case WI_RID_MIF:
 2179                 mif = wreq.wi_val[0];
 2180                 error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
 2181                 val = CSR_READ_2(sc, WI_RESP0);
 2182                 wreq.wi_val[0] = val;
 2183                 len = sizeof(u_int16_t);
 2184                 break;
 2185 
 2186         case WI_RID_ZERO_CACHE:
 2187         case WI_RID_PROCFRAME:          /* ignore for compatibility */
 2188                 /* XXX ??? */
 2189                 break;
 2190 
 2191         case WI_RID_READ_CACHE:
 2192                 return ieee80211_ioctl(ic, cmd, data);
 2193 
 2194         case WI_RID_SCAN_RES:           /* compatibility interface */
 2195                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 2196                         return ieee80211_ioctl(ic, cmd, data);
 2197                 if (sc->sc_scan_timer > 0) {
 2198                         error = EINPROGRESS;
 2199                         break;
 2200                 }
 2201                 n = sc->sc_naps;
 2202                 if (sc->sc_firmware_type == WI_LUCENT) {
 2203                         off = 0;
 2204                         reslen = WI_WAVELAN_RES_SIZE;
 2205                 } else {
 2206                         off = sizeof(struct wi_scan_p2_hdr);
 2207                         reslen = WI_PRISM2_RES_SIZE;
 2208                 }
 2209                 if (len < off + reslen * n)
 2210                         n = (len - off) / reslen;
 2211                 len = off + reslen * n;
 2212                 if (off != 0) {
 2213                         struct wi_scan_p2_hdr *p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
 2214                         /*
 2215                          * Prepend Prism-specific header.
 2216                          */
 2217                         if (len < sizeof(struct wi_scan_p2_hdr)) {
 2218                                 error = ENOSPC;
 2219                                 break;
 2220                         }
 2221                         p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
 2222                         p2->wi_rsvd = 0;
 2223                         p2->wi_reason = n;      /* XXX */
 2224                 }
 2225                 for (i = 0; i < n; i++, off += reslen) {
 2226                         const struct wi_apinfo *ap = &sc->sc_aps[i];
 2227 
 2228                         res = (struct wi_scan_res *)((char *)wreq.wi_val + off);
 2229                         res->wi_chan = ap->channel;
 2230                         res->wi_noise = ap->noise;
 2231                         res->wi_signal = ap->signal;
 2232                         IEEE80211_ADDR_COPY(res->wi_bssid, ap->bssid);
 2233                         res->wi_interval = ap->interval;
 2234                         res->wi_capinfo = ap->capinfo;
 2235                         res->wi_ssid_len = ap->namelen;
 2236                         memcpy(res->wi_ssid, ap->name,
 2237                                 IEEE80211_NWID_LEN);
 2238                         if (sc->sc_firmware_type != WI_LUCENT) {
 2239                                 /* XXX not saved from Prism cards */
 2240                                 memset(res->wi_srates, 0,
 2241                                         sizeof(res->wi_srates));
 2242                                 res->wi_rate = ap->rate;
 2243                                 res->wi_rsvd = 0;
 2244                         }
 2245                 }
 2246                 break;
 2247 
 2248         default:
 2249                 if (sc->sc_enabled) {
 2250                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2251                             &len);
 2252                         break;
 2253                 }
 2254                 switch (wreq.wi_type) {
 2255                 case WI_RID_MAX_DATALEN:
 2256                         wreq.wi_val[0] = htole16(sc->sc_max_datalen);
 2257                         len = sizeof(u_int16_t);
 2258                         break;
 2259                 case WI_RID_RTS_THRESH:
 2260                         wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
 2261                         len = sizeof(u_int16_t);
 2262                         break;
 2263                 case WI_RID_CNFAUTHMODE:
 2264                         wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
 2265                         len = sizeof(u_int16_t);
 2266                         break;
 2267                 case WI_RID_NODENAME:
 2268                         if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
 2269                                 error = ENOSPC;
 2270                                 break;
 2271                         }
 2272                         len = sc->sc_nodelen + sizeof(u_int16_t);
 2273                         wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
 2274                         memcpy(&wreq.wi_val[1], sc->sc_nodename,
 2275                             sc->sc_nodelen);
 2276                         break;
 2277                 default:
 2278                         return ieee80211_ioctl(ic, cmd, data);
 2279                 }
 2280                 break;
 2281         }
 2282         if (error)
 2283                 return error;
 2284         wreq.wi_len = (len + 1) / 2 + 1;
 2285         return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
 2286 }
 2287 
 2288 static int
 2289 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
 2290 {
 2291         struct wi_softc *sc = ifp->if_softc;
 2292         struct ieee80211com *ic = &sc->sc_ic;
 2293         struct ifreq *ifr = (struct ifreq *)data;
 2294         struct wi_req wreq;
 2295         struct mbuf *m;
 2296         int i, len, error, mif, val;
 2297         struct ieee80211_rateset *rs;
 2298 
 2299         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 2300         if (error)
 2301                 return error;
 2302         len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
 2303         switch (wreq.wi_type) {
 2304         case WI_RID_DBM_ADJUST:
 2305                 return ENODEV;
 2306 
 2307         case WI_RID_NODENAME:
 2308                 if (le16toh(wreq.wi_val[0]) * 2 > len ||
 2309                     le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
 2310                         error = ENOSPC;
 2311                         break;
 2312                 }
 2313                 WI_LOCK(sc);
 2314                 if (sc->sc_enabled)
 2315                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2316                             len);
 2317                 if (error == 0) {
 2318                         sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
 2319                         memcpy(sc->sc_nodename, &wreq.wi_val[1],
 2320                                 sc->sc_nodelen);
 2321                 }
 2322                 WI_UNLOCK(sc);
 2323                 break;
 2324 
 2325         case WI_RID_MICROWAVE_OVEN:
 2326         case WI_RID_ROAMING_MODE:
 2327         case WI_RID_SYSTEM_SCALE:
 2328         case WI_RID_FRAG_THRESH:
 2329                 /* XXX unlocked reads */
 2330                 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
 2331                     (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
 2332                         break;
 2333                 if (wreq.wi_type == WI_RID_ROAMING_MODE &&
 2334                     (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
 2335                         break;
 2336                 if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
 2337                     (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
 2338                         break;
 2339                 if (wreq.wi_type == WI_RID_FRAG_THRESH &&
 2340                     (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
 2341                         break;
 2342                 /* FALLTHROUGH */
 2343         case WI_RID_RTS_THRESH:
 2344         case WI_RID_CNFAUTHMODE:
 2345         case WI_RID_MAX_DATALEN:
 2346                 WI_LOCK(sc);
 2347                 if (sc->sc_enabled) {
 2348                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2349                             sizeof(u_int16_t));
 2350                         if (error != 0) {
 2351                                 WI_UNLOCK(sc);
 2352                                 break;
 2353                         }
 2354                 }
 2355                 switch (wreq.wi_type) {
 2356                 case WI_RID_FRAG_THRESH:
 2357                         ic->ic_fragthreshold = le16toh(wreq.wi_val[0]);
 2358                         break;
 2359                 case WI_RID_RTS_THRESH:
 2360                         ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]);
 2361                         break;
 2362                 case WI_RID_MICROWAVE_OVEN:
 2363                         sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
 2364                         break;
 2365                 case WI_RID_ROAMING_MODE:
 2366                         sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
 2367                         break;
 2368                 case WI_RID_SYSTEM_SCALE:
 2369                         sc->sc_system_scale = le16toh(wreq.wi_val[0]);
 2370                         break;
 2371                 case WI_RID_CNFAUTHMODE:
 2372                         sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
 2373                         break;
 2374                 case WI_RID_MAX_DATALEN:
 2375                         sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
 2376                         break;
 2377                 }
 2378                 WI_UNLOCK(sc);
 2379                 break;
 2380 
 2381         case WI_RID_TX_RATE:
 2382                 WI_LOCK(sc);
 2383                 switch (le16toh(wreq.wi_val[0])) {
 2384                 case 3:
 2385                         ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
 2386                         break;
 2387                 default:
 2388                         rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
 2389                         for (i = 0; i < rs->rs_nrates; i++) {
 2390                                 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
 2391                                     / 2 == le16toh(wreq.wi_val[0]))
 2392                                         break;
 2393                         }
 2394                         if (i == rs->rs_nrates) {
 2395                                 WI_UNLOCK(sc);
 2396                                 return EINVAL;
 2397                         }
 2398                         ic->ic_fixed_rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
 2399                 }
 2400                 if (sc->sc_enabled)
 2401                         error = wi_write_txrate(sc);
 2402                 WI_UNLOCK(sc);
 2403                 break;
 2404 
 2405         case WI_RID_SCAN_APS:
 2406                 WI_LOCK(sc);
 2407                 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
 2408                         error = wi_scan_ap(sc, 0x3fff, 0x000f);
 2409                 WI_UNLOCK(sc);
 2410                 break;
 2411 
 2412         case WI_RID_SCAN_REQ:           /* compatibility interface */
 2413                 WI_LOCK(sc);
 2414                 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
 2415                         error = wi_scan_ap(sc, wreq.wi_val[0], wreq.wi_val[1]);
 2416                 WI_UNLOCK(sc);
 2417                 break;
 2418 
 2419         case WI_RID_MGMT_XMIT:
 2420                 WI_LOCK(sc);
 2421                 if (!sc->sc_enabled)
 2422                         error = ENETDOWN;
 2423                 else if (ic->ic_mgtq.ifq_len > 5)
 2424                         error = EAGAIN;
 2425                 else {
 2426                         /* NB: m_devget uses M_DONTWAIT so can hold the lock */
 2427                         /* XXX wi_len looks in u_int8_t, not in u_int16_t */
 2428                         m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0,
 2429                                 ifp, NULL);
 2430                         if (m != NULL)
 2431                                 IF_ENQUEUE(&ic->ic_mgtq, m);
 2432                         else
 2433                                 error = ENOMEM;
 2434                 }
 2435                 WI_UNLOCK(sc);
 2436                 break;
 2437 
 2438         case WI_RID_MIF:
 2439                 mif = wreq.wi_val[0];
 2440                 val = wreq.wi_val[1];
 2441                 WI_LOCK(sc);
 2442                 error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
 2443                 WI_UNLOCK(sc);
 2444                 break;
 2445 
 2446         case WI_RID_PROCFRAME:          /* ignore for compatibility */
 2447                 break;
 2448 
 2449         case WI_RID_OWN_SSID:
 2450                 if (le16toh(wreq.wi_val[0]) * 2 > len ||
 2451                     le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
 2452                         error = ENOSPC;
 2453                         break;
 2454                 }
 2455                 WI_LOCK(sc);
 2456                 memset(ic->ic_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN);
 2457                 ic->ic_des_ssid[0].len = le16toh(wreq.wi_val[0]) * 2;
 2458                 memcpy(ic->ic_des_ssid[0].ssid, &wreq.wi_val[1],
 2459                         ic->ic_des_ssid[0].len);
 2460                 if (sc->sc_enabled)
 2461                         wi_init(sc);    /* XXX no error return */
 2462                 WI_UNLOCK(sc);
 2463                 break;
 2464 
 2465         default:
 2466                 WI_LOCK(sc);
 2467                 if (sc->sc_enabled)
 2468                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2469                             len);
 2470                 if (error == 0) {
 2471                         /* XXX ieee80211_ioctl does a copyin */
 2472                         error = ieee80211_ioctl(ic, cmd, data);
 2473                         if (error == ENETRESET) {
 2474                                 if (sc->sc_enabled)
 2475                                         wi_init(sc);
 2476                                 error = 0;
 2477                         }
 2478                 }
 2479                 WI_UNLOCK(sc);
 2480                 break;
 2481         }
 2482         return error;
 2483 }
 2484 #endif
 2485 
 2486 static int
 2487 wi_write_txrate(struct wi_softc *sc)
 2488 {
 2489         struct ieee80211com *ic = &sc->sc_ic;
 2490         int i;
 2491         u_int16_t rate;
 2492 
 2493         if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
 2494                 rate = 0;       /* auto */
 2495         else
 2496                 rate = ic->ic_fixed_rate / 2;
 2497 
 2498         /* rate: 0, 1, 2, 5, 11 */
 2499 
 2500         switch (sc->sc_firmware_type) {
 2501         case WI_LUCENT:
 2502                 switch (rate) {
 2503                 case 0:                 /* auto == 11mbps auto */
 2504                         rate = 3;
 2505                         break;
 2506                 /* case 1, 2 map to 1, 2*/
 2507                 case 5:                 /* 5.5Mbps -> 4 */
 2508                         rate = 4;
 2509                         break;
 2510                 case 11:                /* 11mbps -> 5 */
 2511                         rate = 5;
 2512                         break;
 2513                 default:
 2514                         break;
 2515                 }
 2516                 break;
 2517         default:
 2518                 /* Choose a bit according to this table.
 2519                  *
 2520                  * bit | data rate
 2521                  * ----+-------------------
 2522                  * 0   | 1Mbps
 2523                  * 1   | 2Mbps
 2524                  * 2   | 5.5Mbps
 2525                  * 3   | 11Mbps
 2526                  */
 2527                 for (i = 8; i > 0; i >>= 1) {
 2528                         if (rate >= i)
 2529                                 break;
 2530                 }
 2531                 if (i == 0)
 2532                         rate = 0xf;     /* auto */
 2533                 else
 2534                         rate = i;
 2535                 break;
 2536         }
 2537         return wi_write_val(sc, WI_RID_TX_RATE, rate);
 2538 }
 2539 
 2540 static int
 2541 wi_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k,
 2542         ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
 2543 {
 2544         struct wi_softc *sc = ic->ic_ifp->if_softc;
 2545 
 2546         /*
 2547          * When doing host encryption of outbound frames fail requests
 2548          * for keys that are not marked w/ the SWCRYPT flag so the
 2549          * net80211 layer falls back to s/w crypto.  Note that we also
 2550          * fixup existing keys below to handle mode changes.
 2551          */
 2552         if ((sc->sc_encryption & HOST_ENCRYPT) &&
 2553             (k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0)
 2554                 return 0;
 2555         return sc->sc_key_alloc(ic, k, keyix, rxkeyix);
 2556 }
 2557 
 2558 static int
 2559 wi_write_wep(struct wi_softc *sc)
 2560 {
 2561         struct ieee80211com *ic = &sc->sc_ic;
 2562         int error = 0;
 2563         int i, keylen;
 2564         u_int16_t val;
 2565         struct wi_key wkey[IEEE80211_WEP_NKID];
 2566 
 2567         switch (sc->sc_firmware_type) {
 2568         case WI_LUCENT:
 2569                 val = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0;
 2570                 error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
 2571                 if (error)
 2572                         break;
 2573                 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
 2574                         break;
 2575                 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_def_txkey);
 2576                 if (error)
 2577                         break;
 2578                 memset(wkey, 0, sizeof(wkey));
 2579                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
 2580                         keylen = ic->ic_nw_keys[i].wk_keylen;
 2581                         wkey[i].wi_keylen = htole16(keylen);
 2582                         memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
 2583                             keylen);
 2584                 }
 2585                 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
 2586                     wkey, sizeof(wkey));
 2587                 sc->sc_encryption = 0;
 2588                 break;
 2589 
 2590         case WI_INTERSIL:
 2591         case WI_SYMBOL:
 2592                 if (ic->ic_flags & IEEE80211_F_PRIVACY) {
 2593                         /*
 2594                          * ONLY HWB3163 EVAL-CARD Firmware version
 2595                          * less than 0.8 variant2
 2596                          *
 2597                          *   If promiscuous mode disable, Prism2 chip
 2598                          *  does not work with WEP .
 2599                          * It is under investigation for details.
 2600                          * (ichiro@netbsd.org)
 2601                          */
 2602                         if (sc->sc_firmware_type == WI_INTERSIL &&
 2603                             sc->sc_sta_firmware_ver < 802 ) {
 2604                                 /* firm ver < 0.8 variant 2 */
 2605                                 wi_write_val(sc, WI_RID_PROMISC, 1);
 2606                         }
 2607                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
 2608                             sc->sc_cnfauthmode);
 2609                         /* XXX should honor IEEE80211_F_DROPUNENC */
 2610                         val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
 2611                         /*
 2612                          * Encryption firmware has a bug for HostAP mode.
 2613                          */
 2614                         if (sc->sc_firmware_type == WI_INTERSIL &&
 2615                             ic->ic_opmode == IEEE80211_M_HOSTAP)
 2616                                 val |= HOST_ENCRYPT;
 2617                 } else {
 2618                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
 2619                             IEEE80211_AUTH_OPEN);
 2620                         val = HOST_ENCRYPT | HOST_DECRYPT;
 2621                 }
 2622                 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
 2623                 if (error)
 2624                         break;
 2625                 sc->sc_encryption = val;
 2626                 if ((val & PRIVACY_INVOKED) == 0)
 2627                         break;
 2628                 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
 2629                     ic->ic_def_txkey);
 2630                 if (error)
 2631                         break;
 2632                 if (val & HOST_DECRYPT)
 2633                         break;
 2634                 /*
 2635                  * It seems that the firmware accept 104bit key only if
 2636                  * all the keys have 104bit length.  We get the length of
 2637                  * the transmit key and use it for all other keys.
 2638                  * Perhaps we should use software WEP for such situation.
 2639                  */
 2640                 if (ic->ic_def_txkey != IEEE80211_KEYIX_NONE)
 2641                         keylen = ic->ic_nw_keys[ic->ic_def_txkey].wk_keylen;
 2642                 else    /* XXX should not hapen */
 2643                         keylen = IEEE80211_WEP_KEYLEN;
 2644                 if (keylen > IEEE80211_WEP_KEYLEN)
 2645                         keylen = 13;    /* 104bit keys */
 2646                 else
 2647                         keylen = IEEE80211_WEP_KEYLEN;
 2648                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
 2649                         error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
 2650                             ic->ic_nw_keys[i].wk_key, keylen);
 2651                         if (error)
 2652                                 break;
 2653                 }
 2654                 break;
 2655         }
 2656         /*
 2657          * XXX horrible hack; insure pre-existing keys are
 2658          * setup properly to do s/w crypto.
 2659          */
 2660         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
 2661                 struct ieee80211_key *k = &ic->ic_nw_keys[i];
 2662                 if (k->wk_flags & IEEE80211_KEY_XMIT) {
 2663                         if (sc->sc_encryption & HOST_ENCRYPT)
 2664                                 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
 2665                         else
 2666                                 k->wk_flags &= ~IEEE80211_KEY_SWCRYPT;
 2667                 }
 2668         }
 2669         return error;
 2670 }
 2671 
 2672 static int
 2673 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
 2674 {
 2675         int                     i, s = 0;
 2676         
 2677         if (sc->wi_gone)
 2678                 return (ENODEV);
 2679 
 2680         /* wait for the busy bit to clear */
 2681         for (i = sc->wi_cmd_count; i > 0; i--) {        /* 500ms */
 2682                 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
 2683                         break;
 2684                 DELAY(1*1000);  /* 1ms */
 2685         }
 2686         if (i == 0) {
 2687                 device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
 2688                 sc->wi_gone = 1;
 2689                 return(ETIMEDOUT);
 2690         }
 2691 
 2692         CSR_WRITE_2(sc, WI_PARAM0, val0);
 2693         CSR_WRITE_2(sc, WI_PARAM1, val1);
 2694         CSR_WRITE_2(sc, WI_PARAM2, val2);
 2695         CSR_WRITE_2(sc, WI_COMMAND, cmd);
 2696 
 2697         if (cmd == WI_CMD_INI) {
 2698                 /* XXX: should sleep here. */
 2699                 DELAY(100*1000);                /* 100ms delay for init */
 2700         }
 2701         for (i = 0; i < WI_TIMEOUT; i++) {
 2702                 /*
 2703                  * Wait for 'command complete' bit to be
 2704                  * set in the event status register.
 2705                  */
 2706                 s = CSR_READ_2(sc, WI_EVENT_STAT);
 2707                 if (s & WI_EV_CMD) {
 2708                         /* Ack the event and read result code. */
 2709                         s = CSR_READ_2(sc, WI_STATUS);
 2710                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
 2711                         if (s & WI_STAT_CMD_RESULT) {
 2712                                 return(EIO);
 2713                         }
 2714                         break;
 2715                 }
 2716                 DELAY(WI_DELAY);
 2717         }
 2718 
 2719         if (i == WI_TIMEOUT) {
 2720                 device_printf(sc->sc_dev,
 2721                     "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
 2722                 if (s == 0xffff)
 2723                         sc->wi_gone = 1;
 2724                 return(ETIMEDOUT);
 2725         }
 2726         return (0);
 2727 }
 2728 
 2729 static int
 2730 wi_seek_bap(struct wi_softc *sc, int id, int off)
 2731 {
 2732         int i, status;
 2733 
 2734         CSR_WRITE_2(sc, WI_SEL0, id);
 2735         CSR_WRITE_2(sc, WI_OFF0, off);
 2736 
 2737         for (i = 0; ; i++) {
 2738                 status = CSR_READ_2(sc, WI_OFF0);
 2739                 if ((status & WI_OFF_BUSY) == 0)
 2740                         break;
 2741                 if (i == WI_TIMEOUT) {
 2742                         device_printf(sc->sc_dev, "timeout in wi_seek to %x/%x\n",
 2743                             id, off);
 2744                         sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2745                         if (status == 0xffff)
 2746                                 sc->wi_gone = 1;
 2747                         return ETIMEDOUT;
 2748                 }
 2749                 DELAY(1);
 2750         }
 2751         if (status & WI_OFF_ERR) {
 2752                 device_printf(sc->sc_dev, "failed in wi_seek to %x/%x\n", id, off);
 2753                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2754                 return EIO;
 2755         }
 2756         sc->sc_bap_id = id;
 2757         sc->sc_bap_off = off;
 2758         return 0;
 2759 }
 2760 
 2761 static int
 2762 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
 2763 {
 2764         u_int16_t *ptr;
 2765         int i, error, cnt;
 2766 
 2767         if (buflen == 0)
 2768                 return 0;
 2769         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
 2770                 if ((error = wi_seek_bap(sc, id, off)) != 0)
 2771                         return error;
 2772         }
 2773         cnt = (buflen + 1) / 2;
 2774         ptr = (u_int16_t *)buf;
 2775         for (i = 0; i < cnt; i++)
 2776                 *ptr++ = CSR_READ_2(sc, WI_DATA0);
 2777         sc->sc_bap_off += cnt * 2;
 2778         return 0;
 2779 }
 2780 
 2781 static int
 2782 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
 2783 {
 2784         u_int16_t *ptr;
 2785         int i, error, cnt;
 2786 
 2787         if (buflen == 0)
 2788                 return 0;
 2789 
 2790 #ifdef WI_HERMES_AUTOINC_WAR
 2791   again:
 2792 #endif
 2793         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
 2794                 if ((error = wi_seek_bap(sc, id, off)) != 0)
 2795                         return error;
 2796         }
 2797         cnt = (buflen + 1) / 2;
 2798         ptr = (u_int16_t *)buf;
 2799         for (i = 0; i < cnt; i++)
 2800                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
 2801         sc->sc_bap_off += cnt * 2;
 2802 
 2803 #ifdef WI_HERMES_AUTOINC_WAR
 2804         /*
 2805          * According to the comments in the HCF Light code, there is a bug
 2806          * in the Hermes (or possibly in certain Hermes firmware revisions)
 2807          * where the chip's internal autoincrement counter gets thrown off
 2808          * during data writes:  the autoincrement is missed, causing one
 2809          * data word to be overwritten and subsequent words to be written to
 2810          * the wrong memory locations. The end result is that we could end
 2811          * up transmitting bogus frames without realizing it. The workaround
 2812          * for this is to write a couple of extra guard words after the end
 2813          * of the transfer, then attempt to read then back. If we fail to
 2814          * locate the guard words where we expect them, we preform the
 2815          * transfer over again.
 2816          */
 2817         if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
 2818                 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
 2819                 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
 2820                 wi_seek_bap(sc, id, sc->sc_bap_off);
 2821                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2822                 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
 2823                     CSR_READ_2(sc, WI_DATA0) != 0x5678) {
 2824                         device_printf(sc->sc_dev,
 2825                                 "detect auto increment bug, try again\n");
 2826                         goto again;
 2827                 }
 2828         }
 2829 #endif
 2830         return 0;
 2831 }
 2832 
 2833 static int
 2834 wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
 2835 {
 2836         int error, len;
 2837         struct mbuf *m;
 2838 
 2839         for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
 2840                 if (m->m_len == 0)
 2841                         continue;
 2842 
 2843                 len = min(m->m_len, totlen);
 2844 
 2845                 if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
 2846                         m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
 2847                         return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
 2848                             totlen);
 2849                 }
 2850 
 2851                 if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
 2852                         return error;
 2853 
 2854                 off += m->m_len;
 2855                 totlen -= len;
 2856         }
 2857         return 0;
 2858 }
 2859 
 2860 static int
 2861 wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
 2862 {
 2863         int i;
 2864 
 2865         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
 2866                 device_printf(sc->sc_dev, "failed to allocate %d bytes on NIC\n",
 2867                     len);
 2868                 return ENOMEM;
 2869         }
 2870 
 2871         for (i = 0; i < WI_TIMEOUT; i++) {
 2872                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
 2873                         break;
 2874                 DELAY(1);
 2875         }
 2876         if (i == WI_TIMEOUT) {
 2877                 device_printf(sc->sc_dev, "timeout in alloc\n");
 2878                 return ETIMEDOUT;
 2879         }
 2880         *idp = CSR_READ_2(sc, WI_ALLOC_FID);
 2881         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 2882         return 0;
 2883 }
 2884 
 2885 static int
 2886 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
 2887 {
 2888         int error, len;
 2889         u_int16_t ltbuf[2];
 2890 
 2891         /* Tell the NIC to enter record read mode. */
 2892         error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
 2893         if (error)
 2894                 return error;
 2895 
 2896         error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
 2897         if (error)
 2898                 return error;
 2899 
 2900         if (le16toh(ltbuf[1]) != rid) {
 2901                 device_printf(sc->sc_dev, "record read mismatch, rid=%x, got=%x\n",
 2902                     rid, le16toh(ltbuf[1]));
 2903                 return EIO;
 2904         }
 2905         len = (le16toh(ltbuf[0]) - 1) * 2;       /* already got rid */
 2906         if (*buflenp < len) {
 2907                 device_printf(sc->sc_dev, "record buffer is too small, "
 2908                     "rid=%x, size=%d, len=%d\n",
 2909                     rid, *buflenp, len);
 2910                 return ENOSPC;
 2911         }
 2912         *buflenp = len;
 2913         return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
 2914 }
 2915 
 2916 static int
 2917 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
 2918 {
 2919         int error;
 2920         u_int16_t ltbuf[2];
 2921 
 2922         ltbuf[0] = htole16((buflen + 1) / 2 + 1);        /* includes rid */
 2923         ltbuf[1] = htole16(rid);
 2924 
 2925         error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
 2926         if (error)
 2927                 return error;
 2928         error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
 2929         if (error)
 2930                 return error;
 2931 
 2932         return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
 2933 }
 2934 
 2935 static int
 2936 wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 2937 {
 2938         struct ifnet *ifp = ic->ic_ifp;
 2939         struct wi_softc *sc = ifp->if_softc;
 2940         struct ieee80211_node *ni;
 2941         int buflen;
 2942         u_int16_t val;
 2943         struct wi_ssid ssid;
 2944         u_int8_t old_bssid[IEEE80211_ADDR_LEN];
 2945 
 2946         DPRINTF(("%s: %s -> %s\n", __func__,
 2947                 ieee80211_state_name[ic->ic_state],
 2948                 ieee80211_state_name[nstate]));
 2949 
 2950         /*
 2951          * Internal to the driver the INIT and RUN states are used
 2952          * so bypass the net80211 state machine for other states.
 2953          * Beware however that this requires use to net80211 state
 2954          * management that otherwise would be handled for us.
 2955          */
 2956         switch (nstate) {
 2957         case IEEE80211_S_INIT:
 2958                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 2959                 return (*sc->sc_newstate)(ic, nstate, arg);
 2960 
 2961         case IEEE80211_S_SCAN:
 2962                 return (*sc->sc_newstate)(ic, nstate, arg);
 2963 
 2964         case IEEE80211_S_AUTH:
 2965         case IEEE80211_S_ASSOC:
 2966                 ic->ic_state = nstate;  /* NB: skip normal ieee80211 handling */
 2967                 break;
 2968 
 2969         case IEEE80211_S_RUN:
 2970                 ni = ic->ic_bss;
 2971                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 2972                 buflen = IEEE80211_ADDR_LEN;
 2973                 IEEE80211_ADDR_COPY(old_bssid, ni->ni_bssid);
 2974                 wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
 2975                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
 2976                 buflen = sizeof(val);
 2977                 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
 2978                 ni->ni_chan = ieee80211_find_channel(ic,
 2979                     ieee80211_ieee2mhz(val, IEEE80211_CHAN_B),
 2980                     IEEE80211_CHAN_B);
 2981                 if (ni->ni_chan == NULL)
 2982                         ni->ni_chan = &ic->ic_channels[0];
 2983                 ic->ic_curchan = ic->ic_bsschan = ni->ni_chan;
 2984 #if NBPFILTER > 0
 2985                 sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
 2986                         htole16(ni->ni_chan->ic_freq);
 2987                 sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
 2988                         htole16(ni->ni_chan->ic_flags);
 2989 #endif
 2990                 /*
 2991                  * XXX hack; unceremoniously clear 
 2992                  * IEEE80211_F_DROPUNENC when operating with
 2993                  * wep enabled so we don't drop unencoded frames
 2994                  * at the 802.11 layer.  This is necessary because
 2995                  * we must strip the WEP bit from the 802.11 header
 2996                  * before passing frames to ieee80211_input because
 2997                  * the card has already stripped the WEP crypto 
 2998                  * header from the packet.
 2999                  */
 3000                 if (ic->ic_flags & IEEE80211_F_PRIVACY)
 3001                         ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
 3002                 if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
 3003                         /* XXX check return value */
 3004                         buflen = sizeof(ssid);
 3005                         wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
 3006                         ni->ni_esslen = le16toh(ssid.wi_len);
 3007                         if (ni->ni_esslen > IEEE80211_NWID_LEN)
 3008                                 ni->ni_esslen = IEEE80211_NWID_LEN;     /*XXX*/
 3009                         memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
 3010                 }
 3011                 return (*sc->sc_newstate)(ic, nstate, arg);
 3012         default:
 3013                 break;
 3014         }
 3015         return 0;
 3016 }
 3017 
 3018 static int
 3019 wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
 3020 {
 3021         int error = 0;
 3022         u_int16_t val[2];
 3023 
 3024         if (!sc->sc_enabled)
 3025                 return ENXIO;
 3026         switch (sc->sc_firmware_type) {
 3027         case WI_LUCENT:
 3028                 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 3029                 break;
 3030         case WI_INTERSIL:
 3031                 val[0] = htole16(chanmask);     /* channel */
 3032                 val[1] = htole16(txrate);       /* tx rate */
 3033                 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
 3034                 break;
 3035         case WI_SYMBOL:
 3036                 /*
 3037                  * XXX only supported on 3.x ?
 3038                  */
 3039                 val[0] = BSCAN_BCAST | BSCAN_ONETIME;
 3040                 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
 3041                     val, sizeof(val[0]));
 3042                 break;
 3043         }
 3044         if (error == 0) {
 3045                 sc->sc_scan_timer = WI_SCAN_WAIT;
 3046                 DPRINTF(("wi_scan_ap: start scanning, "
 3047                         "chamask 0x%x txrate 0x%x\n", chanmask, txrate));
 3048         }
 3049         return error;
 3050 }
 3051 
 3052 static void
 3053 wi_scan_result(struct wi_softc *sc, int fid, int cnt)
 3054 {
 3055 #define N(a)    (sizeof (a) / sizeof (a[0]))
 3056         int i, naps, off, szbuf;
 3057         struct wi_scan_header ws_hdr;   /* Prism2 header */
 3058         struct wi_scan_data_p2 ws_dat;  /* Prism2 scantable*/
 3059         struct wi_apinfo *ap;
 3060         struct ieee80211_scanparams sp;
 3061         struct ieee80211_frame wh;
 3062         static long rstamp;
 3063         struct ieee80211com *ic;
 3064         uint8_t ssid[2+IEEE80211_NWID_LEN];
 3065 
 3066         ic = &sc->sc_ic;
 3067         rstamp++;
 3068         memset(&sp, 0, sizeof(sp));
 3069 
 3070         off = sizeof(u_int16_t) * 2;
 3071         memset(&ws_hdr, 0, sizeof(ws_hdr));
 3072         switch (sc->sc_firmware_type) {
 3073         case WI_INTERSIL:
 3074                 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
 3075                 off += sizeof(ws_hdr);
 3076                 szbuf = sizeof(struct wi_scan_data_p2);
 3077                 break;
 3078         case WI_SYMBOL:
 3079                 szbuf = sizeof(struct wi_scan_data_p2) + 6;
 3080                 break;
 3081         case WI_LUCENT:
 3082                 szbuf = sizeof(struct wi_scan_data);
 3083                 break;
 3084         default:
 3085                 device_printf(sc->sc_dev,
 3086                         "wi_scan_result: unknown firmware type %u\n",
 3087                         sc->sc_firmware_type);
 3088                 naps = 0;
 3089                 goto done;
 3090         }
 3091         naps = (cnt * 2 + 2 - off) / szbuf;
 3092         if (naps > N(sc->sc_aps))
 3093                 naps = N(sc->sc_aps);
 3094         sc->sc_naps = naps;
 3095         /* Read Data */
 3096         ap = sc->sc_aps;
 3097         memset(&ws_dat, 0, sizeof(ws_dat));
 3098 
 3099         for (i = 0; i < naps; i++, ap++) {
 3100                 uint8_t rates[2 + IEEE80211_RATE_MAXSIZE];
 3101                 uint16_t *bssid;
 3102                 wi_read_bap(sc, fid, off, &ws_dat,
 3103                     (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
 3104                 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
 3105                     ether_sprintf(ws_dat.wi_bssid)));
 3106 
 3107                 off += szbuf;
 3108                 ap->scanreason = le16toh(ws_hdr.wi_reason);             
 3109                 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
 3110                 
 3111                 bssid = (uint16_t *)&ap->bssid;
 3112                 if (bssid[0] == 0 && bssid[1] == 0 && bssid[2] == 0)
 3113                         break;
 3114 
 3115                 memcpy(wh.i_addr2, ws_dat.wi_bssid, sizeof(ap->bssid));
 3116                 memcpy(wh.i_addr3, ws_dat.wi_bssid, sizeof(ap->bssid));
 3117                 ap->channel = le16toh(ws_dat.wi_chid);
 3118                 ap->signal  = le16toh(ws_dat.wi_signal);
 3119                 ap->noise   = le16toh(ws_dat.wi_noise);
 3120                 ap->quality = ap->signal - ap->noise;
 3121                 sp.capinfo = ap->capinfo = le16toh(ws_dat.wi_capinfo);
 3122                 sp.bintval = ap->interval = le16toh(ws_dat.wi_interval);
 3123                 ap->rate = le16toh(ws_dat.wi_rate);
 3124                 rates[1] = 1;
 3125                 rates[2] = (uint8_t)ap->rate / 5;
 3126                 ap->namelen = le16toh(ws_dat.wi_namelen);
 3127                 if (ap->namelen > sizeof(ap->name))
 3128                         ap->namelen = sizeof(ap->name);
 3129                 memcpy(ap->name, ws_dat.wi_name, ap->namelen);
 3130                 sp.ssid = (uint8_t *)&ssid[0];
 3131                 memcpy(sp.ssid + 2, ap->name, ap->namelen);
 3132                 sp.ssid[1] = ap->namelen;
 3133                 sp.bchan = ap->channel;
 3134                 sp.curchan = ieee80211_find_channel(ic,
 3135                         ieee80211_ieee2mhz(ap->channel, IEEE80211_CHAN_B),
 3136                         IEEE80211_CHAN_B);
 3137                 if (sp.curchan == NULL)
 3138                         sp.curchan = &ic->ic_channels[0];
 3139                 sp.rates = &rates[0];
 3140                 sp.tstamp = (uint8_t *)&rstamp;
 3141                 DPRINTF(("calling add_scan, bssid %s chan %d signal %d\n",
 3142                     ether_sprintf(ws_dat.wi_bssid), ap->channel, ap->signal));
 3143                 ieee80211_add_scan(ic, &sp, &wh, 0, ap->signal, ap->noise, rstamp);
 3144         }
 3145 done:
 3146         /* Done scanning */
 3147         sc->sc_scan_timer = 0;
 3148         DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
 3149 #undef N
 3150 }
 3151 
 3152 static void
 3153 wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
 3154 {
 3155         if (ni != NULL)
 3156                 ieee80211_dump_pkt(ni->ni_ic,
 3157                     (u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
 3158                     ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL,
 3159                     rssi);
 3160         printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
 3161                 le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
 3162                 le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
 3163         printf(" rx_signal %u rx_rate %u rx_flow %u\n",
 3164                 wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
 3165         printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
 3166                 wh->wi_tx_rtry, wh->wi_tx_rate,
 3167                 le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
 3168         printf(" ehdr dst %6D src %6D type 0x%x\n",
 3169                 wh->wi_ehdr.ether_dhost, ":", wh->wi_ehdr.ether_shost, ":",
 3170                 wh->wi_ehdr.ether_type);
 3171 }
 3172 
 3173 int
 3174 wi_alloc(device_t dev, int rid)
 3175 {
 3176         struct wi_softc *sc = device_get_softc(dev);
 3177 
 3178         if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
 3179                 sc->iobase_rid = rid;
 3180                 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
 3181                     &sc->iobase_rid, 0, ~0, (1 << 6),
 3182                     rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
 3183                 if (!sc->iobase) {
 3184                         device_printf(dev, "No I/O space?!\n");
 3185                         return (ENXIO);
 3186                 }
 3187 
 3188                 sc->wi_io_addr = rman_get_start(sc->iobase);
 3189                 sc->wi_btag = rman_get_bustag(sc->iobase);
 3190                 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
 3191         } else {
 3192                 sc->mem_rid = rid;
 3193                 sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 3194                     &sc->mem_rid, RF_ACTIVE);
 3195 
 3196                 if (!sc->mem) {
 3197                         device_printf(dev, "No Mem space on prism2.5?\n");
 3198                         return (ENXIO);
 3199                 }
 3200 
 3201                 sc->wi_btag = rman_get_bustag(sc->mem);
 3202                 sc->wi_bhandle = rman_get_bushandle(sc->mem);
 3203         }
 3204 
 3205 
 3206         sc->irq_rid = 0;
 3207         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
 3208             RF_ACTIVE |
 3209             ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
 3210 
 3211         if (!sc->irq) {
 3212                 wi_free(dev);
 3213                 device_printf(dev, "No irq?!\n");
 3214                 return (ENXIO);
 3215         }
 3216 
 3217         sc->sc_dev = dev;
 3218         sc->sc_unit = device_get_unit(dev);
 3219 
 3220         return (0);
 3221 }
 3222 
 3223 void
 3224 wi_free(device_t dev)
 3225 {
 3226         struct wi_softc *sc = device_get_softc(dev);
 3227 
 3228         if (sc->iobase != NULL) {
 3229                 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
 3230                 sc->iobase = NULL;
 3231         }
 3232         if (sc->irq != NULL) {
 3233                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
 3234                 sc->irq = NULL;
 3235         }
 3236         if (sc->mem != NULL) {
 3237                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
 3238                 sc->mem = NULL;
 3239         }
 3240 
 3241         return;
 3242 }
 3243 
 3244 #if 0
 3245 static int
 3246 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
 3247 {
 3248         int error = 0;
 3249 
 3250         wreq->wi_len = 1;
 3251 
 3252         switch (wreq->wi_type) {
 3253         case WI_DEBUG_SLEEP:
 3254                 wreq->wi_len++;
 3255                 wreq->wi_val[0] = sc->wi_debug.wi_sleep;
 3256                 break;
 3257         case WI_DEBUG_DELAYSUPP:
 3258                 wreq->wi_len++;
 3259                 wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
 3260                 break;
 3261         case WI_DEBUG_TXSUPP:
 3262                 wreq->wi_len++;
 3263                 wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
 3264                 break;
 3265         case WI_DEBUG_MONITOR:
 3266                 wreq->wi_len++;
 3267                 wreq->wi_val[0] = sc->wi_debug.wi_monitor;
 3268                 break;
 3269         case WI_DEBUG_LEDTEST:
 3270                 wreq->wi_len += 3;
 3271                 wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
 3272                 wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
 3273                 wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
 3274                 break;
 3275         case WI_DEBUG_CONTTX:
 3276                 wreq->wi_len += 2;
 3277                 wreq->wi_val[0] = sc->wi_debug.wi_conttx;
 3278                 wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
 3279                 break;
 3280         case WI_DEBUG_CONTRX:
 3281                 wreq->wi_len++;
 3282                 wreq->wi_val[0] = sc->wi_debug.wi_contrx;
 3283                 break;
 3284         case WI_DEBUG_SIGSTATE:
 3285                 wreq->wi_len += 2;
 3286                 wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
 3287                 wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
 3288                 break;
 3289         case WI_DEBUG_CONFBITS:
 3290                 wreq->wi_len += 2;
 3291                 wreq->wi_val[0] = sc->wi_debug.wi_confbits;
 3292                 wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
 3293                 break;
 3294         default:
 3295                 error = EIO;
 3296                 break;
 3297         }
 3298 
 3299         return (error);
 3300 }
 3301 
 3302 static int
 3303 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
 3304 {
 3305         int error = 0;
 3306         u_int16_t               cmd, param0 = 0, param1 = 0;
 3307 
 3308         switch (wreq->wi_type) {
 3309         case WI_DEBUG_RESET:
 3310         case WI_DEBUG_INIT:
 3311         case WI_DEBUG_CALENABLE:
 3312                 break;
 3313         case WI_DEBUG_SLEEP:
 3314                 sc->wi_debug.wi_sleep = 1;
 3315                 break;
 3316         case WI_DEBUG_WAKE:
 3317                 sc->wi_debug.wi_sleep = 0;
 3318                 break;
 3319         case WI_DEBUG_CHAN:
 3320                 param0 = wreq->wi_val[0];
 3321                 break;
 3322         case WI_DEBUG_DELAYSUPP:
 3323                 sc->wi_debug.wi_delaysupp = 1;
 3324                 break;
 3325         case WI_DEBUG_TXSUPP:
 3326                 sc->wi_debug.wi_txsupp = 1;
 3327                 break;
 3328         case WI_DEBUG_MONITOR:
 3329                 sc->wi_debug.wi_monitor = 1;
 3330                 break;
 3331         case WI_DEBUG_LEDTEST:
 3332                 param0 = wreq->wi_val[0];
 3333                 param1 = wreq->wi_val[1];
 3334                 sc->wi_debug.wi_ledtest = 1;
 3335                 sc->wi_debug.wi_ledtest_param0 = param0;
 3336                 sc->wi_debug.wi_ledtest_param1 = param1;
 3337                 break;
 3338         case WI_DEBUG_CONTTX:
 3339                 param0 = wreq->wi_val[0];
 3340                 sc->wi_debug.wi_conttx = 1;
 3341                 sc->wi_debug.wi_conttx_param0 = param0;
 3342                 break;
 3343         case WI_DEBUG_STOPTEST:
 3344                 sc->wi_debug.wi_delaysupp = 0;
 3345                 sc->wi_debug.wi_txsupp = 0;
 3346                 sc->wi_debug.wi_monitor = 0;
 3347                 sc->wi_debug.wi_ledtest = 0;
 3348                 sc->wi_debug.wi_ledtest_param0 = 0;
 3349                 sc->wi_debug.wi_ledtest_param1 = 0;
 3350                 sc->wi_debug.wi_conttx = 0;
 3351                 sc->wi_debug.wi_conttx_param0 = 0;
 3352                 sc->wi_debug.wi_contrx = 0;
 3353                 sc->wi_debug.wi_sigstate = 0;
 3354                 sc->wi_debug.wi_sigstate_param0 = 0;
 3355                 break;
 3356         case WI_DEBUG_CONTRX:
 3357                 sc->wi_debug.wi_contrx = 1;
 3358                 break;
 3359         case WI_DEBUG_SIGSTATE:
 3360                 param0 = wreq->wi_val[0];
 3361                 sc->wi_debug.wi_sigstate = 1;
 3362                 sc->wi_debug.wi_sigstate_param0 = param0;
 3363                 break;
 3364         case WI_DEBUG_CONFBITS:
 3365                 param0 = wreq->wi_val[0];
 3366                 param1 = wreq->wi_val[1];
 3367                 sc->wi_debug.wi_confbits = param0;
 3368                 sc->wi_debug.wi_confbits_param0 = param1;
 3369                 break;
 3370         default:
 3371                 error = EIO;
 3372                 break;
 3373         }
 3374 
 3375         if (error)
 3376                 return (error);
 3377 
 3378         cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
 3379         error = wi_cmd(sc, cmd, param0, param1, 0);
 3380 
 3381         return (error);
 3382 }
 3383 #endif
 3384 
 3385 /*
 3386  * Special routines to download firmware for Symbol CF card.
 3387  * XXX: This should be modified generic into any PRISM-2 based card.
 3388  */
 3389 
 3390 #define WI_SBCF_PDIADDR         0x3100
 3391 
 3392 /* unaligned load little endian */
 3393 #define GETLE32(p)      ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
 3394 #define GETLE16(p)      ((p)[0] | ((p)[1]<<8))
 3395 
 3396 int
 3397 wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
 3398     const void *secsym, int seclen)
 3399 {
 3400         uint8_t ebuf[256];
 3401         int i;
 3402 
 3403         /* load primary code and run it */
 3404         wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
 3405         if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
 3406                 return EIO;
 3407         wi_symbol_set_hcr(sc, WI_HCR_RUN);
 3408         for (i = 0; ; i++) {
 3409                 if (i == 10)
 3410                         return ETIMEDOUT;
 3411                 tsleep(sc, PWAIT, "wiinit", 1);
 3412                 if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
 3413                         break;
 3414                 /* write the magic key value to unlock aux port */
 3415                 CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
 3416                 CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
 3417                 CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
 3418                 CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
 3419         }
 3420 
 3421         /* issue read EEPROM command: XXX copied from wi_cmd() */
 3422         CSR_WRITE_2(sc, WI_PARAM0, 0);
 3423         CSR_WRITE_2(sc, WI_PARAM1, 0);
 3424         CSR_WRITE_2(sc, WI_PARAM2, 0);
 3425         CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
 3426         for (i = 0; i < WI_TIMEOUT; i++) {
 3427                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
 3428                         break;
 3429                 DELAY(1);
 3430         }
 3431         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
 3432 
 3433         CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
 3434         CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
 3435         CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
 3436             (uint16_t *)ebuf, sizeof(ebuf) / 2);
 3437         if (GETLE16(ebuf) > sizeof(ebuf))
 3438                 return EIO;
 3439         if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
 3440                 return EIO;
 3441         return 0;
 3442 }
 3443 
 3444 static int
 3445 wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
 3446     const void *ebuf, int ebuflen)
 3447 {
 3448         const uint8_t *p, *ep, *q, *eq;
 3449         char *tp;
 3450         uint32_t addr, id, eid;
 3451         int i, len, elen, nblk, pdrlen;
 3452 
 3453         /*
 3454          * Parse the header of the firmware image.
 3455          */
 3456         p = buf;
 3457         ep = p + buflen;
 3458         while (p < ep && *p++ != ' ');  /* FILE: */
 3459         while (p < ep && *p++ != ' ');  /* filename */
 3460         while (p < ep && *p++ != ' ');  /* type of the firmware */
 3461         nblk = strtoul(p, &tp, 10);
 3462         p = tp;
 3463         pdrlen = strtoul(p + 1, &tp, 10);
 3464         p = tp;
 3465         while (p < ep && *p++ != 0x1a); /* skip rest of header */
 3466 
 3467         /*
 3468          * Block records: address[4], length[2], data[length];
 3469          */
 3470         for (i = 0; i < nblk; i++) {
 3471                 addr = GETLE32(p);      p += 4;
 3472                 len  = GETLE16(p);      p += 2;
 3473                 CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
 3474                 CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
 3475                 CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
 3476                     (const uint16_t *)p, len / 2);
 3477                 p += len;
 3478         }
 3479         
 3480         /*
 3481          * PDR: id[4], address[4], length[4];
 3482          */
 3483         for (i = 0; i < pdrlen; ) {
 3484                 id   = GETLE32(p);      p += 4; i += 4;
 3485                 addr = GETLE32(p);      p += 4; i += 4;
 3486                 len  = GETLE32(p);      p += 4; i += 4;
 3487                 /* replace PDR entry with the values from EEPROM, if any */
 3488                 for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
 3489                         elen = GETLE16(q);      q += 2;
 3490                         eid  = GETLE16(q);      q += 2;
 3491                         elen--;         /* elen includes eid */
 3492                         if (eid == 0)
 3493                                 break;
 3494                         if (eid != id)
 3495                                 continue;
 3496                         CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
 3497                         CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
 3498                         CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
 3499                             (const uint16_t *)q, len / 2);
 3500                         break;
 3501                 }
 3502         }
 3503         return 0;
 3504 }
 3505 
 3506 static int
 3507 wi_symbol_set_hcr(struct wi_softc *sc, int mode)
 3508 {
 3509         uint16_t hcr;
 3510 
 3511         CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
 3512         tsleep(sc, PWAIT, "wiinit", 1);
 3513         hcr = CSR_READ_2(sc, WI_HCR);
 3514         hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
 3515         CSR_WRITE_2(sc, WI_HCR, hcr);
 3516         tsleep(sc, PWAIT, "wiinit", 1);
 3517         CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
 3518         tsleep(sc, PWAIT, "wiinit", 1);
 3519         return 0;
 3520 }
 3521 
 3522 /*
 3523  * This function can be called by ieee80211_set_shortslottime(). Refer to
 3524  * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
 3525  */
 3526 static void
 3527 wi_update_slot(struct ifnet *ifp)
 3528 {
 3529         DPRINTF(("wi update slot unimplemented\n"));
 3530 }
 3531 
 3532 static void
 3533 wi_set_channel(struct ieee80211com *ic)
 3534 {
 3535         struct ifnet *ifp = ic->ic_ifp;
 3536         struct wi_softc *sc = ifp->if_softc;
 3537 
 3538         WI_LOCK(sc);
 3539         if (sc->sc_enabled && !(sc->sc_flags & WI_FLAGS_SCANNING)) {
 3540                 DPRINTF(("wi_set_channel: %d (%dMHz)\n",
 3541                     ieee80211_chan2ieee(ic, ic->ic_curchan),
 3542                     ic->ic_curchan->ic_freq));
 3543 
 3544                 sc->wi_channel = ic->ic_curchan;
 3545                 wi_write_val(sc, WI_RID_OWN_CHNL,
 3546                     ieee80211_chan2ieee(ic, ic->ic_curchan));
 3547 
 3548                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
 3549                     sc->sc_firmware_type == WI_INTERSIL) {
 3550                         /* XXX: some cards need to be re-enabled */
 3551                         wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
 3552                         wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
 3553                 }
 3554         }
 3555         WI_UNLOCK(sc);
 3556 }
 3557 
 3558 static void
 3559 wi_scan_start(struct ieee80211com *ic)
 3560 {
 3561         struct ifnet *ifp = ic->ic_ifp;
 3562         struct wi_softc *sc = ifp->if_softc;
 3563 
 3564         WI_LOCK(sc);
 3565         sc->sc_flags |= WI_FLAGS_SCANNING;
 3566         wi_scan_ap(sc, 0x3fff, 0x000f);
 3567         WI_UNLOCK(sc);
 3568 
 3569 }
 3570 
 3571 static void
 3572 wi_scan_curchan(struct ieee80211com *ic, unsigned long maxdwell)
 3573 {
 3574         /* The firmware is not capable of scanning a single channel */
 3575 }
 3576 
 3577 static void
 3578 wi_scan_mindwell(struct ieee80211com *ic)
 3579 {
 3580         /* NB: don't try to abort scan; wait for firmware to finish */
 3581 }
 3582 
 3583 static void
 3584 wi_scan_end(struct ieee80211com *ic)
 3585 {
 3586         struct ifnet *ifp = ic->ic_ifp;
 3587         struct wi_softc *sc = ifp->if_softc;
 3588 
 3589         WI_LOCK(sc);
 3590         sc->sc_flags &= ~WI_FLAGS_SCANNING;
 3591         WI_UNLOCK(sc);
 3592 }

Cache object: 98005d8b242f98cf9cd8a4560eafacb6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.