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

Cache object: 4f1c9004cec4d508a36ae509ef4e5a90


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