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/ic/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.159.2.2 2004/07/23 23:26:50 he Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1997, 1998, 1999
   41  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. All advertising materials mentioning features or use of this software
   52  *    must display the following acknowledgement:
   53  *      This product includes software developed by Bill Paul.
   54  * 4. Neither the name of the author nor the names of any co-contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   62  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   63  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   64  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   65  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   66  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   67  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   68  * THE POSSIBILITY OF SUCH DAMAGE.
   69  */
   70 
   71 /*
   72  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
   73  *
   74  * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
   75  * Electrical Engineering Department
   76  * Columbia University, New York City
   77  */
   78 
   79 /*
   80  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
   81  * from Lucent. Unlike the older cards, the new ones are programmed
   82  * entirely via a firmware-driven controller called the Hermes.
   83  * Unfortunately, Lucent will not release the Hermes programming manual
   84  * without an NDA (if at all). What they do release is an API library
   85  * called the HCF (Hardware Control Functions) which is supposed to
   86  * do the device-specific operations of a device driver for you. The
   87  * publically available version of the HCF library (the 'HCF Light') is 
   88  * a) extremely gross, b) lacks certain features, particularly support
   89  * for 802.11 frames, and c) is contaminated by the GNU Public License.
   90  *
   91  * This driver does not use the HCF or HCF Light at all. Instead, it
   92  * programs the Hermes controller directly, using information gleaned
   93  * from the HCF Light code and corresponding documentation.
   94  *
   95  * This driver supports both the PCMCIA and ISA versions of the
   96  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
   97  * anything of the sort: it's actually a PCMCIA bridge adapter
   98  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
   99  * inserted. Consequently, you need to use the pccard support for
  100  * both the ISA and PCMCIA adapters.
  101  */
  102 
  103 /*
  104  * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
  105  * Oslo IETF plenary meeting.
  106  */
  107 
  108 #include <sys/cdefs.h>
  109 __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.159.2.2 2004/07/23 23:26:50 he Exp $");
  110 
  111 #define WI_HERMES_AUTOINC_WAR   /* Work around data write autoinc bug. */
  112 #define WI_HERMES_STATS_WAR     /* Work around stats counter bug. */
  113 #undef WI_HISTOGRAM
  114 #undef WI_RING_DEBUG
  115 #define STATIC static
  116 
  117 #include "bpfilter.h"
  118 
  119 #include <sys/param.h>
  120 #include <sys/systm.h>
  121 #include <sys/callout.h>
  122 #include <sys/device.h>
  123 #include <sys/socket.h>
  124 #include <sys/mbuf.h>
  125 #include <sys/ioctl.h>
  126 #include <sys/kernel.h>         /* for hz */
  127 #include <sys/proc.h>
  128 
  129 #include <net/if.h>
  130 #include <net/if_dl.h>
  131 #include <net/if_llc.h>
  132 #include <net/if_media.h>
  133 #include <net/if_ether.h>
  134 #include <net/route.h>
  135 
  136 #include <net80211/ieee80211_var.h>
  137 #include <net80211/ieee80211_compat.h>
  138 #include <net80211/ieee80211_ioctl.h>
  139 #include <net80211/ieee80211_radiotap.h>
  140 #include <net80211/ieee80211_rssadapt.h>
  141 
  142 #if NBPFILTER > 0
  143 #include <net/bpf.h>
  144 #include <net/bpfdesc.h>
  145 #endif
  146 
  147 #include <machine/bus.h>
  148 
  149 #include <dev/ic/wi_ieee.h>
  150 #include <dev/ic/wireg.h>
  151 #include <dev/ic/wivar.h>
  152 
  153 STATIC int  wi_init(struct ifnet *);
  154 STATIC void wi_stop(struct ifnet *, int);
  155 STATIC void wi_start(struct ifnet *);
  156 STATIC int  wi_reset(struct wi_softc *);
  157 STATIC void wi_watchdog(struct ifnet *);
  158 STATIC int  wi_ioctl(struct ifnet *, u_long, caddr_t);
  159 STATIC int  wi_media_change(struct ifnet *);
  160 STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
  161 
  162 STATIC struct ieee80211_node *wi_node_alloc(struct ieee80211com *);
  163 STATIC void wi_node_copy(struct ieee80211com *, struct ieee80211_node *,
  164     const struct ieee80211_node *);
  165 STATIC void wi_node_free(struct ieee80211com *, struct ieee80211_node *);
  166 
  167 STATIC void wi_raise_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
  168 STATIC void wi_lower_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
  169 STATIC int wi_choose_rate(struct ieee80211com *, struct ieee80211_node *,
  170     struct ieee80211_frame *, u_int);
  171 STATIC void wi_rssadapt_updatestats_cb(void *, struct ieee80211_node *);
  172 STATIC void wi_rssadapt_updatestats(void *);
  173 STATIC void wi_rssdescs_init(struct wi_rssdesc (*)[], wi_rssdescq_t *);
  174 STATIC void wi_rssdescs_reset(struct ieee80211com *, struct wi_rssdesc (*)[],
  175     wi_rssdescq_t *, u_int8_t (*)[]);
  176 STATIC void wi_sync_bssid(struct wi_softc *, u_int8_t new_bssid[]);
  177 
  178 STATIC void wi_rx_intr(struct wi_softc *);
  179 STATIC void wi_txalloc_intr(struct wi_softc *);
  180 STATIC void wi_tx_intr(struct wi_softc *);
  181 STATIC void wi_tx_ex_intr(struct wi_softc *);
  182 STATIC void wi_info_intr(struct wi_softc *);
  183 
  184 STATIC void wi_push_packet(struct wi_softc *);
  185 STATIC int  wi_get_cfg(struct ifnet *, u_long, caddr_t);
  186 STATIC int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
  187 STATIC int  wi_cfg_txrate(struct wi_softc *);
  188 STATIC int  wi_write_txrate(struct wi_softc *, int);
  189 STATIC int  wi_write_wep(struct wi_softc *);
  190 STATIC int  wi_write_multi(struct wi_softc *);
  191 STATIC int  wi_alloc_fid(struct wi_softc *, int, int *);
  192 STATIC void wi_read_nicid(struct wi_softc *);
  193 STATIC int  wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
  194 
  195 STATIC int  wi_cmd(struct wi_softc *, int, int, int, int);
  196 STATIC int  wi_seek_bap(struct wi_softc *, int, int);
  197 STATIC int  wi_read_bap(struct wi_softc *, int, int, void *, int);
  198 STATIC int  wi_write_bap(struct wi_softc *, int, int, void *, int);
  199 STATIC int  wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
  200 STATIC int  wi_read_rid(struct wi_softc *, int, void *, int *);
  201 STATIC int  wi_write_rid(struct wi_softc *, int, void *, int);
  202 
  203 STATIC int  wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
  204 STATIC int  wi_set_tim(struct ieee80211com *, int, int);
  205 
  206 STATIC int  wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
  207 STATIC void wi_scan_result(struct wi_softc *, int, int);
  208 
  209 STATIC void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
  210 
  211 static inline int
  212 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
  213 {
  214 
  215         val = htole16(val);
  216         return wi_write_rid(sc, rid, &val, sizeof(val));
  217 }
  218 
  219 static  struct timeval lasttxerror;     /* time of last tx error msg */
  220 static  int curtxeps = 0;               /* current tx error msgs/sec */
  221 static  int wi_txerate = 0;             /* tx error rate: max msgs/sec */
  222 
  223 #ifdef WI_DEBUG
  224 int wi_debug = 0;
  225 
  226 #define DPRINTF(X)      if (wi_debug) printf X
  227 #define DPRINTF2(X)     if (wi_debug > 1) printf X
  228 #define IFF_DUMPPKTS(_ifp) \
  229         (((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
  230 #else
  231 #define DPRINTF(X)
  232 #define DPRINTF2(X)
  233 #define IFF_DUMPPKTS(_ifp)      0
  234 #endif
  235 
  236 #define WI_INTRS        (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO | \
  237                          WI_EV_TX | WI_EV_TX_EXC)
  238 
  239 struct wi_card_ident
  240 wi_card_ident[] = {
  241         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
  242         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
  243         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
  244         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
  245         { WI_NIC_EVB2_ID,               WI_NIC_EVB2_STR,        WI_INTERSIL },
  246         { WI_NIC_HWB3763_ID,            WI_NIC_HWB3763_STR,     WI_INTERSIL },
  247         { WI_NIC_HWB3163_ID,            WI_NIC_HWB3163_STR,     WI_INTERSIL },
  248         { WI_NIC_HWB3163B_ID,           WI_NIC_HWB3163B_STR,    WI_INTERSIL },
  249         { WI_NIC_EVB3_ID,               WI_NIC_EVB3_STR,        WI_INTERSIL },
  250         { WI_NIC_HWB1153_ID,            WI_NIC_HWB1153_STR,     WI_INTERSIL },
  251         { WI_NIC_P2_SST_ID,             WI_NIC_P2_SST_STR,      WI_INTERSIL },
  252         { WI_NIC_EVB2_SST_ID,           WI_NIC_EVB2_SST_STR,    WI_INTERSIL },
  253         { WI_NIC_3842_EVA_ID,           WI_NIC_3842_EVA_STR,    WI_INTERSIL },
  254         { WI_NIC_3842_PCMCIA_AMD_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  255         { WI_NIC_3842_PCMCIA_SST_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  256         { WI_NIC_3842_PCMCIA_ATM_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  257         { WI_NIC_3842_MINI_AMD_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  258         { WI_NIC_3842_MINI_SST_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  259         { WI_NIC_3842_MINI_ATM_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  260         { WI_NIC_3842_PCI_AMD_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  261         { WI_NIC_3842_PCI_SST_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  262         { WI_NIC_3842_PCI_ATM_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  263         { WI_NIC_P3_PCMCIA_AMD_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  264         { WI_NIC_P3_PCMCIA_SST_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  265         { WI_NIC_P3_MINI_AMD_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  266         { WI_NIC_P3_MINI_SST_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  267         { 0,    NULL,   0 },
  268 };
  269 
  270 int
  271 wi_attach(struct wi_softc *sc)
  272 {
  273         struct ieee80211com *ic = &sc->sc_ic;
  274         struct ifnet *ifp = &ic->ic_if;
  275         int chan, nrate, buflen;
  276         u_int16_t val, chanavail;
  277         struct {
  278                 u_int16_t nrates;
  279                 char rates[IEEE80211_RATE_SIZE];
  280         } ratebuf;
  281         static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
  282                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  283         };
  284         int s;
  285 
  286         s = splnet();
  287 
  288         /* Make sure interrupts are disabled. */
  289         CSR_WRITE_2(sc, WI_INT_EN, 0);
  290         CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
  291 
  292         sc->sc_invalid = 0;
  293 
  294         /* Reset the NIC. */
  295         if (wi_reset(sc) != 0) {
  296                 sc->sc_invalid = 1;
  297                 splx(s);
  298                 return 1;
  299         }
  300 
  301         buflen = IEEE80211_ADDR_LEN;
  302         if (wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen) != 0 ||
  303             IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
  304                 printf(" could not get mac address, attach failed\n");
  305                 splx(s);
  306                 return 1;
  307         }
  308 
  309         printf(" 802.11 address %s\n", ether_sprintf(ic->ic_myaddr));
  310 
  311         /* Read NIC identification */
  312         wi_read_nicid(sc);
  313 
  314         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
  315         ifp->if_softc = sc;
  316         ifp->if_start = wi_start;
  317         ifp->if_ioctl = wi_ioctl;
  318         ifp->if_watchdog = wi_watchdog;
  319         ifp->if_init = wi_init;
  320         ifp->if_stop = wi_stop;
  321         ifp->if_flags =
  322             IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS;
  323         IFQ_SET_READY(&ifp->if_snd);
  324 
  325         ic->ic_phytype = IEEE80211_T_DS;
  326         ic->ic_opmode = IEEE80211_M_STA;
  327         ic->ic_caps = IEEE80211_C_AHDEMO;
  328         ic->ic_state = IEEE80211_S_INIT;
  329         ic->ic_max_aid = WI_MAX_AID;
  330 
  331         /* Find available channel */
  332         buflen = sizeof(chanavail);
  333         if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &chanavail, &buflen) != 0)
  334                 chanavail = htole16(0x1fff);    /* assume 1-11 */
  335         for (chan = 16; chan > 0; chan--) {
  336                 if (!isset((u_int8_t*)&chanavail, chan - 1))
  337                         continue;
  338                 ic->ic_ibss_chan = &ic->ic_channels[chan];
  339                 ic->ic_channels[chan].ic_freq =
  340                     ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
  341                 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
  342         }
  343 
  344         /* Find default IBSS channel */
  345         buflen = sizeof(val);
  346         if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
  347                 chan = le16toh(val);
  348                 if (isset((u_int8_t*)&chanavail, chan - 1))
  349                         ic->ic_ibss_chan = &ic->ic_channels[chan];
  350         }
  351         if (ic->ic_ibss_chan == NULL)
  352                 panic("%s: no available channel\n", sc->sc_dev.dv_xname);
  353 
  354         if (sc->sc_firmware_type == WI_LUCENT) {
  355                 sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
  356         } else {
  357                 buflen = sizeof(val);
  358                 if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
  359                     wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0)
  360                         sc->sc_dbm_offset = le16toh(val);
  361                 else
  362                         sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
  363         }
  364 
  365         sc->sc_flags |= WI_FLAGS_RSSADAPTSTA;
  366 
  367         /*
  368          * Set flags based on firmware version.
  369          */
  370         switch (sc->sc_firmware_type) {
  371         case WI_LUCENT:
  372                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
  373 #ifdef WI_HERMES_AUTOINC_WAR
  374                 /* XXX: not confirmed, but never seen for recent firmware */
  375                 if (sc->sc_sta_firmware_ver <  40000) {
  376                         sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
  377                 }
  378 #endif
  379                 if (sc->sc_sta_firmware_ver >= 60000)
  380                         sc->sc_flags |= WI_FLAGS_HAS_MOR;
  381                 if (sc->sc_sta_firmware_ver >= 60006) {
  382                         ic->ic_caps |= IEEE80211_C_IBSS;
  383                         ic->ic_caps |= IEEE80211_C_MONITOR;
  384                 }
  385                 ic->ic_caps |= IEEE80211_C_PMGT;
  386                 sc->sc_ibss_port = 1;
  387                 break;
  388 
  389         case WI_INTERSIL:
  390                 sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
  391                 sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
  392                 sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
  393                 if (sc->sc_sta_firmware_ver > 10101)
  394                         sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
  395                 if (sc->sc_sta_firmware_ver >= 800) {
  396                         if (sc->sc_sta_firmware_ver != 10402)
  397                                 ic->ic_caps |= IEEE80211_C_HOSTAP;
  398                         ic->ic_caps |= IEEE80211_C_IBSS;
  399                         ic->ic_caps |= IEEE80211_C_MONITOR;
  400                 }
  401                 ic->ic_caps |= IEEE80211_C_PMGT;
  402                 sc->sc_ibss_port = 0;
  403                 sc->sc_alt_retry = 2;
  404                 break;
  405 
  406         case WI_SYMBOL:
  407                 sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
  408                 if (sc->sc_sta_firmware_ver >= 20000)
  409                         ic->ic_caps |= IEEE80211_C_IBSS;
  410                 sc->sc_ibss_port = 4;
  411                 break;
  412         }
  413 
  414         /*
  415          * Find out if we support WEP on this card.
  416          */
  417         buflen = sizeof(val);
  418         if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
  419             val != htole16(0))
  420                 ic->ic_caps |= IEEE80211_C_WEP;
  421 
  422         /* Find supported rates. */
  423         buflen = sizeof(ratebuf);
  424         if (wi_read_rid(sc, WI_RID_DATA_RATES, &ratebuf, &buflen) == 0) {
  425                 nrate = le16toh(ratebuf.nrates);
  426                 if (nrate > IEEE80211_RATE_SIZE)
  427                         nrate = IEEE80211_RATE_SIZE;
  428                 memcpy(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates,
  429                     &ratebuf.rates[0], nrate);
  430                 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = nrate;
  431         }
  432         buflen = sizeof(val);
  433 
  434         sc->sc_max_datalen = 2304;
  435         sc->sc_rts_thresh = 2347;
  436         sc->sc_frag_thresh = 2346;
  437         sc->sc_system_scale = 1;
  438         sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
  439         sc->sc_roaming_mode = 1;
  440 
  441         callout_init(&sc->sc_rssadapt_ch);
  442 
  443         /*
  444          * Call MI attach routines.
  445          */
  446         if_attach(ifp);
  447         ieee80211_ifattach(ifp);
  448 
  449         sc->sc_newstate = ic->ic_newstate;
  450         ic->ic_newstate = wi_newstate;
  451         ic->ic_node_alloc = wi_node_alloc;
  452         ic->ic_node_free = wi_node_free;
  453         ic->ic_node_copy = wi_node_copy;
  454         ic->ic_set_tim = wi_set_tim;
  455 
  456         ieee80211_media_init(ifp, wi_media_change, wi_media_status);
  457 
  458 #if NBPFILTER > 0
  459         bpfattach2(ifp, DLT_IEEE802_11_RADIO,
  460             sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
  461 #endif
  462 
  463         memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
  464         sc->sc_rxtap.wr_ihdr.it_len = sizeof(sc->sc_rxtapu);
  465         sc->sc_rxtap.wr_ihdr.it_present = WI_RX_RADIOTAP_PRESENT;
  466 
  467         memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
  468         sc->sc_txtap.wt_ihdr.it_len = sizeof(sc->sc_txtapu);
  469         sc->sc_txtap.wt_ihdr.it_present = WI_TX_RADIOTAP_PRESENT;
  470 
  471         /* Attach is successful. */
  472         sc->sc_attached = 1;
  473 
  474         splx(s);
  475         return 0;
  476 }
  477 
  478 int
  479 wi_detach(struct wi_softc *sc)
  480 {
  481         struct ifnet *ifp = &sc->sc_ic.ic_if;
  482         int s;
  483 
  484         if (!sc->sc_attached)
  485                 return 0;
  486 
  487         s = splnet();
  488 
  489         sc->sc_invalid = 1;
  490         wi_stop(ifp, 1);
  491 
  492         /* Delete all remaining media. */
  493         ifmedia_delete_instance(&sc->sc_ic.ic_media, IFM_INST_ANY);
  494 
  495         ieee80211_ifdetach(ifp);
  496         if_detach(ifp);
  497         splx(s);
  498         return 0;
  499 }
  500 
  501 #ifdef __NetBSD__
  502 int
  503 wi_activate(struct device *self, enum devact act)
  504 {
  505         struct wi_softc *sc = (struct wi_softc *)self;
  506         int rv = 0, s;
  507 
  508         s = splnet();
  509         switch (act) {
  510         case DVACT_ACTIVATE:
  511                 rv = EOPNOTSUPP;
  512                 break;
  513 
  514         case DVACT_DEACTIVATE:
  515                 if_deactivate(&sc->sc_ic.ic_if);
  516                 break;
  517         }
  518         splx(s);
  519         return rv;
  520 }
  521 
  522 void
  523 wi_power(struct wi_softc *sc, int why)
  524 {
  525         struct ifnet *ifp = &sc->sc_ic.ic_if;
  526         int s;
  527 
  528         s = splnet();
  529         switch (why) {
  530         case PWR_SUSPEND:
  531         case PWR_STANDBY:
  532                 wi_stop(ifp, 1);
  533                 break;
  534         case PWR_RESUME:
  535                 if (ifp->if_flags & IFF_UP) {
  536                         wi_init(ifp);
  537                         (void)wi_intr(sc);
  538                 }
  539                 break;
  540         case PWR_SOFTSUSPEND:
  541         case PWR_SOFTSTANDBY:
  542         case PWR_SOFTRESUME:
  543                 break;
  544         }
  545         splx(s);
  546 }
  547 #endif /* __NetBSD__ */
  548 
  549 void
  550 wi_shutdown(struct wi_softc *sc)
  551 {
  552         struct ifnet *ifp = &sc->sc_ic.ic_if;
  553 
  554         if (sc->sc_attached)
  555                 wi_stop(ifp, 1);
  556 }
  557 
  558 int
  559 wi_intr(void *arg)
  560 {
  561         int i;
  562         struct wi_softc *sc = arg;
  563         struct ifnet *ifp = &sc->sc_ic.ic_if;
  564         u_int16_t status;
  565 
  566         if (sc->sc_enabled == 0 ||
  567             (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
  568             (ifp->if_flags & IFF_RUNNING) == 0)
  569                 return 0;
  570 
  571         if ((ifp->if_flags & IFF_UP) == 0) {
  572                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  573                 CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
  574                 return 1;
  575         }
  576 
  577         /* This is superfluous on Prism, but Lucent breaks if we
  578          * do not disable interrupts.
  579          */
  580         CSR_WRITE_2(sc, WI_INT_EN, 0);
  581 
  582         /* maximum 10 loops per interrupt */
  583         for (i = 0; i < 10; i++) {
  584                 /*
  585                  * Only believe a status bit when we enter wi_intr, or when
  586                  * the bit was "off" the last time through the loop. This is
  587                  * my strategy to avoid racing the hardware/firmware if I
  588                  * can re-read the event status register more quickly than
  589                  * it is updated.
  590                  */
  591                 status = CSR_READ_2(sc, WI_EVENT_STAT);
  592                 if ((status & WI_INTRS) == 0)
  593                         break;
  594 
  595                 if (status & WI_EV_RX)
  596                         wi_rx_intr(sc);
  597 
  598                 if (status & WI_EV_ALLOC)
  599                         wi_txalloc_intr(sc);
  600 
  601                 if (status & WI_EV_TX)
  602                         wi_tx_intr(sc);
  603 
  604                 if (status & WI_EV_TX_EXC)
  605                         wi_tx_ex_intr(sc);
  606 
  607                 if (status & WI_EV_INFO)
  608                         wi_info_intr(sc);
  609 
  610                 CSR_WRITE_2(sc, WI_EVENT_ACK, status);
  611 
  612                 if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
  613                     (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
  614                     !IFQ_IS_EMPTY(&ifp->if_snd))
  615                         wi_start(ifp);
  616         }
  617 
  618         /* re-enable interrupts */
  619         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  620 
  621         return 1;
  622 }
  623 
  624 #define arraylen(a) (sizeof(a) / sizeof((a)[0]))
  625 
  626 STATIC void
  627 wi_rssdescs_init(struct wi_rssdesc (*rssd)[WI_NTXRSS], wi_rssdescq_t *rssdfree)
  628 {
  629         int i;
  630         SLIST_INIT(rssdfree);
  631         for (i = 0; i < arraylen(*rssd); i++) {
  632                 SLIST_INSERT_HEAD(rssdfree, &(*rssd)[i], rd_next);
  633         }
  634 }
  635 
  636 STATIC void
  637 wi_rssdescs_reset(struct ieee80211com *ic, struct wi_rssdesc (*rssd)[WI_NTXRSS],
  638     wi_rssdescq_t *rssdfree, u_int8_t (*txpending)[IEEE80211_RATE_MAXSIZE])
  639 {
  640         struct ieee80211_node *ni;
  641         int i;
  642         for (i = 0; i < arraylen(*rssd); i++) {
  643                 ni = (*rssd)[i].rd_desc.id_node;
  644                 (*rssd)[i].rd_desc.id_node = NULL;
  645                 if (ni != NULL && (ic->ic_if.if_flags & IFF_DEBUG) != 0)
  646                         printf("%s: cleaning outstanding rssadapt "
  647                             "descriptor for %s\n",
  648                             ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
  649                 if (ni != NULL && ni != ic->ic_bss)
  650                         ieee80211_free_node(ic, ni);
  651         }
  652         memset(*txpending, 0, sizeof(*txpending));
  653         wi_rssdescs_init(rssd, rssdfree);
  654 }
  655 
  656 STATIC int
  657 wi_init(struct ifnet *ifp)
  658 {
  659         struct wi_softc *sc = ifp->if_softc;
  660         struct ieee80211com *ic = &sc->sc_ic;
  661         struct wi_joinreq join;
  662         int i;
  663         int error = 0, wasenabled;
  664 
  665         DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled));
  666         wasenabled = sc->sc_enabled;
  667         if (!sc->sc_enabled) {
  668                 if ((error = (*sc->sc_enable)(sc)) != 0)
  669                         goto out;
  670                 sc->sc_enabled = 1;
  671         } else
  672                 wi_stop(ifp, 0);
  673 
  674         /* Symbol firmware cannot be initialized more than once */
  675         if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled)
  676                 if ((error = wi_reset(sc)) != 0)
  677                         goto out;
  678 
  679         /* common 802.11 configuration */
  680         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  681         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
  682         switch (ic->ic_opmode) {
  683         case IEEE80211_M_STA:
  684                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
  685                 break;
  686         case IEEE80211_M_IBSS:
  687                 wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
  688                 ic->ic_flags |= IEEE80211_F_IBSSON;
  689                 sc->sc_syn_timer = 5;
  690                 ifp->if_timer = 1;
  691                 break;
  692         case IEEE80211_M_AHDEMO:
  693                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
  694                 break;
  695         case IEEE80211_M_HOSTAP:
  696                 wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
  697                 break;
  698         case IEEE80211_M_MONITOR:
  699                 if (sc->sc_firmware_type == WI_LUCENT)
  700                         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
  701                 wi_cmd(sc, WI_CMD_TEST | (WI_TEST_MONITOR << 8), 0, 0, 0);
  702                 break;
  703         }
  704 
  705         /* Intersil interprets this RID as joining ESS even in IBSS mode */
  706         if (sc->sc_firmware_type == WI_LUCENT &&
  707             (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
  708                 wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
  709         else
  710                 wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
  711         wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
  712         wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
  713             ic->ic_des_esslen);
  714         wi_write_val(sc, WI_RID_OWN_CHNL,
  715             ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
  716         wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
  717         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
  718         wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
  719         if (ic->ic_caps & IEEE80211_C_PMGT)
  720                 wi_write_val(sc, WI_RID_PM_ENABLED,
  721                     (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
  722 
  723         /* not yet common 802.11 configuration */
  724         wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
  725         wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh);
  726         if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
  727                 wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh);
  728 
  729         /* driver specific 802.11 configuration */
  730         if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
  731                 wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
  732         if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
  733                 wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
  734         if (sc->sc_flags & WI_FLAGS_HAS_MOR)
  735                 wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
  736         wi_cfg_txrate(sc);
  737         wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
  738 
  739         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
  740             sc->sc_firmware_type == WI_INTERSIL) {
  741                 wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
  742                 wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
  743         }
  744 
  745         if (sc->sc_firmware_type == WI_INTERSIL) {
  746                 struct ieee80211_rateset *rs =
  747                     &ic->ic_sup_rates[IEEE80211_MODE_11B];
  748                 u_int16_t basic = 0, supported = 0, rate;
  749 
  750                 for (i = 0; i < rs->rs_nrates; i++) {
  751                         switch (rs->rs_rates[i] & IEEE80211_RATE_VAL) {
  752                         case 2:
  753                                 rate = 1;
  754                                 break;
  755                         case 4:
  756                                 rate = 2;
  757                                 break;
  758                         case 11:
  759                                 rate = 4;
  760                                 break;
  761                         case 22:
  762                                 rate = 8;
  763                                 break;
  764                         default:
  765                                 rate = 0;
  766                                 break;
  767                         }
  768                         if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
  769                                 basic |= rate;
  770                         supported |= rate;
  771                 }
  772                 wi_write_val(sc, WI_RID_BASIC_RATE, basic);
  773                 wi_write_val(sc, WI_RID_SUPPORT_RATE, supported);
  774                 wi_write_val(sc, WI_RID_ALT_RETRY_COUNT, sc->sc_alt_retry);
  775         }
  776 
  777         /*
  778          * Initialize promisc mode.
  779          *      Being in Host-AP mode causes a great
  780          *      deal of pain if promiscuous mode is set.
  781          *      Therefore we avoid confusing the firmware
  782          *      and always reset promisc mode in Host-AP
  783          *      mode.  Host-AP sees all the packets anyway.
  784          */
  785         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
  786             (ifp->if_flags & IFF_PROMISC) != 0) {
  787                 wi_write_val(sc, WI_RID_PROMISC, 1);
  788         } else {
  789                 wi_write_val(sc, WI_RID_PROMISC, 0);
  790         }
  791 
  792         /* Configure WEP. */
  793         if (ic->ic_caps & IEEE80211_C_WEP)
  794                 wi_write_wep(sc);
  795 
  796         /* Set multicast filter. */
  797         wi_write_multi(sc);
  798 
  799         sc->sc_txalloc = 0;
  800         sc->sc_txalloced = 0;
  801         sc->sc_txqueue = 0;
  802         sc->sc_txqueued = 0;
  803         sc->sc_txstart = 0;
  804         sc->sc_txstarted = 0;
  805 
  806         if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
  807                 sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
  808                 if (sc->sc_firmware_type == WI_SYMBOL)
  809                         sc->sc_buflen = 1585;   /* XXX */
  810                 for (i = 0; i < WI_NTXBUF; i++) {
  811                         error = wi_alloc_fid(sc, sc->sc_buflen,
  812                             &sc->sc_txd[i].d_fid);
  813                         if (error) {
  814                                 printf("%s: tx buffer allocation failed\n",
  815                                     sc->sc_dev.dv_xname);
  816                                 goto out;
  817                         }
  818                         DPRINTF2(("wi_init: txbuf %d allocated %x\n", i,
  819                             sc->sc_txd[i].d_fid));
  820                         ++sc->sc_txalloced;
  821                 }
  822         }
  823 
  824         wi_rssdescs_init(&sc->sc_rssd, &sc->sc_rssdfree);
  825 
  826         /* Enable desired port */
  827         wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
  828         ifp->if_flags |= IFF_RUNNING;
  829         ifp->if_flags &= ~IFF_OACTIVE;
  830         ic->ic_state = IEEE80211_S_INIT;
  831 
  832         if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
  833             ic->ic_opmode == IEEE80211_M_MONITOR ||
  834             ic->ic_opmode == IEEE80211_M_HOSTAP)
  835                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  836 
  837         /* Enable interrupts */
  838         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  839 
  840         if (!wasenabled &&
  841             ic->ic_opmode == IEEE80211_M_HOSTAP &&
  842             sc->sc_firmware_type == WI_INTERSIL) {
  843                 /* XXX: some card need to be re-enabled for hostap */
  844                 wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
  845                 wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
  846         }
  847 
  848         if (ic->ic_opmode == IEEE80211_M_STA &&
  849             ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
  850             ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
  851                 memset(&join, 0, sizeof(join));
  852                 if (ic->ic_flags & IEEE80211_F_DESBSSID)
  853                         IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
  854                 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
  855                         join.wi_chan =
  856                             htole16(ieee80211_chan2ieee(ic, ic->ic_des_chan));
  857                 /* Lucent firmware does not support the JOIN RID. */
  858                 if (sc->sc_firmware_type != WI_LUCENT)
  859                         wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
  860         }
  861 
  862  out:
  863         if (error) {
  864                 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  865                 wi_stop(ifp, 0);
  866         }
  867         DPRINTF(("wi_init: return %d\n", error));
  868         return error;
  869 }
  870 
  871 STATIC void
  872 wi_stop(struct ifnet *ifp, int disable)
  873 {
  874         struct wi_softc *sc = ifp->if_softc;
  875         struct ieee80211com *ic = &sc->sc_ic;
  876         int s;
  877 
  878         if (!sc->sc_enabled)
  879                 return;
  880 
  881         s = splnet();
  882 
  883         DPRINTF(("wi_stop: disable %d\n", disable));
  884 
  885         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
  886         if (!sc->sc_invalid) {
  887                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  888                 wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
  889         }
  890 
  891         wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
  892             &sc->sc_txpending);
  893 
  894         sc->sc_tx_timer = 0;
  895         sc->sc_scan_timer = 0;
  896         sc->sc_syn_timer = 0;
  897         sc->sc_false_syns = 0;
  898         sc->sc_naps = 0;
  899         ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
  900         ifp->if_timer = 0;
  901 
  902         if (disable) {
  903                 if (sc->sc_disable)
  904                         (*sc->sc_disable)(sc);
  905                 sc->sc_enabled = 0;
  906         }
  907         splx(s);
  908 }
  909 
  910 /*
  911  * Choose a data rate for a packet len bytes long that suits the packet
  912  * type and the wireless conditions.
  913  *
  914  * TBD Adapt fragmentation threshold.
  915  */
  916 STATIC int
  917 wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
  918     struct ieee80211_frame *wh, u_int len)
  919 {
  920         struct wi_softc *sc = ic->ic_if.if_softc;
  921         struct wi_node *wn = (void*)ni;
  922         struct ieee80211_rssadapt *ra = &wn->wn_rssadapt;
  923         int do_not_adapt, i, rateidx, s;
  924 
  925         do_not_adapt = (ic->ic_opmode != IEEE80211_M_HOSTAP) &&
  926             (sc->sc_flags & WI_FLAGS_RSSADAPTSTA) == 0;
  927 
  928         s = splnet();
  929 
  930         rateidx = ieee80211_rssadapt_choose(ra, &ni->ni_rates, wh, len,
  931             ic->ic_fixed_rate,
  932             ((ic->ic_if.if_flags & IFF_DEBUG) == 0) ? NULL : ic->ic_if.if_xname,
  933             do_not_adapt);
  934 
  935         ni->ni_txrate = rateidx;
  936 
  937         if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
  938                 /* choose the slowest pending rate so that we don't
  939                  * accidentally send a packet on the MAC's queue
  940                  * too fast. TBD find out if the MAC labels Tx
  941                  * packets w/ rate when enqueued or dequeued.
  942                  */   
  943                 for (i = 0; i < rateidx && sc->sc_txpending[i] == 0; i++);
  944                 rateidx = i;
  945         }
  946 
  947         splx(s);
  948         return (rateidx);
  949 }
  950 
  951 STATIC void
  952 wi_raise_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
  953 {
  954         struct wi_node *wn;
  955         if (id->id_node == NULL)
  956                 return;
  957 
  958         wn = (void*)id->id_node;
  959         ieee80211_rssadapt_raise_rate(ic, &wn->wn_rssadapt, id);
  960 }
  961 
  962 STATIC void
  963 wi_lower_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
  964 {
  965         struct ieee80211_node *ni;
  966         struct wi_node *wn;
  967         int s;
  968 
  969         s = splnet();
  970 
  971         if ((ni = id->id_node) == NULL) {
  972                 DPRINTF(("wi_lower_rate: missing node\n"));
  973                 goto out;
  974         }
  975 
  976         wn = (void *)ni;
  977 
  978         ieee80211_rssadapt_lower_rate(ic, ni, &wn->wn_rssadapt, id);
  979 out:
  980         splx(s);
  981         return;
  982 }
  983 
  984 STATIC void
  985 wi_start(struct ifnet *ifp)
  986 {
  987         struct wi_softc *sc = ifp->if_softc;
  988         struct ieee80211com *ic = &sc->sc_ic;
  989         struct ieee80211_node *ni;
  990         struct ieee80211_frame *wh;
  991         struct ieee80211_rateset *rs;
  992         struct wi_rssdesc *rd;
  993         struct ieee80211_rssdesc *id;
  994         struct mbuf *m0;
  995         struct wi_frame frmhdr;
  996         int cur, fid, off, rateidx;
  997 
  998         if (!sc->sc_enabled || sc->sc_invalid)
  999                 return;
 1000         if (sc->sc_flags & WI_FLAGS_OUTRANGE)
 1001                 return;
 1002 
 1003         memset(&frmhdr, 0, sizeof(frmhdr));
 1004         cur = sc->sc_txqueue;
 1005         for (;;) {
 1006                 ni = ic->ic_bss;
 1007                 if (sc->sc_txalloced == 0 || SLIST_EMPTY(&sc->sc_rssdfree)) {
 1008                         ifp->if_flags |= IFF_OACTIVE;
 1009                         break;
 1010                 }
 1011                 if (!IF_IS_EMPTY(&ic->ic_mgtq)) {
 1012                         IF_DEQUEUE(&ic->ic_mgtq, m0);
 1013                         m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
 1014                             (caddr_t)&frmhdr.wi_ehdr);
 1015                         frmhdr.wi_ehdr.ether_type = 0;
 1016                         wh = mtod(m0, struct ieee80211_frame *);
 1017                         ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
 1018                         m0->m_pkthdr.rcvif = NULL;
 1019                 } else if (ic->ic_state != IEEE80211_S_RUN)
 1020                         break;
 1021                 else if (!IF_IS_EMPTY(&ic->ic_pwrsaveq)) {
 1022                         struct llc *llc;
 1023 
 1024                         /* 
 1025                          * Should these packets be processed after the
 1026                          * regular packets or before?  Since they are being
 1027                          * probed for, they are probably less time critical
 1028                          * than other packets, but, on the other hand,
 1029                          * we want the power saving nodes to go back to
 1030                          * sleep as quickly as possible to save power...
 1031                          */
 1032 
 1033                         IF_DEQUEUE(&ic->ic_pwrsaveq, m0);
 1034                         wh = mtod(m0, struct ieee80211_frame *);
 1035                         llc = (struct llc *) (wh + 1);
 1036                         m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
 1037                             (caddr_t)&frmhdr.wi_ehdr);
 1038                         frmhdr.wi_ehdr.ether_type = llc->llc_snap.ether_type;
 1039                         ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
 1040                         m0->m_pkthdr.rcvif = NULL;
 1041                 } else {
 1042                         IFQ_POLL(&ifp->if_snd, m0);
 1043                         if (m0 == NULL) {
 1044                                 break;
 1045                         }
 1046                         IFQ_DEQUEUE(&ifp->if_snd, m0);
 1047                         ifp->if_opackets++;
 1048                         m_copydata(m0, 0, ETHER_HDR_LEN, 
 1049                             (caddr_t)&frmhdr.wi_ehdr);
 1050 #if NBPFILTER > 0
 1051                         if (ifp->if_bpf)
 1052                                 bpf_mtap(ifp->if_bpf, m0);
 1053 #endif
 1054 
 1055                         if ((m0 = ieee80211_encap(ifp, m0, &ni)) == NULL) {
 1056                                 ifp->if_oerrors++;
 1057                                 continue;
 1058                         }
 1059                         wh = mtod(m0, struct ieee80211_frame *);
 1060                         if (ic->ic_flags & IEEE80211_F_WEPON)
 1061                                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
 1062                         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
 1063                             !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
 1064                             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
 1065                             IEEE80211_FC0_TYPE_DATA) {
 1066                                 if (ni->ni_associd == 0) {
 1067                                         m_freem(m0);
 1068                                         ifp->if_oerrors++;
 1069                                         goto next;
 1070                                 }
 1071                                 if (ni->ni_pwrsave & IEEE80211_PS_SLEEP) {
 1072                                         ieee80211_pwrsave(ic, ni, m0);
 1073                                         continue; /* don't free node. */
 1074                                 }
 1075                         }
 1076                 }
 1077 #if NBPFILTER > 0
 1078                 if (ic->ic_rawbpf)
 1079                         bpf_mtap(ic->ic_rawbpf, m0);
 1080 #endif
 1081                 frmhdr.wi_tx_ctl =
 1082                     htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX|WI_TXCNTL_TX_OK);
 1083                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 1084                         frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_ALTRTRY);
 1085                 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
 1086                     (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
 1087                         if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
 1088                                 ifp->if_oerrors++;
 1089                                 goto next;
 1090                         }
 1091                         frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
 1092                 }
 1093 
 1094                 rateidx = wi_choose_rate(ic, ni, wh, m0->m_pkthdr.len);
 1095                 rs = &ni->ni_rates;
 1096 
 1097 #if NBPFILTER > 0
 1098                 if (sc->sc_drvbpf) {
 1099                         struct mbuf mb;
 1100 
 1101                         struct wi_tx_radiotap_header *tap = &sc->sc_txtap;
 1102 
 1103                         tap->wt_rate = rs->rs_rates[rateidx];
 1104                         tap->wt_chan_freq =
 1105                             htole16(ic->ic_bss->ni_chan->ic_freq);
 1106                         tap->wt_chan_flags =
 1107                             htole16(ic->ic_bss->ni_chan->ic_flags);
 1108 
 1109                         /* TBD tap->wt_flags */
 1110 
 1111                         M_COPY_PKTHDR(&mb, m0);
 1112                         mb.m_data = (caddr_t)tap;
 1113                         mb.m_len = tap->wt_ihdr.it_len;
 1114                         mb.m_next = m0;
 1115                         mb.m_pkthdr.len += mb.m_len;
 1116                         bpf_mtap(sc->sc_drvbpf, &mb);
 1117                 }
 1118 #endif
 1119 
 1120                 rd = SLIST_FIRST(&sc->sc_rssdfree);
 1121                 id = &rd->rd_desc;
 1122                 id->id_len = m0->m_pkthdr.len;
 1123                 id->id_rateidx = ni->ni_txrate;
 1124                 id->id_rssi = ni->ni_rssi;
 1125 
 1126                 frmhdr.wi_tx_idx = rd - sc->sc_rssd;
 1127 
 1128                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 1129                         frmhdr.wi_tx_rate = 5 * (rs->rs_rates[rateidx] &
 1130                             IEEE80211_RATE_VAL);
 1131                 else if (sc->sc_flags & WI_FLAGS_RSSADAPTSTA)
 1132                         (void)wi_write_txrate(sc, rs->rs_rates[rateidx]);
 1133 
 1134                 m_copydata(m0, 0, sizeof(struct ieee80211_frame),
 1135                     (caddr_t)&frmhdr.wi_whdr);
 1136                 m_adj(m0, sizeof(struct ieee80211_frame));
 1137                 frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
 1138                 if (IFF_DUMPPKTS(ifp))
 1139                         wi_dump_pkt(&frmhdr, ni, -1);
 1140                 fid = sc->sc_txd[cur].d_fid;
 1141                 off = sizeof(frmhdr);
 1142                 if (wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0 ||
 1143                     wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0) {
 1144                         printf("%s: %s write fid %x failed\n",
 1145                             sc->sc_dev.dv_xname, __func__, fid);
 1146                         ifp->if_oerrors++;
 1147                         m_freem(m0);
 1148                         goto next;
 1149                 }
 1150                 m_freem(m0);
 1151                 sc->sc_txpending[ni->ni_txrate]++;
 1152                 --sc->sc_txalloced;
 1153                 if (sc->sc_txqueued++ == 0) {
 1154 #ifdef DIAGNOSTIC
 1155                         if (cur != sc->sc_txstart)
 1156                                 printf("%s: ring is desynchronized\n",
 1157                                     sc->sc_dev.dv_xname);
 1158 #endif
 1159                         wi_push_packet(sc);
 1160                 } else {
 1161 #ifdef WI_RING_DEBUG
 1162         printf("%s: queue %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
 1163             sc->sc_dev.dv_xname, fid,
 1164             sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
 1165             sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
 1166 #endif
 1167                 }
 1168                 sc->sc_txqueue = cur = (cur + 1) % WI_NTXBUF;
 1169                 SLIST_REMOVE_HEAD(&sc->sc_rssdfree, rd_next);
 1170                 id->id_node = ni;
 1171                 continue;
 1172 next:
 1173                 if (ni != NULL && ni != ic->ic_bss)
 1174                         ieee80211_free_node(ic, ni);
 1175         }
 1176 }
 1177 
 1178 
 1179 STATIC int
 1180 wi_reset(struct wi_softc *sc)
 1181 {
 1182         int i, error;
 1183 
 1184         DPRINTF(("wi_reset\n"));
 1185 
 1186         if (sc->sc_reset)
 1187                 (*sc->sc_reset)(sc);
 1188 
 1189         error = 0;
 1190         for (i = 0; i < 5; i++) {
 1191                 DELAY(20*1000); /* XXX: way too long! */
 1192                 if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
 1193                         break;
 1194         }
 1195         if (error) {
 1196                 printf("%s: init failed\n", sc->sc_dev.dv_xname);
 1197                 return error;
 1198         }
 1199         CSR_WRITE_2(sc, WI_INT_EN, 0);
 1200         CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
 1201 
 1202         /* Calibrate timer. */
 1203         wi_write_val(sc, WI_RID_TICK_TIME, 0);
 1204         return 0;
 1205 }
 1206 
 1207 STATIC void
 1208 wi_watchdog(struct ifnet *ifp)
 1209 {
 1210         struct wi_softc *sc = ifp->if_softc;
 1211         struct ieee80211com *ic = &sc->sc_ic;
 1212 
 1213         ifp->if_timer = 0;
 1214         if (!sc->sc_enabled)
 1215                 return;
 1216 
 1217         if (sc->sc_tx_timer) {
 1218                 if (--sc->sc_tx_timer == 0) {
 1219                         printf("%s: device timeout\n", ifp->if_xname);
 1220                         ifp->if_oerrors++;
 1221                         wi_init(ifp);
 1222                         return;
 1223                 }
 1224                 ifp->if_timer = 1;
 1225         }
 1226 
 1227         if (sc->sc_scan_timer) {
 1228                 if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
 1229                     sc->sc_firmware_type == WI_INTERSIL) {
 1230                         DPRINTF(("wi_watchdog: inquire scan\n"));
 1231                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 1232                 }
 1233                 if (sc->sc_scan_timer)
 1234                         ifp->if_timer = 1;
 1235         }
 1236 
 1237         if (sc->sc_syn_timer) {
 1238                 if (--sc->sc_syn_timer == 0) {
 1239                         DPRINTF2(("%s: %d false syns\n",
 1240                             sc->sc_dev.dv_xname, sc->sc_false_syns));
 1241                         sc->sc_false_syns = 0;
 1242                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 1243                         sc->sc_syn_timer = 5;
 1244                 }
 1245                 ifp->if_timer = 1;
 1246         }
 1247 
 1248         /* TODO: rate control */
 1249         ieee80211_watchdog(ifp);
 1250 }
 1251 
 1252 STATIC int
 1253 wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1254 {
 1255         struct wi_softc *sc = ifp->if_softc;
 1256         struct ieee80211com *ic = &sc->sc_ic;
 1257         struct ifreq *ifr = (struct ifreq *)data;
 1258         int s, error = 0;
 1259 
 1260         if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
 1261                 return ENXIO;
 1262 
 1263         s = splnet();
 1264 
 1265         switch (cmd) {
 1266         case SIOCSIFFLAGS:
 1267                 /*
 1268                  * Can't do promisc and hostap at the same time.  If all that's
 1269                  * changing is the promisc flag, try to short-circuit a call to
 1270                  * wi_init() by just setting PROMISC in the hardware.
 1271                  */
 1272                 if (ifp->if_flags & IFF_UP) {
 1273                         if (sc->sc_enabled) {
 1274                                 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
 1275                                     (ifp->if_flags & IFF_PROMISC) != 0)
 1276                                         wi_write_val(sc, WI_RID_PROMISC, 1);
 1277                                 else
 1278                                         wi_write_val(sc, WI_RID_PROMISC, 0);
 1279                         } else
 1280                                 error = wi_init(ifp);
 1281                 } else if (sc->sc_enabled)
 1282                         wi_stop(ifp, 1);
 1283                 break;
 1284         case SIOCSIFMEDIA:
 1285         case SIOCGIFMEDIA:
 1286                 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
 1287                 break;
 1288         case SIOCADDMULTI:
 1289         case SIOCDELMULTI:
 1290                 error = (cmd == SIOCADDMULTI) ?
 1291                     ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
 1292                     ether_delmulti(ifr, &sc->sc_ic.ic_ec);
 1293                 if (error == ENETRESET) {
 1294                         if (sc->sc_enabled) {
 1295                                 /* do not rescan */
 1296                                 error = wi_write_multi(sc);
 1297                         } else
 1298                                 error = 0;
 1299                 }
 1300                 break;
 1301         case SIOCGIFGENERIC:
 1302                 error = wi_get_cfg(ifp, cmd, data);
 1303                 break;
 1304         case SIOCSIFGENERIC:
 1305                 error = suser(curproc->p_ucred, &curproc->p_acflag);
 1306                 if (error)
 1307                         break;
 1308                 error = wi_set_cfg(ifp, cmd, data);
 1309                 if (error == ENETRESET) {
 1310                         if (sc->sc_enabled)
 1311                                 error = wi_init(ifp);
 1312                         else
 1313                                 error = 0;
 1314                 }
 1315                 break;
 1316         case SIOCS80211BSSID:
 1317                 if (sc->sc_firmware_type == WI_LUCENT) {
 1318                         error = ENODEV;
 1319                         break;
 1320                 }
 1321                 /* fall through */
 1322         default:
 1323                 error = ieee80211_ioctl(ifp, cmd, data);
 1324                 if (error == ENETRESET) {
 1325                         if (sc->sc_enabled)
 1326                                 error = wi_init(ifp);
 1327                         else
 1328                                 error = 0;
 1329                 }
 1330                 break;
 1331         }
 1332         splx(s);
 1333         return error;
 1334 }
 1335 
 1336 STATIC int
 1337 wi_media_change(struct ifnet *ifp)
 1338 {
 1339         struct wi_softc *sc = ifp->if_softc;
 1340         struct ieee80211com *ic = &sc->sc_ic;
 1341         int error;
 1342 
 1343         error = ieee80211_media_change(ifp);
 1344         if (error == ENETRESET) {
 1345                 if (sc->sc_enabled)
 1346                         error = wi_init(ifp);
 1347                 else
 1348                         error = 0;
 1349         }
 1350         ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media);
 1351 
 1352         return error;
 1353 }
 1354 
 1355 STATIC void
 1356 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 1357 {
 1358         struct wi_softc *sc = ifp->if_softc;
 1359         struct ieee80211com *ic = &sc->sc_ic;
 1360         u_int16_t val;
 1361         int rate, len;
 1362 
 1363         if (sc->sc_enabled == 0) {
 1364                 imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
 1365                 imr->ifm_status = 0;
 1366                 return;
 1367         }
 1368 
 1369         imr->ifm_status = IFM_AVALID;
 1370         imr->ifm_active = IFM_IEEE80211;
 1371         if (ic->ic_state == IEEE80211_S_RUN &&
 1372             (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
 1373                 imr->ifm_status |= IFM_ACTIVE;
 1374         len = sizeof(val);
 1375         if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) != 0)
 1376                 rate = 0;
 1377         else {
 1378                 /* convert to 802.11 rate */
 1379                 val = le16toh(val);
 1380                 rate = val * 2;
 1381                 if (sc->sc_firmware_type == WI_LUCENT) {
 1382                         if (rate == 10)
 1383                                 rate = 11;      /* 5.5Mbps */
 1384                 } else {
 1385                         if (rate == 4*2)
 1386                                 rate = 11;      /* 5.5Mbps */
 1387                         else if (rate == 8*2)
 1388                                 rate = 22;      /* 11Mbps */
 1389                 }
 1390         }
 1391         imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
 1392         switch (ic->ic_opmode) {
 1393         case IEEE80211_M_STA:
 1394                 break;
 1395         case IEEE80211_M_IBSS:
 1396                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
 1397                 break;
 1398         case IEEE80211_M_AHDEMO:
 1399                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
 1400                 break;
 1401         case IEEE80211_M_HOSTAP:
 1402                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 1403                 break;
 1404         case IEEE80211_M_MONITOR:
 1405                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
 1406                 break;
 1407         }
 1408 }
 1409 
 1410 STATIC struct ieee80211_node *
 1411 wi_node_alloc(struct ieee80211com *ic)
 1412 {
 1413         struct wi_node *wn =
 1414             malloc(sizeof(struct wi_node), M_DEVBUF, M_NOWAIT | M_ZERO);
 1415         return wn ? &wn->wn_node : NULL;
 1416 }
 1417 
 1418 STATIC void
 1419 wi_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
 1420 {
 1421         struct wi_softc *sc = ic->ic_if.if_softc;
 1422         int i;
 1423 
 1424         for (i = 0; i < WI_NTXRSS; i++) {
 1425                 if (sc->sc_rssd[i].rd_desc.id_node == ni)
 1426                         sc->sc_rssd[i].rd_desc.id_node = NULL;
 1427         }
 1428         free(ni, M_DEVBUF);
 1429 }
 1430 
 1431 STATIC void
 1432 wi_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
 1433     const struct ieee80211_node *src)
 1434 {
 1435         *(struct wi_node *)dst = *(const struct wi_node *)src;
 1436 }
 1437 
 1438 STATIC void
 1439 wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
 1440 {
 1441         struct ieee80211com *ic = &sc->sc_ic;
 1442         struct ieee80211_node *ni = ic->ic_bss;
 1443         struct ifnet *ifp = &ic->ic_if;
 1444 
 1445         if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
 1446                 return;
 1447 
 1448         DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
 1449         DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
 1450 
 1451         /* In promiscuous mode, the BSSID field is not a reliable
 1452          * indicator of the firmware's BSSID. Damp spurious
 1453          * change-of-BSSID indications.
 1454          */
 1455         if ((ifp->if_flags & IFF_PROMISC) != 0 &&
 1456             sc->sc_false_syns >= WI_MAX_FALSE_SYNS)
 1457                 return;
 1458 
 1459         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 1460 }
 1461 
 1462 static __inline void
 1463 wi_rssadapt_input(struct ieee80211com *ic, struct ieee80211_node *ni,
 1464     struct ieee80211_frame *wh, int rssi)
 1465 {
 1466         struct wi_node *wn;
 1467 
 1468         if (ni == NULL) {
 1469                 printf("%s: null node", __func__);
 1470                 return;
 1471         }
 1472 
 1473         wn = (void*)ni;
 1474         ieee80211_rssadapt_input(ic, ni, &wn->wn_rssadapt, rssi);
 1475 }
 1476 
 1477 STATIC void
 1478 wi_rx_intr(struct wi_softc *sc)
 1479 {
 1480         struct ieee80211com *ic = &sc->sc_ic;
 1481         struct ifnet *ifp = &ic->ic_if;
 1482         struct ieee80211_node *ni;
 1483         struct wi_frame frmhdr;
 1484         struct mbuf *m;
 1485         struct ieee80211_frame *wh;
 1486         int fid, len, off, rssi;
 1487         u_int8_t dir;
 1488         u_int16_t status;
 1489         u_int32_t rstamp;
 1490 
 1491         fid = CSR_READ_2(sc, WI_RX_FID);
 1492 
 1493         /* First read in the frame header */
 1494         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
 1495                 printf("%s: %s read fid %x failed\n", sc->sc_dev.dv_xname,
 1496                     __func__, fid);
 1497                 ifp->if_ierrors++;
 1498                 return;
 1499         }
 1500 
 1501         if (IFF_DUMPPKTS(ifp))
 1502                 wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
 1503 
 1504         /*
 1505          * Drop undecryptable or packets with receive errors here
 1506          */
 1507         status = le16toh(frmhdr.wi_status);
 1508         if ((status & WI_STAT_ERRSTAT) != 0 &&
 1509             ic->ic_opmode != IEEE80211_M_MONITOR) {
 1510                 ifp->if_ierrors++;
 1511                 DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
 1512                 return;
 1513         }
 1514         rssi = frmhdr.wi_rx_signal;
 1515         rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
 1516             le16toh(frmhdr.wi_rx_tstamp1);
 1517 
 1518         len = le16toh(frmhdr.wi_dat_len);
 1519         off = ALIGN(sizeof(struct ieee80211_frame));
 1520 
 1521         /* Sometimes the PRISM2.x returns bogusly large frames. Except
 1522          * in monitor mode, just throw them away.
 1523          */
 1524         if (off + len > MCLBYTES) {
 1525                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
 1526                         ifp->if_ierrors++;
 1527                         DPRINTF(("wi_rx_intr: oversized packet\n"));
 1528                         return;
 1529                 } else
 1530                         len = 0;
 1531         }
 1532 
 1533         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1534         if (m == NULL) {
 1535                 ifp->if_ierrors++;
 1536                 DPRINTF(("wi_rx_intr: MGET failed\n"));
 1537                 return;
 1538         }
 1539         if (off + len > MHLEN) {
 1540                 MCLGET(m, M_DONTWAIT);
 1541                 if ((m->m_flags & M_EXT) == 0) {
 1542                         m_freem(m);
 1543                         ifp->if_ierrors++;
 1544                         DPRINTF(("wi_rx_intr: MCLGET failed\n"));
 1545                         return;
 1546                 }
 1547         }
 1548 
 1549         m->m_data += off - sizeof(struct ieee80211_frame);
 1550         memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
 1551         wi_read_bap(sc, fid, sizeof(frmhdr),
 1552             m->m_data + sizeof(struct ieee80211_frame), len);
 1553         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
 1554         m->m_pkthdr.rcvif = ifp;
 1555 
 1556 #if NBPFILTER > 0
 1557         if (sc->sc_drvbpf) {
 1558                 struct mbuf mb;
 1559                 struct wi_rx_radiotap_header *tap = &sc->sc_rxtap;
 1560 
 1561                 tap->wr_rate = frmhdr.wi_rx_rate / 5;
 1562                 tap->wr_antsignal = WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_signal);
 1563                 tap->wr_antnoise = WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_silence);
 1564 
 1565                 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
 1566                 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
 1567                 if (frmhdr.wi_status & WI_STAT_PCF)
 1568                         tap->wr_flags |= IEEE80211_RADIOTAP_F_CFP;
 1569 
 1570                 M_COPY_PKTHDR(&mb, m);
 1571                 mb.m_data = (caddr_t)tap;
 1572                 mb.m_len = tap->wr_ihdr.it_len;
 1573                 mb.m_next = m;
 1574                 mb.m_pkthdr.len += mb.m_len;
 1575                 bpf_mtap(sc->sc_drvbpf, &mb);
 1576         }
 1577 #endif
 1578         wh = mtod(m, struct ieee80211_frame *);
 1579         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 1580                 /*
 1581                  * WEP is decrypted by hardware. Clear WEP bit
 1582                  * header for ieee80211_input().
 1583                  */
 1584                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
 1585         }
 1586 
 1587         /* synchronize driver's BSSID with firmware's BSSID */
 1588         dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
 1589         if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
 1590                 wi_sync_bssid(sc, wh->i_addr3);
 1591 
 1592         ni = ieee80211_find_rxnode(ic, wh);
 1593 
 1594         ieee80211_input(ifp, m, ni, rssi, rstamp);
 1595 
 1596         wi_rssadapt_input(ic, ni, wh, rssi);
 1597 
 1598         /*
 1599          * The frame may have caused the node to be marked for
 1600          * reclamation (e.g. in response to a DEAUTH message)
 1601          * so use free_node here instead of unref_node.
 1602          */
 1603         if (ni == ic->ic_bss)
 1604                 ieee80211_unref_node(&ni);
 1605         else
 1606                 ieee80211_free_node(ic, ni);
 1607 }
 1608 
 1609 STATIC void
 1610 wi_tx_ex_intr(struct wi_softc *sc)
 1611 {
 1612         struct ieee80211com *ic = &sc->sc_ic;
 1613         struct ifnet *ifp = &ic->ic_if;
 1614         struct ieee80211_node *ni;
 1615         struct ieee80211_rssdesc *id;
 1616         struct wi_rssdesc *rssd;
 1617         struct wi_frame frmhdr;
 1618         int fid;
 1619         u_int16_t status;
 1620 
 1621         fid = CSR_READ_2(sc, WI_TX_CMP_FID);
 1622         /* Read in the frame header */
 1623         if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
 1624                 printf("%s: %s read fid %x failed\n", sc->sc_dev.dv_xname,
 1625                     __func__, fid);
 1626                 wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
 1627                     &sc->sc_txpending);
 1628                 goto out;
 1629         }
 1630 
 1631         if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
 1632                 printf("%s: %s bad idx %02x\n",
 1633                     sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
 1634                 wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
 1635                     &sc->sc_txpending);
 1636                 goto out;
 1637         }
 1638 
 1639         status = le16toh(frmhdr.wi_status);
 1640 
 1641         /*
 1642          * Spontaneous station disconnects appear as xmit
 1643          * errors.  Don't announce them and/or count them
 1644          * as an output error.
 1645          */
 1646         if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
 1647                 printf("%s: tx failed", sc->sc_dev.dv_xname);
 1648                 if (status & WI_TXSTAT_RET_ERR)
 1649                         printf(", retry limit exceeded");
 1650                 if (status & WI_TXSTAT_AGED_ERR)
 1651                         printf(", max transmit lifetime exceeded");
 1652                 if (status & WI_TXSTAT_DISCONNECT)
 1653                         printf(", port disconnected");
 1654                 if (status & WI_TXSTAT_FORM_ERR)
 1655                         printf(", invalid format (data len %u src %s)",
 1656                                 le16toh(frmhdr.wi_dat_len),
 1657                                 ether_sprintf(frmhdr.wi_ehdr.ether_shost));
 1658                 if (status & ~0xf)
 1659                         printf(", status=0x%x", status);
 1660                 printf("\n");
 1661         }
 1662         ifp->if_oerrors++;
 1663         rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
 1664         id = &rssd->rd_desc;
 1665         if ((status & WI_TXSTAT_RET_ERR) != 0)
 1666                 wi_lower_rate(ic, id);
 1667 
 1668         ni = id->id_node;
 1669         id->id_node = NULL;
 1670 
 1671         if (ni == NULL) {
 1672                 printf("%s: %s null node, rssdesc %02x\n",
 1673                     sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
 1674                 goto out;
 1675         }
 1676 
 1677         if (sc->sc_txpending[id->id_rateidx]-- == 0) {
 1678                 printf("%s: %s txpending[%i] wraparound", sc->sc_dev.dv_xname,
 1679                     __func__, id->id_rateidx);
 1680                 sc->sc_txpending[id->id_rateidx] = 0;
 1681         }
 1682         if (ni != NULL && ni != ic->ic_bss)
 1683                 ieee80211_free_node(ic, ni);
 1684         SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
 1685 out:
 1686         ifp->if_flags &= ~IFF_OACTIVE;
 1687 }
 1688 
 1689 STATIC void
 1690 wi_txalloc_intr(struct wi_softc *sc)
 1691 {
 1692         struct ieee80211com *ic = &sc->sc_ic;
 1693         struct ifnet *ifp = &ic->ic_if;
 1694         int fid, cur;
 1695 
 1696         fid = CSR_READ_2(sc, WI_ALLOC_FID);
 1697 
 1698         cur = sc->sc_txalloc;
 1699 #ifdef DIAGNOSTIC
 1700         if (sc->sc_txstarted == 0) {
 1701                 printf("%s: spurious alloc %x != %x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
 1702                     sc->sc_dev.dv_xname, fid, sc->sc_txd[cur].d_fid, cur,
 1703                     sc->sc_txqueue, sc->sc_txstart, sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
 1704                 return;
 1705         }
 1706 #endif
 1707         --sc->sc_txstarted;
 1708         ++sc->sc_txalloced;
 1709         sc->sc_txd[cur].d_fid = fid;
 1710         sc->sc_txalloc = (cur + 1) % WI_NTXBUF;
 1711 #ifdef WI_RING_DEBUG
 1712         printf("%s: alloc %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
 1713             sc->sc_dev.dv_xname, fid,
 1714             sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
 1715             sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
 1716 #endif
 1717         if (--sc->sc_txqueued == 0) {
 1718                 sc->sc_tx_timer = 0;
 1719                 ifp->if_flags &= ~IFF_OACTIVE;
 1720         } else
 1721                 wi_push_packet(sc);
 1722 }
 1723 
 1724 STATIC void
 1725 wi_push_packet(struct wi_softc *sc)
 1726 {
 1727         struct ieee80211com *ic = &sc->sc_ic;
 1728         struct ifnet *ifp = &ic->ic_if;
 1729         int cur, fid;
 1730 
 1731         cur = sc->sc_txstart;
 1732         fid = sc->sc_txd[cur].d_fid;
 1733         if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
 1734                 printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
 1735                 /* XXX ring might have a hole */
 1736         }
 1737         ++sc->sc_txstarted;
 1738 #ifdef DIAGNOSTIC
 1739         if (sc->sc_txstarted > WI_NTXBUF)
 1740                 printf("%s: too many buffers started\n", sc->sc_dev.dv_xname);
 1741 #endif
 1742         sc->sc_txstart = (cur + 1) % WI_NTXBUF;
 1743         sc->sc_tx_timer = 5;
 1744         ifp->if_timer = 1;
 1745 #ifdef WI_RING_DEBUG
 1746         printf("%s: push  %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
 1747             sc->sc_dev.dv_xname, fid,
 1748             sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
 1749             sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
 1750 #endif
 1751 }
 1752 
 1753 STATIC void
 1754 wi_tx_intr(struct wi_softc *sc)
 1755 {
 1756         struct ieee80211com *ic = &sc->sc_ic;
 1757         struct ifnet *ifp = &ic->ic_if;
 1758         struct ieee80211_node *ni;
 1759         struct ieee80211_rssdesc *id;
 1760         struct wi_rssdesc *rssd;
 1761         struct wi_frame frmhdr;
 1762         int fid;
 1763 
 1764         fid = CSR_READ_2(sc, WI_TX_CMP_FID);
 1765         /* Read in the frame header */
 1766         if (wi_read_bap(sc, fid, 8, &frmhdr.wi_rx_rate, 2) != 0) {
 1767                 printf("%s: %s read fid %x failed\n", sc->sc_dev.dv_xname,
 1768                     __func__, fid);
 1769                 wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
 1770                     &sc->sc_txpending);
 1771                 goto out;
 1772         }
 1773 
 1774         if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
 1775                 printf("%s: %s bad idx %02x\n",
 1776                     sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
 1777                 wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
 1778                     &sc->sc_txpending);
 1779                 goto out;
 1780         }
 1781 
 1782         rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
 1783         id = &rssd->rd_desc;
 1784         wi_raise_rate(ic, id);
 1785 
 1786         ni = id->id_node;
 1787         id->id_node = NULL;
 1788 
 1789         if (ni == NULL) {
 1790                 printf("%s: %s null node, rssdesc %02x\n",
 1791                     sc->sc_dev.dv_xname, __func__, frmhdr.wi_tx_idx);
 1792                 goto out;
 1793         }
 1794 
 1795         if (sc->sc_txpending[id->id_rateidx]-- == 0) {
 1796                 printf("%s: %s txpending[%i] wraparound", sc->sc_dev.dv_xname,
 1797                     __func__, id->id_rateidx);
 1798                 sc->sc_txpending[id->id_rateidx] = 0;
 1799         }
 1800         if (ni != NULL && ni != ic->ic_bss)
 1801                 ieee80211_free_node(ic, ni);
 1802         SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
 1803 out:
 1804         ifp->if_flags &= ~IFF_OACTIVE;
 1805 }
 1806 
 1807 STATIC void
 1808 wi_info_intr(struct wi_softc *sc)
 1809 {
 1810         struct ieee80211com *ic = &sc->sc_ic;
 1811         struct ifnet *ifp = &ic->ic_if;
 1812         int i, fid, len, off;
 1813         u_int16_t ltbuf[2];
 1814         u_int16_t stat;
 1815         u_int32_t *ptr;
 1816 
 1817         fid = CSR_READ_2(sc, WI_INFO_FID);
 1818         wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
 1819 
 1820         switch (le16toh(ltbuf[1])) {
 1821 
 1822         case WI_INFO_LINK_STAT:
 1823                 wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
 1824                 DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
 1825                 switch (le16toh(stat)) {
 1826                 case CONNECTED:
 1827                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 1828                         if (ic->ic_state == IEEE80211_S_RUN &&
 1829                             ic->ic_opmode != IEEE80211_M_IBSS)
 1830                                 break;
 1831                         /* FALLTHROUGH */
 1832                 case AP_CHANGE:
 1833                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 1834                         break;
 1835                 case AP_IN_RANGE:
 1836                         sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 1837                         break;
 1838                 case AP_OUT_OF_RANGE:
 1839                         if (sc->sc_firmware_type == WI_SYMBOL &&
 1840                             sc->sc_scan_timer > 0) {
 1841                                 if (wi_cmd(sc, WI_CMD_INQUIRE,
 1842                                     WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
 1843                                         sc->sc_scan_timer = 0;
 1844                                 break;
 1845                         }
 1846                         if (ic->ic_opmode == IEEE80211_M_STA)
 1847                                 sc->sc_flags |= WI_FLAGS_OUTRANGE;
 1848                         break;
 1849                 case DISCONNECTED:
 1850                 case ASSOC_FAILED:
 1851                         if (ic->ic_opmode == IEEE80211_M_STA)
 1852                                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 1853                         break;
 1854                 }
 1855                 break;
 1856 
 1857         case WI_INFO_COUNTERS:
 1858                 /* some card versions have a larger stats structure */
 1859                 len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
 1860                 ptr = (u_int32_t *)&sc->sc_stats;
 1861                 off = sizeof(ltbuf);
 1862                 for (i = 0; i < len; i++, off += 2, ptr++) {
 1863                         wi_read_bap(sc, fid, off, &stat, sizeof(stat));
 1864                         stat = le16toh(stat);
 1865 #ifdef WI_HERMES_STATS_WAR
 1866                         if (stat & 0xf000)
 1867                                 stat = ~stat;
 1868 #endif
 1869                         *ptr += stat;
 1870                 }
 1871                 ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
 1872                     sc->sc_stats.wi_tx_multi_retries +
 1873                     sc->sc_stats.wi_tx_retry_limit;
 1874                 break;
 1875 
 1876         case WI_INFO_SCAN_RESULTS:
 1877         case WI_INFO_HOST_SCAN_RESULTS:
 1878                 wi_scan_result(sc, fid, le16toh(ltbuf[0]));
 1879                 break;
 1880 
 1881         default:
 1882                 DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
 1883                     le16toh(ltbuf[1]), le16toh(ltbuf[0])));
 1884                 break;
 1885         }
 1886 }
 1887 
 1888 STATIC int
 1889 wi_write_multi(struct wi_softc *sc)
 1890 {
 1891         struct ifnet *ifp = &sc->sc_ic.ic_if;
 1892         int n;
 1893         struct wi_mcast mlist;
 1894         struct ether_multi *enm;
 1895         struct ether_multistep estep;
 1896 
 1897         if ((ifp->if_flags & IFF_PROMISC) != 0) {
 1898 allmulti:
 1899                 ifp->if_flags |= IFF_ALLMULTI;
 1900                 memset(&mlist, 0, sizeof(mlist));
 1901                 return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
 1902                     sizeof(mlist));
 1903         }
 1904 
 1905         n = 0;
 1906         ETHER_FIRST_MULTI(estep, &sc->sc_ic.ic_ec, enm);
 1907         while (enm != NULL) {
 1908                 /* Punt on ranges or too many multicast addresses. */
 1909                 if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi) ||
 1910                     n >= sizeof(mlist) / sizeof(mlist.wi_mcast[0]))
 1911                         goto allmulti;
 1912 
 1913                 IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], enm->enm_addrlo);
 1914                 n++;
 1915                 ETHER_NEXT_MULTI(estep, enm);
 1916         }
 1917         ifp->if_flags &= ~IFF_ALLMULTI;
 1918         return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
 1919             IEEE80211_ADDR_LEN * n);
 1920 }
 1921 
 1922 
 1923 STATIC void
 1924 wi_read_nicid(struct wi_softc *sc)
 1925 {
 1926         struct wi_card_ident *id;
 1927         char *p;
 1928         int len;
 1929         u_int16_t ver[4];
 1930 
 1931         /* getting chip identity */
 1932         memset(ver, 0, sizeof(ver));
 1933         len = sizeof(ver);
 1934         wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
 1935         printf("%s: using ", sc->sc_dev.dv_xname);
 1936 DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
 1937 
 1938         sc->sc_firmware_type = WI_NOTYPE;
 1939         for (id = wi_card_ident; id->card_name != NULL; id++) {
 1940                 if (le16toh(ver[0]) == id->card_id) {
 1941                         printf("%s", id->card_name);
 1942                         sc->sc_firmware_type = id->firm_type;
 1943                         break;
 1944                 }
 1945         }
 1946         if (sc->sc_firmware_type == WI_NOTYPE) {
 1947                 if (le16toh(ver[0]) & 0x8000) {
 1948                         printf("Unknown PRISM2 chip");
 1949                         sc->sc_firmware_type = WI_INTERSIL;
 1950                 } else {
 1951                         printf("Unknown Lucent chip");
 1952                         sc->sc_firmware_type = WI_LUCENT;
 1953                 }
 1954         }
 1955 
 1956         /* get primary firmware version (Only Prism chips) */
 1957         if (sc->sc_firmware_type != WI_LUCENT) {
 1958                 memset(ver, 0, sizeof(ver));
 1959                 len = sizeof(ver);
 1960                 wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
 1961                 sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
 1962                     le16toh(ver[3]) * 100 + le16toh(ver[1]);
 1963         }
 1964 
 1965         /* get station firmware version */
 1966         memset(ver, 0, sizeof(ver));
 1967         len = sizeof(ver);
 1968         wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
 1969         sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
 1970             le16toh(ver[3]) * 100 + le16toh(ver[1]);
 1971         if (sc->sc_firmware_type == WI_INTERSIL &&
 1972             (sc->sc_sta_firmware_ver == 10102 ||
 1973              sc->sc_sta_firmware_ver == 20102)) {
 1974                 char ident[12];
 1975                 memset(ident, 0, sizeof(ident));
 1976                 len = sizeof(ident);
 1977                 /* value should be the format like "V2.00-11" */
 1978                 if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
 1979                     *(p = (char *)ident) >= 'A' &&
 1980                     p[2] == '.' && p[5] == '-' && p[8] == '\0') {
 1981                         sc->sc_firmware_type = WI_SYMBOL;
 1982                         sc->sc_sta_firmware_ver = (p[1] - '') * 10000 +
 1983                             (p[3] - '') * 1000 + (p[4] - '') * 100 +
 1984                             (p[6] - '') * 10 + (p[7] - '');
 1985                 }
 1986         }
 1987 
 1988         printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
 1989              sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
 1990             (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
 1991         if (sc->sc_firmware_type != WI_LUCENT)  /* XXX */
 1992                 printf("Primary (%u.%u.%u), ",
 1993                     sc->sc_pri_firmware_ver / 10000,
 1994                     (sc->sc_pri_firmware_ver % 10000) / 100,
 1995                     sc->sc_pri_firmware_ver % 100);
 1996         printf("Station (%u.%u.%u)\n",
 1997             sc->sc_sta_firmware_ver / 10000,
 1998             (sc->sc_sta_firmware_ver % 10000) / 100,
 1999             sc->sc_sta_firmware_ver % 100);
 2000 }
 2001 
 2002 STATIC int
 2003 wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
 2004 {
 2005         struct wi_ssid ssid;
 2006 
 2007         if (buflen > IEEE80211_NWID_LEN)
 2008                 return ENOBUFS;
 2009         memset(&ssid, 0, sizeof(ssid));
 2010         ssid.wi_len = htole16(buflen);
 2011         memcpy(ssid.wi_ssid, buf, buflen);
 2012         return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
 2013 }
 2014 
 2015 STATIC int
 2016 wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
 2017 {
 2018         struct wi_softc *sc = ifp->if_softc;
 2019         struct ieee80211com *ic = &sc->sc_ic;
 2020         struct ifreq *ifr = (struct ifreq *)data;
 2021         struct wi_req wreq;
 2022         int len, n, error;
 2023 
 2024         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 2025         if (error)
 2026                 return error;
 2027         len = (wreq.wi_len - 1) * 2;
 2028         if (len < sizeof(u_int16_t))
 2029                 return ENOSPC;
 2030         if (len > sizeof(wreq.wi_val))
 2031                 len = sizeof(wreq.wi_val);
 2032 
 2033         switch (wreq.wi_type) {
 2034 
 2035         case WI_RID_IFACE_STATS:
 2036                 memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
 2037                 if (len < sizeof(sc->sc_stats))
 2038                         error = ENOSPC;
 2039                 else
 2040                         len = sizeof(sc->sc_stats);
 2041                 break;
 2042 
 2043         case WI_RID_ENCRYPTION:
 2044         case WI_RID_TX_CRYPT_KEY:
 2045         case WI_RID_DEFLT_CRYPT_KEYS:
 2046         case WI_RID_TX_RATE:
 2047                 return ieee80211_cfgget(ifp, cmd, data);
 2048 
 2049         case WI_RID_MICROWAVE_OVEN:
 2050                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
 2051                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2052                             &len);
 2053                         break;
 2054                 }
 2055                 wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
 2056                 len = sizeof(u_int16_t);
 2057                 break;
 2058 
 2059         case WI_RID_DBM_ADJUST:
 2060                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
 2061                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2062                             &len);
 2063                         break;
 2064                 }
 2065                 wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
 2066                 len = sizeof(u_int16_t);
 2067                 break;
 2068 
 2069         case WI_RID_ROAMING_MODE:
 2070                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
 2071                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2072                             &len);
 2073                         break;
 2074                 }
 2075                 wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
 2076                 len = sizeof(u_int16_t);
 2077                 break;
 2078 
 2079         case WI_RID_SYSTEM_SCALE:
 2080                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
 2081                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2082                             &len);
 2083                         break;
 2084                 }
 2085                 wreq.wi_val[0] = htole16(sc->sc_system_scale);
 2086                 len = sizeof(u_int16_t);
 2087                 break;
 2088 
 2089         case WI_RID_FRAG_THRESH:
 2090                 if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
 2091                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2092                             &len);
 2093                         break;
 2094                 }
 2095                 wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
 2096                 len = sizeof(u_int16_t);
 2097                 break;
 2098 
 2099         case WI_RID_READ_APS:
 2100                 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
 2101                         return ieee80211_cfgget(ifp, cmd, data);
 2102                 if (sc->sc_scan_timer > 0) {
 2103                         error = EINPROGRESS;
 2104                         break;
 2105                 }
 2106                 n = sc->sc_naps;
 2107                 if (len < sizeof(n)) {
 2108                         error = ENOSPC;
 2109                         break;
 2110                 }
 2111                 if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
 2112                         n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
 2113                 len = sizeof(n) + sizeof(struct wi_apinfo) * n;
 2114                 memcpy(wreq.wi_val, &n, sizeof(n));
 2115                 memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
 2116                     sizeof(struct wi_apinfo) * n);
 2117                 break;
 2118 
 2119         default:
 2120                 if (sc->sc_enabled) {
 2121                         error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
 2122                             &len);
 2123                         break;
 2124                 }
 2125                 switch (wreq.wi_type) {
 2126                 case WI_RID_MAX_DATALEN:
 2127                         wreq.wi_val[0] = htole16(sc->sc_max_datalen);
 2128                         len = sizeof(u_int16_t);
 2129                         break;
 2130                 case WI_RID_FRAG_THRESH:
 2131                         wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
 2132                         len = sizeof(u_int16_t);
 2133                         break;
 2134                 case WI_RID_RTS_THRESH:
 2135                         wreq.wi_val[0] = htole16(sc->sc_rts_thresh);
 2136                         len = sizeof(u_int16_t);
 2137                         break;
 2138                 case WI_RID_CNFAUTHMODE:
 2139                         wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
 2140                         len = sizeof(u_int16_t);
 2141                         break;
 2142                 case WI_RID_NODENAME:
 2143                         if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
 2144                                 error = ENOSPC;
 2145                                 break;
 2146                         }
 2147                         len = sc->sc_nodelen + sizeof(u_int16_t);
 2148                         wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
 2149                         memcpy(&wreq.wi_val[1], sc->sc_nodename,
 2150                             sc->sc_nodelen);
 2151                         break;
 2152                 default:
 2153                         return ieee80211_cfgget(ifp, cmd, data);
 2154                 }
 2155                 break;
 2156         }
 2157         if (error)
 2158                 return error;
 2159         wreq.wi_len = (len + 1) / 2 + 1;
 2160         return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
 2161 }
 2162 
 2163 STATIC int
 2164 wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
 2165 {
 2166         struct wi_softc *sc = ifp->if_softc;
 2167         struct ieee80211com *ic = &sc->sc_ic;
 2168         struct ifreq *ifr = (struct ifreq *)data;
 2169         struct ieee80211_rateset *rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
 2170         struct wi_req wreq;
 2171         struct mbuf *m;
 2172         int i, len, error;
 2173 
 2174         error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 2175         if (error)
 2176                 return error;
 2177         len = (wreq.wi_len - 1) * 2;
 2178         switch (wreq.wi_type) {
 2179         case WI_RID_DBM_ADJUST:
 2180                 return ENODEV;
 2181 
 2182         case WI_RID_NODENAME:
 2183                 if (le16toh(wreq.wi_val[0]) * 2 > len ||
 2184                     le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
 2185                         error = ENOSPC;
 2186                         break;
 2187                 }
 2188                 if (sc->sc_enabled) {
 2189                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2190                             len);
 2191                         if (error)
 2192                                 break;
 2193                 }
 2194                 sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
 2195                 memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
 2196                 break;
 2197 
 2198         case WI_RID_MICROWAVE_OVEN:
 2199         case WI_RID_ROAMING_MODE:
 2200         case WI_RID_SYSTEM_SCALE:
 2201         case WI_RID_FRAG_THRESH:
 2202                 if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
 2203                     (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
 2204                         break;
 2205                 if (wreq.wi_type == WI_RID_ROAMING_MODE &&
 2206                     (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
 2207                         break;
 2208                 if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
 2209                     (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
 2210                         break;
 2211                 if (wreq.wi_type == WI_RID_FRAG_THRESH &&
 2212                     (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
 2213                         break;
 2214                 /* FALLTHROUGH */
 2215         case WI_RID_RTS_THRESH:
 2216         case WI_RID_CNFAUTHMODE:
 2217         case WI_RID_MAX_DATALEN:
 2218                 if (sc->sc_enabled) {
 2219                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2220                             sizeof(u_int16_t));
 2221                         if (error)
 2222                                 break;
 2223                 }
 2224                 switch (wreq.wi_type) {
 2225                 case WI_RID_FRAG_THRESH:
 2226                         sc->sc_frag_thresh = le16toh(wreq.wi_val[0]);
 2227                         break;
 2228                 case WI_RID_RTS_THRESH:
 2229                         sc->sc_rts_thresh = le16toh(wreq.wi_val[0]);
 2230                         break;
 2231                 case WI_RID_MICROWAVE_OVEN:
 2232                         sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
 2233                         break;
 2234                 case WI_RID_ROAMING_MODE:
 2235                         sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
 2236                         break;
 2237                 case WI_RID_SYSTEM_SCALE:
 2238                         sc->sc_system_scale = le16toh(wreq.wi_val[0]);
 2239                         break;
 2240                 case WI_RID_CNFAUTHMODE:
 2241                         sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
 2242                         break;
 2243                 case WI_RID_MAX_DATALEN:
 2244                         sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
 2245                         break;
 2246                 }
 2247                 break;
 2248 
 2249         case WI_RID_TX_RATE:
 2250                 switch (le16toh(wreq.wi_val[0])) {
 2251                 case 3:
 2252                         ic->ic_fixed_rate = -1;
 2253                         break;
 2254                 default:
 2255                         for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
 2256                                 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
 2257                                     / 2 == le16toh(wreq.wi_val[0]))
 2258                                         break;
 2259                         }
 2260                         if (i == IEEE80211_RATE_SIZE)
 2261                                 return EINVAL;
 2262                         ic->ic_fixed_rate = i;
 2263                 }
 2264                 if (sc->sc_enabled)
 2265                         error = wi_cfg_txrate(sc);
 2266                 break;
 2267 
 2268         case WI_RID_SCAN_APS:
 2269                 if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
 2270                         error = wi_scan_ap(sc, 0x3fff, 0x000f);
 2271                 break;
 2272 
 2273         case WI_RID_MGMT_XMIT:
 2274                 if (!sc->sc_enabled) {
 2275                         error = ENETDOWN;
 2276                         break;
 2277                 }
 2278                 if (ic->ic_mgtq.ifq_len > 5) {
 2279                         error = EAGAIN;
 2280                         break;
 2281                 }
 2282                 /* XXX wi_len looks in u_int8_t, not in u_int16_t */
 2283                 m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
 2284                 if (m == NULL) {
 2285                         error = ENOMEM;
 2286                         break;
 2287                 }
 2288                 IF_ENQUEUE(&ic->ic_mgtq, m);
 2289                 break;
 2290 
 2291         default:
 2292                 if (sc->sc_enabled) {
 2293                         error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
 2294                             len);
 2295                         if (error)
 2296                                 break;
 2297                 }
 2298                 error = ieee80211_cfgset(ifp, cmd, data);
 2299                 break;
 2300         }
 2301         return error;
 2302 }
 2303 
 2304 /* Rate is 0 for hardware auto-select, otherwise rate is
 2305  * 2, 4, 11, or 22 (units of 500Kbps).
 2306  */
 2307 STATIC int
 2308 wi_write_txrate(struct wi_softc *sc, int rate)
 2309 {
 2310         u_int16_t hwrate;
 2311 
 2312         /* rate: 0, 2, 4, 11, 22 */
 2313         switch (sc->sc_firmware_type) {
 2314         case WI_LUCENT:
 2315                 switch (rate & IEEE80211_RATE_VAL) {
 2316                 case 2:
 2317                         hwrate = 1;
 2318                         break;
 2319                 case 4:
 2320                         hwrate = 2;
 2321                         break;
 2322                 default:
 2323                         hwrate = 3;     /* auto */
 2324                         break;
 2325                 case 11:
 2326                         hwrate = 4;
 2327                         break;
 2328                 case 22:
 2329                         hwrate = 5;
 2330                         break;
 2331                 }
 2332                 break;
 2333         default:
 2334                 switch (rate & IEEE80211_RATE_VAL) {
 2335                 case 2:
 2336                         hwrate = 1;
 2337                         break;
 2338                 case 4:
 2339                         hwrate = 2;
 2340                         break;
 2341                 case 11:
 2342                         hwrate = 4;
 2343                         break;
 2344                 case 22:
 2345                         hwrate = 8;
 2346                         break;
 2347                 default:
 2348                         hwrate = 15;    /* auto */
 2349                         break;
 2350                 }
 2351                 break;
 2352         }
 2353 
 2354         if (sc->sc_tx_rate == hwrate)
 2355                 return 0;
 2356 
 2357         if (sc->sc_if.if_flags & IFF_DEBUG)
 2358                 printf("%s: tx rate %d -> %d (%d)\n", __func__, sc->sc_tx_rate,
 2359                     hwrate, rate);
 2360 
 2361         sc->sc_tx_rate = hwrate;
 2362 
 2363         return wi_write_val(sc, WI_RID_TX_RATE, sc->sc_tx_rate);
 2364 }
 2365 
 2366 STATIC int
 2367 wi_cfg_txrate(struct wi_softc *sc)
 2368 {
 2369         struct ieee80211com *ic = &sc->sc_ic;
 2370         struct ieee80211_rateset *rs;
 2371         int rate;
 2372 
 2373         rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
 2374 
 2375         sc->sc_tx_rate = 0; /* force write to RID */
 2376 
 2377         if (ic->ic_fixed_rate < 0)
 2378                 rate = 0;       /* auto */
 2379         else
 2380                 rate = rs->rs_rates[ic->ic_fixed_rate];
 2381 
 2382         return wi_write_txrate(sc, rate);
 2383 }
 2384 
 2385 STATIC int
 2386 wi_write_wep(struct wi_softc *sc)
 2387 {
 2388         struct ieee80211com *ic = &sc->sc_ic;
 2389         int error = 0;
 2390         int i, keylen;
 2391         u_int16_t val;
 2392         struct wi_key wkey[IEEE80211_WEP_NKID];
 2393 
 2394         switch (sc->sc_firmware_type) {
 2395         case WI_LUCENT:
 2396                 val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
 2397                 error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
 2398                 if (error)
 2399                         break;
 2400                 error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
 2401                 if (error)
 2402                         break;
 2403                 memset(wkey, 0, sizeof(wkey));
 2404                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
 2405                         keylen = ic->ic_nw_keys[i].wk_len;
 2406                         wkey[i].wi_keylen = htole16(keylen);
 2407                         memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
 2408                             keylen);
 2409                 }
 2410                 error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
 2411                     wkey, sizeof(wkey));
 2412                 break;
 2413 
 2414         case WI_INTERSIL:
 2415         case WI_SYMBOL:
 2416                 if (ic->ic_flags & IEEE80211_F_WEPON) {
 2417                         /*
 2418                          * ONLY HWB3163 EVAL-CARD Firmware version
 2419                          * less than 0.8 variant2
 2420                          *
 2421                          *   If promiscuous mode disable, Prism2 chip
 2422                          *  does not work with WEP .
 2423                          * It is under investigation for details.
 2424                          * (ichiro@NetBSD.org)
 2425                          */
 2426                         if (sc->sc_firmware_type == WI_INTERSIL &&
 2427                             sc->sc_sta_firmware_ver < 802 ) {
 2428                                 /* firm ver < 0.8 variant 2 */
 2429                                 wi_write_val(sc, WI_RID_PROMISC, 1);
 2430                         }
 2431                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
 2432                             sc->sc_cnfauthmode);
 2433                         val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
 2434                         /*
 2435                          * Encryption firmware has a bug for HostAP mode.
 2436                          */
 2437                         if (sc->sc_firmware_type == WI_INTERSIL &&
 2438                             ic->ic_opmode == IEEE80211_M_HOSTAP)
 2439                                 val |= HOST_ENCRYPT;
 2440                 } else {
 2441                         wi_write_val(sc, WI_RID_CNFAUTHMODE,
 2442                             IEEE80211_AUTH_OPEN);
 2443                         val = HOST_ENCRYPT | HOST_DECRYPT;
 2444                 }
 2445                 error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
 2446                 if (error)
 2447                         break;
 2448                 error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
 2449                     ic->ic_wep_txkey);
 2450                 if (error)
 2451                         break;
 2452                 /*
 2453                  * It seems that the firmware accept 104bit key only if
 2454                  * all the keys have 104bit length.  We get the length of
 2455                  * the transmit key and use it for all other keys.
 2456                  * Perhaps we should use software WEP for such situation.
 2457                  */
 2458                 keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
 2459                 if (keylen > IEEE80211_WEP_KEYLEN)
 2460                         keylen = 13;    /* 104bit keys */
 2461                 else
 2462                         keylen = IEEE80211_WEP_KEYLEN;
 2463                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
 2464                         error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
 2465                             ic->ic_nw_keys[i].wk_key, keylen);
 2466                         if (error)
 2467                                 break;
 2468                 }
 2469                 break;
 2470         }
 2471         return error;
 2472 }
 2473 
 2474 /* Must be called at proper protection level! */
 2475 STATIC int
 2476 wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
 2477 {
 2478 #ifdef WI_HISTOGRAM
 2479         static int hist1[11];
 2480         static int hist1count;
 2481         static int hist2[11];
 2482         static int hist2count;
 2483 #endif
 2484         int i, status;
 2485 
 2486         /* wait for the busy bit to clear */
 2487         for (i = 500; i > 0; i--) {     /* 5s */
 2488                 if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
 2489                         break;
 2490                 DELAY(1000);    /* 1 m sec */
 2491         }
 2492         if (i == 0) {
 2493                 printf("%s: wi_cmd: busy bit won't clear.\n",
 2494                     sc->sc_dev.dv_xname);
 2495                 return(ETIMEDOUT);
 2496         }
 2497 #ifdef WI_HISTOGRAM
 2498         if (i > 490)
 2499                 hist1[500 - i]++;
 2500         else
 2501                 hist1[10]++;
 2502         if (++hist1count == 1000) {
 2503                 hist1count = 0;
 2504                 printf("%s: hist1: %d %d %d %d %d %d %d %d %d %d %d\n",
 2505                     sc->sc_dev.dv_xname,
 2506                     hist1[0], hist1[1], hist1[2], hist1[3], hist1[4],
 2507                     hist1[5], hist1[6], hist1[7], hist1[8], hist1[9],
 2508                     hist1[10]);
 2509         }
 2510 #endif
 2511         CSR_WRITE_2(sc, WI_PARAM0, val0);
 2512         CSR_WRITE_2(sc, WI_PARAM1, val1);
 2513         CSR_WRITE_2(sc, WI_PARAM2, val2);
 2514         CSR_WRITE_2(sc, WI_COMMAND, cmd);
 2515 
 2516         if (cmd == WI_CMD_INI) {
 2517                 /* XXX: should sleep here. */
 2518                 DELAY(100*1000);
 2519         }
 2520         /* wait for the cmd completed bit */
 2521         for (i = 0; i < WI_TIMEOUT; i++) {
 2522                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
 2523                         break;
 2524                 DELAY(WI_DELAY);
 2525         }
 2526 #ifdef WI_HISTOGRAM
 2527         if (i < 100)
 2528                 hist2[i/10]++;
 2529         else
 2530                 hist2[10]++;
 2531         if (++hist2count == 1000) {
 2532                 hist2count = 0;
 2533                 printf("%s: hist2: %d %d %d %d %d %d %d %d %d %d %d\n",
 2534                     sc->sc_dev.dv_xname,
 2535                     hist2[0], hist2[1], hist2[2], hist2[3], hist2[4],
 2536                     hist2[5], hist2[6], hist2[7], hist2[8], hist2[9],
 2537                     hist2[10]);
 2538         }
 2539 #endif
 2540 
 2541         status = CSR_READ_2(sc, WI_STATUS);
 2542 
 2543         /* Ack the command */
 2544         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
 2545 
 2546         if (i == WI_TIMEOUT) {
 2547                 printf("%s: command timed out, cmd=0x%x, arg=0x%x\n",
 2548                     sc->sc_dev.dv_xname, cmd, val0);
 2549                 return ETIMEDOUT;
 2550         }
 2551 
 2552         if (status & WI_STAT_CMD_RESULT) {
 2553                 printf("%s: command failed, cmd=0x%x, arg=0x%x\n",
 2554                     sc->sc_dev.dv_xname, cmd, val0);
 2555                 return EIO;
 2556         }
 2557         return 0;
 2558 }
 2559 
 2560 STATIC int
 2561 wi_seek_bap(struct wi_softc *sc, int id, int off)
 2562 {
 2563 #ifdef WI_HISTOGRAM
 2564         static int hist4[11];
 2565         static int hist4count;
 2566 #endif
 2567         int i, status;
 2568 
 2569         CSR_WRITE_2(sc, WI_SEL0, id);
 2570         CSR_WRITE_2(sc, WI_OFF0, off);
 2571 
 2572         for (i = 0; ; i++) {
 2573                 status = CSR_READ_2(sc, WI_OFF0);
 2574                 if ((status & WI_OFF_BUSY) == 0)
 2575                         break;
 2576                 if (i == WI_TIMEOUT) {
 2577                         printf("%s: timeout in wi_seek to %x/%x\n",
 2578                             sc->sc_dev.dv_xname, id, off);
 2579                         sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2580                         return ETIMEDOUT;
 2581                 }
 2582                 DELAY(2);
 2583         }
 2584 #ifdef WI_HISTOGRAM
 2585         if (i < 100)
 2586                 hist4[i/10]++;
 2587         else
 2588                 hist4[10]++;
 2589         if (++hist4count == 2500) {
 2590                 hist4count = 0;
 2591                 printf("%s: hist4: %d %d %d %d %d %d %d %d %d %d %d\n",
 2592                     sc->sc_dev.dv_xname,
 2593                     hist4[0], hist4[1], hist4[2], hist4[3], hist4[4],
 2594                     hist4[5], hist4[6], hist4[7], hist4[8], hist4[9],
 2595                     hist4[10]);
 2596         }
 2597 #endif
 2598         if (status & WI_OFF_ERR) {
 2599                 printf("%s: failed in wi_seek to %x/%x\n",
 2600                     sc->sc_dev.dv_xname, id, off);
 2601                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2602                 return EIO;
 2603         }
 2604         sc->sc_bap_id = id;
 2605         sc->sc_bap_off = off;
 2606         return 0;
 2607 }
 2608 
 2609 STATIC int
 2610 wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
 2611 {
 2612         int error, cnt;
 2613 
 2614         if (buflen == 0)
 2615                 return 0;
 2616         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
 2617                 if ((error = wi_seek_bap(sc, id, off)) != 0)
 2618                         return error;
 2619         }
 2620         cnt = (buflen + 1) / 2;
 2621         CSR_READ_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
 2622         sc->sc_bap_off += cnt * 2;
 2623         return 0;
 2624 }
 2625 
 2626 STATIC int
 2627 wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
 2628 {
 2629         int error, cnt;
 2630 
 2631         if (buflen == 0)
 2632                 return 0;
 2633 
 2634 #ifdef WI_HERMES_AUTOINC_WAR
 2635   again:
 2636 #endif
 2637         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
 2638                 if ((error = wi_seek_bap(sc, id, off)) != 0)
 2639                         return error;
 2640         }
 2641         cnt = (buflen + 1) / 2;
 2642         CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
 2643         sc->sc_bap_off += cnt * 2;
 2644 
 2645 #ifdef WI_HERMES_AUTOINC_WAR
 2646         /*
 2647          * According to the comments in the HCF Light code, there is a bug
 2648          * in the Hermes (or possibly in certain Hermes firmware revisions)
 2649          * where the chip's internal autoincrement counter gets thrown off
 2650          * during data writes:  the autoincrement is missed, causing one
 2651          * data word to be overwritten and subsequent words to be written to
 2652          * the wrong memory locations. The end result is that we could end
 2653          * up transmitting bogus frames without realizing it. The workaround
 2654          * for this is to write a couple of extra guard words after the end
 2655          * of the transfer, then attempt to read then back. If we fail to
 2656          * locate the guard words where we expect them, we preform the
 2657          * transfer over again.
 2658          */
 2659         if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
 2660                 CSR_WRITE_2(sc, WI_DATA0, 0x1234);
 2661                 CSR_WRITE_2(sc, WI_DATA0, 0x5678);
 2662                 wi_seek_bap(sc, id, sc->sc_bap_off);
 2663                 sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */
 2664                 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
 2665                     CSR_READ_2(sc, WI_DATA0) != 0x5678) {
 2666                         printf("%s: detect auto increment bug, try again\n",
 2667                             sc->sc_dev.dv_xname);
 2668                         goto again;
 2669                 }
 2670         }
 2671 #endif
 2672         return 0;
 2673 }
 2674 
 2675 STATIC int
 2676 wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
 2677 {
 2678         int error, len;
 2679         struct mbuf *m;
 2680 
 2681         for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
 2682                 if (m->m_len == 0)
 2683                         continue;
 2684 
 2685                 len = min(m->m_len, totlen);
 2686 
 2687                 if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
 2688                         m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
 2689                         return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
 2690                             totlen);
 2691                 }
 2692 
 2693                 if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
 2694                         return error;
 2695 
 2696                 off += m->m_len;
 2697                 totlen -= len;
 2698         }
 2699         return 0;
 2700 }
 2701 
 2702 STATIC int
 2703 wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
 2704 {
 2705         int i;
 2706 
 2707         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
 2708                 printf("%s: failed to allocate %d bytes on NIC\n",
 2709                     sc->sc_dev.dv_xname, len);
 2710                 return ENOMEM;
 2711         }
 2712 
 2713         for (i = 0; i < WI_TIMEOUT; i++) {
 2714                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
 2715                         break;
 2716                 if (i == WI_TIMEOUT) {
 2717                         printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
 2718                         return ETIMEDOUT;
 2719                 }
 2720                 DELAY(1);
 2721         }
 2722         *idp = CSR_READ_2(sc, WI_ALLOC_FID);
 2723         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 2724         return 0;
 2725 }
 2726 
 2727 STATIC int
 2728 wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
 2729 {
 2730         int error, len;
 2731         u_int16_t ltbuf[2];
 2732 
 2733         /* Tell the NIC to enter record read mode. */
 2734         error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
 2735         if (error)
 2736                 return error;
 2737 
 2738         error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
 2739         if (error)
 2740                 return error;
 2741 
 2742         if (le16toh(ltbuf[1]) != rid) {
 2743                 printf("%s: record read mismatch, rid=%x, got=%x\n",
 2744                     sc->sc_dev.dv_xname, rid, le16toh(ltbuf[1]));
 2745                 return EIO;
 2746         }
 2747         len = max(0, le16toh(ltbuf[0]) - 1) * 2;         /* already got rid */
 2748         if (*buflenp < len) {
 2749                 printf("%s: record buffer is too small, "
 2750                     "rid=%x, size=%d, len=%d\n",
 2751                     sc->sc_dev.dv_xname, rid, *buflenp, len);
 2752                 return ENOSPC;
 2753         }
 2754         *buflenp = len;
 2755         return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
 2756 }
 2757 
 2758 STATIC int
 2759 wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
 2760 {
 2761         int error;
 2762         u_int16_t ltbuf[2];
 2763 
 2764         ltbuf[0] = htole16((buflen + 1) / 2 + 1);        /* includes rid */
 2765         ltbuf[1] = htole16(rid);
 2766 
 2767         error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
 2768         if (error)
 2769                 return error;
 2770         error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
 2771         if (error)
 2772                 return error;
 2773 
 2774         return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
 2775 }
 2776 
 2777 STATIC void
 2778 wi_rssadapt_updatestats_cb(void *arg, struct ieee80211_node *ni)
 2779 {
 2780         struct wi_node *wn = (void*)ni;
 2781         ieee80211_rssadapt_updatestats(&wn->wn_rssadapt);
 2782 }
 2783 
 2784 STATIC void
 2785 wi_rssadapt_updatestats(void *arg)
 2786 {
 2787         struct wi_softc *sc = arg;
 2788         struct ieee80211com *ic = &sc->sc_ic;
 2789         ieee80211_iterate_nodes(ic, wi_rssadapt_updatestats_cb, arg);
 2790         if (ic->ic_opmode != IEEE80211_M_MONITOR &&
 2791             ic->ic_state == IEEE80211_S_RUN)
 2792                 callout_reset(&sc->sc_rssadapt_ch, hz / 10,
 2793                     wi_rssadapt_updatestats, arg);
 2794 }
 2795 
 2796 STATIC int
 2797 wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 2798 {
 2799         struct ifnet *ifp = &ic->ic_if;
 2800         struct wi_softc *sc = ic->ic_softc;
 2801         struct ieee80211_node *ni = ic->ic_bss;
 2802         int buflen, linkstate = LINK_STATE_DOWN, s;
 2803         u_int16_t val;
 2804         struct wi_ssid ssid;
 2805         struct wi_macaddr bssid, old_bssid;
 2806         enum ieee80211_state ostate;
 2807 #ifdef WI_DEBUG
 2808         static const char *stname[] =
 2809             { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
 2810 #endif /* WI_DEBUG */
 2811 
 2812         ostate = ic->ic_state;
 2813         DPRINTF(("wi_newstate: %s -> %s\n", stname[ostate], stname[nstate]));
 2814 
 2815         switch (nstate) {
 2816         case IEEE80211_S_INIT:
 2817                 if (ic->ic_opmode != IEEE80211_M_MONITOR)
 2818                         callout_stop(&sc->sc_rssadapt_ch);
 2819                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
 2820                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 2821                 return (*sc->sc_newstate)(ic, nstate, arg);
 2822 
 2823         case IEEE80211_S_RUN:
 2824                 linkstate = LINK_STATE_UP;
 2825                 sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
 2826                 buflen = IEEE80211_ADDR_LEN;
 2827                 IEEE80211_ADDR_COPY(old_bssid.wi_mac_addr, ni->ni_bssid);
 2828                 wi_read_rid(sc, WI_RID_CURRENT_BSSID, &bssid, &buflen);
 2829                 IEEE80211_ADDR_COPY(ni->ni_bssid, &bssid);
 2830                 IEEE80211_ADDR_COPY(ni->ni_macaddr, &bssid);
 2831                 buflen = sizeof(val);
 2832                 wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
 2833                 if (!isset(ic->ic_chan_avail, le16toh(val)))
 2834                         panic("%s: invalid channel %d\n", sc->sc_dev.dv_xname,
 2835                             le16toh(val));
 2836                 ni->ni_chan = &ic->ic_channels[le16toh(val)];
 2837 
 2838                 if (IEEE80211_ADDR_EQ(old_bssid.wi_mac_addr, ni->ni_bssid))
 2839                         sc->sc_false_syns++;
 2840                 else
 2841                         sc->sc_false_syns = 0;
 2842 
 2843                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
 2844                         ni->ni_esslen = ic->ic_des_esslen;
 2845                         memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
 2846                         ni->ni_rates = ic->ic_sup_rates[
 2847                             ieee80211_chan2mode(ic, ni->ni_chan)];
 2848                         ni->ni_intval = ic->ic_lintval;
 2849                         ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
 2850                         if (ic->ic_flags & IEEE80211_F_WEPON)
 2851                                 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
 2852                 } else {
 2853                         buflen = sizeof(ssid);
 2854                         wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
 2855                         ni->ni_esslen = le16toh(ssid.wi_len);
 2856                         if (ni->ni_esslen > IEEE80211_NWID_LEN)
 2857                                 ni->ni_esslen = IEEE80211_NWID_LEN;     /*XXX*/
 2858                         memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
 2859                         ni->ni_rates = ic->ic_sup_rates[
 2860                             ieee80211_chan2mode(ic, ni->ni_chan)]; /*XXX*/
 2861                 }
 2862                 if (ic->ic_opmode != IEEE80211_M_MONITOR)
 2863                         callout_reset(&sc->sc_rssadapt_ch, hz / 10,
 2864                             wi_rssadapt_updatestats, sc);
 2865                 break;
 2866 
 2867         case IEEE80211_S_SCAN:
 2868         case IEEE80211_S_AUTH:
 2869         case IEEE80211_S_ASSOC:
 2870                 break;
 2871         }
 2872 
 2873         if (ifp->if_link_state != linkstate) {
 2874                 ifp->if_link_state = linkstate;
 2875                 s = splnet();
 2876                 rt_ifmsg(ifp);
 2877                 splx(s);
 2878         }
 2879         ic->ic_state = nstate;
 2880         /* skip standard ieee80211 handling */
 2881         return 0;
 2882 }
 2883 
 2884 STATIC int
 2885 wi_set_tim(struct ieee80211com *ic, int aid, int which)
 2886 {
 2887         struct wi_softc *sc = ic->ic_softc;
 2888 
 2889         aid &= ~0xc000;
 2890         if (which)
 2891                 aid |= 0x8000;
 2892 
 2893         return wi_write_val(sc, WI_RID_SET_TIM, aid);
 2894 }
 2895 
 2896 STATIC int
 2897 wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
 2898 {
 2899         int error = 0;
 2900         u_int16_t val[2];
 2901 
 2902         if (!sc->sc_enabled)
 2903                 return ENXIO;
 2904         switch (sc->sc_firmware_type) {
 2905         case WI_LUCENT:
 2906                 (void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 2907                 break;
 2908         case WI_INTERSIL:
 2909                 val[0] = htole16(chanmask);     /* channel */
 2910                 val[1] = htole16(txrate);       /* tx rate */
 2911                 error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
 2912                 break;
 2913         case WI_SYMBOL:
 2914                 /*
 2915                  * XXX only supported on 3.x ?
 2916                  */
 2917                 val[0] = BSCAN_BCAST | BSCAN_ONETIME;
 2918                 error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
 2919                     val, sizeof(val[0]));
 2920                 break;
 2921         }
 2922         if (error == 0) {
 2923                 sc->sc_scan_timer = WI_SCAN_WAIT;
 2924                 sc->sc_ic.ic_if.if_timer = 1;
 2925                 DPRINTF(("wi_scan_ap: start scanning, "
 2926                         "chanmask 0x%x txrate 0x%x\n", chanmask, txrate));
 2927         }
 2928         return error;
 2929 }
 2930 
 2931 STATIC void
 2932 wi_scan_result(struct wi_softc *sc, int fid, int cnt)
 2933 {
 2934 #define N(a)    (sizeof (a) / sizeof (a[0]))
 2935         int i, naps, off, szbuf;
 2936         struct wi_scan_header ws_hdr;   /* Prism2 header */
 2937         struct wi_scan_data_p2 ws_dat;  /* Prism2 scantable*/
 2938         struct wi_apinfo *ap;
 2939 
 2940         off = sizeof(u_int16_t) * 2;
 2941         memset(&ws_hdr, 0, sizeof(ws_hdr));
 2942         switch (sc->sc_firmware_type) {
 2943         case WI_INTERSIL:
 2944                 wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
 2945                 off += sizeof(ws_hdr);
 2946                 szbuf = sizeof(struct wi_scan_data_p2);
 2947                 break;
 2948         case WI_SYMBOL:
 2949                 szbuf = sizeof(struct wi_scan_data_p2) + 6;
 2950                 break;
 2951         case WI_LUCENT:
 2952                 szbuf = sizeof(struct wi_scan_data);
 2953                 break;
 2954         default:
 2955                 printf("%s: wi_scan_result: unknown firmware type %u\n",
 2956                     sc->sc_dev.dv_xname, sc->sc_firmware_type);
 2957                 naps = 0;
 2958                 goto done;
 2959         }
 2960         naps = (cnt * 2 + 2 - off) / szbuf;
 2961         if (naps > N(sc->sc_aps))
 2962                 naps = N(sc->sc_aps);
 2963         sc->sc_naps = naps;
 2964         /* Read Data */
 2965         ap = sc->sc_aps;
 2966         memset(&ws_dat, 0, sizeof(ws_dat));
 2967         for (i = 0; i < naps; i++, ap++) {
 2968                 wi_read_bap(sc, fid, off, &ws_dat,
 2969                     (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
 2970                 DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
 2971                     ether_sprintf(ws_dat.wi_bssid)));
 2972                 off += szbuf;
 2973                 ap->scanreason = le16toh(ws_hdr.wi_reason);
 2974                 memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
 2975                 ap->channel = le16toh(ws_dat.wi_chid);
 2976                 ap->signal  = le16toh(ws_dat.wi_signal);
 2977                 ap->noise   = le16toh(ws_dat.wi_noise);
 2978                 ap->quality = ap->signal - ap->noise;
 2979                 ap->capinfo = le16toh(ws_dat.wi_capinfo);
 2980                 ap->interval = le16toh(ws_dat.wi_interval);
 2981                 ap->rate    = le16toh(ws_dat.wi_rate);
 2982                 ap->namelen = le16toh(ws_dat.wi_namelen);
 2983                 if (ap->namelen > sizeof(ap->name))
 2984                         ap->namelen = sizeof(ap->name);
 2985                 memcpy(ap->name, ws_dat.wi_name, ap->namelen);
 2986         }
 2987 done:
 2988         /* Done scanning */
 2989         sc->sc_scan_timer = 0;
 2990         DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
 2991 #undef N
 2992 }
 2993 
 2994 STATIC void
 2995 wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
 2996 {
 2997         ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
 2998             ni  ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL
 2999                 : -1,
 3000             rssi);
 3001         printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
 3002                 le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
 3003                 le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
 3004         printf(" rx_signal %u rx_rate %u rx_flow %u\n",
 3005                 wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
 3006         printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
 3007                 wh->wi_tx_rtry, wh->wi_tx_rate,
 3008                 le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
 3009         printf(" ehdr dst %s src %s type 0x%x\n",
 3010                 ether_sprintf(wh->wi_ehdr.ether_dhost),
 3011                 ether_sprintf(wh->wi_ehdr.ether_shost),
 3012                 wh->wi_ehdr.ether_type);
 3013 }

Cache object: b10189523fc11437ef37f87fb1680263


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