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


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

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

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

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

Cache object: 870000e0b8d27c8a19c771776a1f47b5


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