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

Cache object: 88434a4b821f6843c4c60ed46b561685


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