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


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

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

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

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

Cache object: 0cb6a60661d43e4ffd957b8b849d82de


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