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


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

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

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

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

Cache object: 83a09c999e110d7e515f7ccb4526afa7


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