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

Cache object: f87f6be1ff1a60490f5416ecb0146834


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