[ 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  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

    1 /*
    2  * Copyright (c) 1997, 1998, 1999
    3  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Bill Paul.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD.
   35  *
   36  * Written by Bill Paul <wpaul@ctr.columbia.edu>
   37  * Electrical Engineering Department
   38  * Columbia University, New York City
   39  */
   40 
   41 /*
   42  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
   43  * from Lucent. Unlike the older cards, the new ones are programmed
   44  * entirely via a firmware-driven controller called the Hermes.
   45  * Unfortunately, Lucent will not release the Hermes programming manual
   46  * without an NDA (if at all). What they do release is an API library
   47  * called the HCF (Hardware Control Functions) which is supposed to
   48  * do the device-specific operations of a device driver for you. The
   49  * publically available version of the HCF library (the 'HCF Light') is 
   50  * a) extremely gross, b) lacks certain features, particularly support
   51  * for 802.11 frames, and c) is contaminated by the GNU Public License.
   52  *
   53  * This driver does not use the HCF or HCF Light at all. Instead, it
   54  * programs the Hermes controller directly, using information gleaned
   55  * from the HCF Light code and corresponding documentation.
   56  *
   57  * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
   58  * WaveLan cards (based on the Hermes chipset), as well as the newer
   59  * Prism 2 chipsets with firmware from Intersil and Symbol.
   60  */
   61 
   62 #include <sys/param.h>
   63 #include <sys/systm.h>
   64 #if __FreeBSD_version >= 500033
   65 #include <sys/endian.h>
   66 #endif
   67 #include <sys/sockio.h>
   68 #include <sys/mbuf.h>
   69 #include <sys/proc.h>
   70 #include <sys/kernel.h>
   71 #include <sys/socket.h>
   72 #include <sys/module.h>
   73 #include <sys/bus.h>
   74 #include <sys/random.h>
   75 #include <sys/syslog.h>
   76 #include <sys/sysctl.h>
   77 
   78 #include <machine/bus.h>
   79 #include <machine/resource.h>
   80 #include <machine/clock.h>
   81 #include <sys/rman.h>
   82 
   83 #include <net/if.h>
   84 #include <net/if_arp.h>
   85 #include <net/ethernet.h>
   86 #include <net/if_dl.h>
   87 #include <net/if_media.h>
   88 #include <net/if_types.h>
   89 #include <net/if_ieee80211.h>
   90 
   91 #include <netinet/in.h>
   92 #include <netinet/in_systm.h>
   93 #include <netinet/in_var.h>
   94 #include <netinet/ip.h>
   95 #include <netinet/if_ether.h>
   96 
   97 #include <net/bpf.h>
   98 
   99 #include <dev/wi/if_wavelan_ieee.h>
  100 #include <dev/wi/wi_hostap.h>
  101 #include <dev/wi/if_wivar.h>
  102 #include <dev/wi/if_wireg.h>
  103 
  104 #if !defined(lint)
  105 static const char rcsid[] =
  106   "$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.103.2.6 2004/05/18 06:57:33 imp Exp $";
  107 #endif
  108 
  109 static void wi_intr(void *);
  110 static void wi_reset(struct wi_softc *);
  111 static int wi_ioctl(struct ifnet *, u_long, caddr_t);
  112 static void wi_init(void *);
  113 static void wi_start(struct ifnet *);
  114 static void wi_watchdog(struct ifnet *);
  115 static void wi_rxeof(struct wi_softc *);
  116 static void wi_txeof(struct wi_softc *, int);
  117 static void wi_update_stats(struct wi_softc *);
  118 static void wi_setmulti(struct wi_softc *);
  119 
  120 static int wi_cmd(struct wi_softc *, int, int, int, int);
  121 static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);
  122 static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *);
  123 static int wi_read_data(struct wi_softc *, int, int, caddr_t, int);
  124 static int wi_write_data(struct wi_softc *, int, int, caddr_t, int);
  125 static int wi_seek(struct wi_softc *, int, int, int);
  126 static int wi_alloc_nicmem(struct wi_softc *, int, int *);
  127 static void wi_inquire(void *);
  128 static void wi_setdef(struct wi_softc *, struct wi_req *);
  129 
  130 #ifdef WICACHE
  131 static
  132 void wi_cache_store(struct wi_softc *, struct ether_header *,
  133         struct mbuf *, unsigned short);
  134 #endif
  135 
  136 static int wi_get_cur_ssid(struct wi_softc *, char *, int *);
  137 static void wi_get_id(struct wi_softc *);
  138 static int wi_media_change(struct ifnet *);
  139 static void wi_media_status(struct ifnet *, struct ifmediareq *);
  140 
  141 static int wi_get_debug(struct wi_softc *, struct wi_req *);
  142 static int wi_set_debug(struct wi_softc *, struct wi_req *);
  143 
  144 devclass_t wi_devclass;
  145 
  146 struct wi_card_ident wi_card_ident[] = {
  147         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
  148         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
  149         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
  150         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
  151         { WI_NIC_EVB2_ID,               WI_NIC_EVB2_STR,        WI_INTERSIL },
  152         { WI_NIC_HWB3763_ID,            WI_NIC_HWB3763_STR,     WI_INTERSIL },
  153         { WI_NIC_HWB3163_ID,            WI_NIC_HWB3163_STR,     WI_INTERSIL },
  154         { WI_NIC_HWB3163B_ID,           WI_NIC_HWB3163B_STR,    WI_INTERSIL },
  155         { WI_NIC_EVB3_ID,               WI_NIC_EVB3_STR,        WI_INTERSIL },
  156         { WI_NIC_HWB1153_ID,            WI_NIC_HWB1153_STR,     WI_INTERSIL },
  157         { WI_NIC_P2_SST_ID,             WI_NIC_P2_SST_STR,      WI_INTERSIL },
  158         { WI_NIC_EVB2_SST_ID,           WI_NIC_EVB2_SST_STR,    WI_INTERSIL },
  159         { WI_NIC_3842_EVA_ID,           WI_NIC_3842_EVA_STR,    WI_INTERSIL },
  160         { WI_NIC_3842_PCMCIA_AMD_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  161         { WI_NIC_3842_PCMCIA_SST_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  162         { WI_NIC_3842_PCMCIA_ATM_ID,    WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
  163         { WI_NIC_3842_MINI_AMD_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  164         { WI_NIC_3842_MINI_SST_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  165         { WI_NIC_3842_MINI_ATM_ID,      WI_NIC_3842_MINI_STR,   WI_INTERSIL },
  166         { WI_NIC_3842_PCI_AMD_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  167         { WI_NIC_3842_PCI_SST_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  168         { WI_NIC_3842_PCI_ATM_ID,       WI_NIC_3842_PCI_STR,    WI_INTERSIL },
  169         { WI_NIC_P3_PCMCIA_AMD_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  170         { WI_NIC_P3_PCMCIA_SST_ID,      WI_NIC_P3_PCMCIA_STR,   WI_INTERSIL },
  171         { WI_NIC_P3_MINI_AMD_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  172         { WI_NIC_P3_MINI_SST_ID,        WI_NIC_P3_MINI_STR,     WI_INTERSIL },
  173         { 0,    NULL,   0 },
  174 };
  175 
  176 int
  177 wi_generic_detach(dev)
  178         device_t                dev;
  179 {
  180         struct wi_softc         *sc;
  181         struct ifnet            *ifp;
  182         int                     s;
  183 
  184         sc = device_get_softc(dev);
  185         WI_LOCK(sc, s);
  186         ifp = &sc->arpcom.ac_if;
  187 
  188         if (sc->wi_gone) {
  189                 device_printf(dev, "already unloaded\n");
  190                 WI_UNLOCK(sc, s);
  191                 return(ENODEV);
  192         }
  193 
  194         wi_stop(sc);
  195 
  196         /* Delete all remaining media. */
  197         ifmedia_removeall(&sc->ifmedia);
  198 
  199         ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
  200         wi_free(dev);
  201         sc->wi_gone = 1;
  202 
  203         WI_UNLOCK(sc, s);
  204 #if __FreeBSD_version >= 500000
  205         mtx_destroy(&sc->wi_mtx);
  206 #endif
  207 
  208         return(0);
  209 }
  210 
  211 int
  212 wi_generic_attach(device_t dev)
  213 {
  214         struct wi_softc         *sc;
  215         struct wi_ltv_macaddr   mac;
  216         struct wi_ltv_gen       gen;
  217         struct ifnet            *ifp;
  218         int                     error;
  219         int                     s;
  220 
  221         /* XXX maybe we need the splimp stuff here XXX */
  222         sc = device_get_softc(dev);
  223         ifp = &sc->arpcom.ac_if;
  224 
  225         error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
  226             wi_intr, sc, &sc->wi_intrhand);
  227 
  228         if (error) {
  229                 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
  230                 wi_free(dev);
  231                 return (error);
  232         }
  233 
  234 #if __FreeBSD_version >= 500000
  235         mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  236             MTX_DEF | MTX_RECURSE);
  237 #endif
  238         WI_LOCK(sc, s);
  239 
  240         /* Reset the NIC. */
  241         wi_reset(sc);
  242 
  243         /*
  244          * Read the station address.
  245          * And do it twice. I've seen PRISM-based cards that return
  246          * an error when trying to read it the first time, which causes
  247          * the probe to fail.
  248          */
  249         mac.wi_type = WI_RID_MAC_NODE;
  250         mac.wi_len = 4;
  251         wi_read_record(sc, (struct wi_ltv_gen *)&mac);
  252         if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) {
  253                 device_printf(dev, "mac read failed %d\n", error);
  254                 wi_free(dev);
  255                 return (error);
  256         }
  257         bcopy((char *)&mac.wi_mac_addr,
  258            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  259 
  260         device_printf(dev, "802.11 address: %6D\n", sc->arpcom.ac_enaddr, ":");
  261 
  262         wi_get_id(sc);
  263 
  264         ifp->if_softc = sc;
  265         ifp->if_unit = sc->wi_unit;
  266         ifp->if_name = "wi";
  267         ifp->if_mtu = ETHERMTU;
  268         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  269         ifp->if_ioctl = wi_ioctl;
  270         ifp->if_output = ether_output;
  271         ifp->if_start = wi_start;
  272         ifp->if_watchdog = wi_watchdog;
  273         ifp->if_init = wi_init;
  274         ifp->if_baudrate = 10000000;
  275         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  276 
  277         bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
  278         bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
  279             sizeof(WI_DEFAULT_NODENAME) - 1);
  280 
  281         bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
  282         bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
  283             sizeof(WI_DEFAULT_NETNAME) - 1);
  284 
  285         bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
  286         bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
  287             sizeof(WI_DEFAULT_IBSS) - 1);
  288 
  289         sc->wi_portnum = WI_DEFAULT_PORT;
  290         sc->wi_ptype = WI_PORTTYPE_BSS;
  291         sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
  292         sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
  293         sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
  294         sc->wi_max_data_len = WI_DEFAULT_DATALEN;
  295         sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
  296         sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
  297         sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
  298         sc->wi_roaming = WI_DEFAULT_ROAMING;
  299         sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
  300         sc->wi_authmode = IEEE80211_AUTH_OPEN;
  301 
  302         /*
  303          * Read the default channel from the NIC. This may vary
  304          * depending on the country where the NIC was purchased, so
  305          * we can't hard-code a default and expect it to work for
  306          * everyone.
  307          */
  308         gen.wi_type = WI_RID_OWN_CHNL;
  309         gen.wi_len = 2;
  310         wi_read_record(sc, &gen);
  311         sc->wi_channel = gen.wi_val;
  312 
  313         /*
  314          * Set flags based on firmware version.
  315          */
  316         switch (sc->sc_firmware_type) {
  317         case WI_LUCENT:
  318                 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
  319                 if (sc->sc_sta_firmware_ver >= 60000)
  320                         sc->wi_flags |= WI_FLAGS_HAS_MOR;
  321                 if (sc->sc_sta_firmware_ver >= 60006) {
  322                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
  323                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
  324                 }
  325                 sc->wi_ibss_port = htole16(1);
  326                 break;
  327         case WI_INTERSIL:
  328                 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
  329                 if (sc->sc_sta_firmware_ver >= 800) {
  330                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
  331                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
  332                 }
  333                 /*
  334                  * version 0.8.3 and newer are the only ones that are known
  335                  * to currently work.  Earlier versions can be made to work,
  336                  * at least according to the Linux driver.
  337                  */
  338                 if (sc->sc_sta_firmware_ver >= 803)
  339                         sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
  340                 sc->wi_ibss_port = htole16(0);
  341                 break;
  342         case WI_SYMBOL:
  343                 sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
  344                 if (sc->sc_sta_firmware_ver >= 20000)
  345                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
  346                 /* Older Symbol firmware does not support IBSS creation. */
  347                 if (sc->sc_sta_firmware_ver >= 25000)
  348                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
  349                 sc->wi_ibss_port = htole16(4);
  350                 break;
  351         }
  352 
  353         /*
  354          * Find out if we support WEP on this card.
  355          */
  356         gen.wi_type = WI_RID_WEP_AVAIL;
  357         gen.wi_len = 2;
  358         wi_read_record(sc, &gen);
  359         sc->wi_has_wep = gen.wi_val;
  360 
  361         if (bootverbose)
  362                 device_printf(sc->dev, "wi_has_wep = %d\n", sc->wi_has_wep);
  363 
  364         /* 
  365          * Find supported rates.
  366          */
  367         gen.wi_type = WI_RID_DATA_RATES;
  368         gen.wi_len = 2;
  369         if (wi_read_record(sc, &gen))
  370                 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
  371                     WI_SUPPRATES_5M | WI_SUPPRATES_11M;
  372         else
  373                 sc->wi_supprates = gen.wi_val;
  374 
  375         bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
  376 
  377         wi_init(sc);
  378         wi_stop(sc);
  379 
  380         ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);
  381 #define ADD(m, c)       ifmedia_add(&sc->ifmedia, (m), (c), NULL)
  382         if (sc->wi_supprates & WI_SUPPRATES_1M) {
  383                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
  384                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  385                     IFM_IEEE80211_ADHOC, 0), 0);
  386                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  387                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  388                             IFM_IEEE80211_IBSS, 0), 0);
  389                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  390                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  391                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  392                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
  393                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  394                             IFM_IEEE80211_HOSTAP, 0), 0);
  395         }
  396         if (sc->wi_supprates & WI_SUPPRATES_2M) {
  397                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
  398                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  399                     IFM_IEEE80211_ADHOC, 0), 0);
  400                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  401                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  402                             IFM_IEEE80211_IBSS, 0), 0);
  403                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  404                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  405                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  406                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
  407                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  408                             IFM_IEEE80211_HOSTAP, 0), 0);
  409         }
  410         if (sc->wi_supprates & WI_SUPPRATES_5M) {
  411                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
  412                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  413                     IFM_IEEE80211_ADHOC, 0), 0);
  414                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  415                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  416                             IFM_IEEE80211_IBSS, 0), 0);
  417                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  418                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  419                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  420                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
  421                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  422                             IFM_IEEE80211_HOSTAP, 0), 0);
  423         }
  424         if (sc->wi_supprates & WI_SUPPRATES_11M) {
  425                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
  426                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  427                     IFM_IEEE80211_ADHOC, 0), 0);
  428                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  429                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  430                             IFM_IEEE80211_IBSS, 0), 0);
  431                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  432                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  433                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  434                 if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
  435                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  436                             IFM_IEEE80211_HOSTAP, 0), 0);
  437                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
  438         }
  439         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
  440         if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  441                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
  442                     0), 0);
  443         if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  444                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
  445                     IFM_IEEE80211_IBSSMASTER, 0), 0);
  446         if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
  447                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
  448                     IFM_IEEE80211_HOSTAP, 0), 0);
  449         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
  450 #undef ADD
  451         ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
  452 
  453         /*
  454          * Call MI attach routine.
  455          */
  456         ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
  457         callout_handle_init(&sc->wi_stat_ch);
  458         WI_UNLOCK(sc, s);
  459 
  460         return(0);
  461 }
  462 
  463 static void
  464 wi_get_id(sc)
  465         struct wi_softc *sc;
  466 {
  467         struct wi_ltv_ver       ver;
  468         struct wi_card_ident    *id;
  469 
  470         /* getting chip identity */
  471         memset(&ver, 0, sizeof(ver));
  472         ver.wi_type = WI_RID_CARD_ID;
  473         ver.wi_len = 5;
  474         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
  475         device_printf(sc->dev, "using ");
  476         sc->sc_firmware_type = WI_NOTYPE;
  477         for (id = wi_card_ident; id->card_name != NULL; id++) {
  478                 if (le16toh(ver.wi_ver[0]) == id->card_id) {
  479                         printf("%s", id->card_name);
  480                         sc->sc_firmware_type = id->firm_type;
  481                         break;
  482                 }
  483         }
  484         if (sc->sc_firmware_type == WI_NOTYPE) {
  485                 if (le16toh(ver.wi_ver[0]) & 0x8000) {
  486                         printf("Unknown PRISM2 chip");
  487                         sc->sc_firmware_type = WI_INTERSIL;
  488                 } else {
  489                         printf("Unknown Lucent chip");
  490                         sc->sc_firmware_type = WI_LUCENT;
  491                 }
  492         }
  493 
  494         if (sc->sc_firmware_type != WI_LUCENT) {
  495                 /* get primary firmware version */
  496                 memset(&ver, 0, sizeof(ver));
  497                 ver.wi_type = WI_RID_PRI_IDENTITY;
  498                 ver.wi_len = 5;
  499                 wi_read_record(sc, (struct wi_ltv_gen *)&ver);
  500                 ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
  501                 ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
  502                 ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
  503                 sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
  504                     ver.wi_ver[3] * 100 + ver.wi_ver[1];
  505         }
  506 
  507         /* get station firmware version */
  508         memset(&ver, 0, sizeof(ver));
  509         ver.wi_type = WI_RID_STA_IDENTITY;
  510         ver.wi_len = 5;
  511         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
  512         ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
  513         ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
  514         ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
  515         sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
  516             ver.wi_ver[3] * 100 + ver.wi_ver[1];
  517         if (sc->sc_firmware_type == WI_INTERSIL &&
  518             (sc->sc_sta_firmware_ver == 10102 || 
  519              sc->sc_sta_firmware_ver == 20102)) {
  520                 struct wi_ltv_str sver;
  521                 char *p;
  522 
  523                 memset(&sver, 0, sizeof(sver));
  524                 sver.wi_type = WI_RID_SYMBOL_IDENTITY;
  525                 sver.wi_len = 7;
  526                 /* value should be the format like "V2.00-11" */
  527                 if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
  528                     *(p = (char *)sver.wi_str) >= 'A' &&
  529                     p[2] == '.' && p[5] == '-' && p[8] == '\0') {
  530                         sc->sc_firmware_type = WI_SYMBOL;
  531                         sc->sc_sta_firmware_ver = (p[1] - '') * 10000 +
  532                             (p[3] - '') * 1000 + (p[4] - '') * 100 +
  533                             (p[6] - '') * 10 + (p[7] - '');
  534                 }
  535         }
  536         printf("\n");
  537         device_printf(sc->dev, "%s Firmware: ",
  538              sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
  539             (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
  540 
  541         /*
  542          * The primary firmware is only valid on Prism based chipsets
  543          * (INTERSIL or SYMBOL).
  544          */
  545         if (sc->sc_firmware_type != WI_LUCENT)
  546             printf("Primary %u.%02u.%02u, ", sc->sc_pri_firmware_ver / 10000,
  547                     (sc->sc_pri_firmware_ver % 10000) / 100,
  548                     sc->sc_pri_firmware_ver % 100);
  549         printf("Station %u.%02u.%02u\n",
  550             sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
  551             sc->sc_sta_firmware_ver % 100);
  552         return;
  553 }
  554 
  555 static void
  556 wi_rxeof(sc)
  557         struct wi_softc         *sc;
  558 {
  559         struct ifnet            *ifp;
  560         struct ether_header     *eh;
  561         struct mbuf             *m;
  562         int                     id;
  563 
  564         ifp = &sc->arpcom.ac_if;
  565 
  566         id = CSR_READ_2(sc, WI_RX_FID);
  567 
  568         /*
  569          * if we have the procframe flag set, disregard all this and just
  570          * read the data from the device.
  571          */
  572         if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
  573                 struct wi_frame         *rx_frame;
  574                 int                     datlen, hdrlen;
  575 
  576                 /* first allocate mbuf for packet storage */
  577                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  578                 if (m == NULL) {
  579                         ifp->if_ierrors++;
  580                         return;
  581                 }
  582                 MCLGET(m, M_DONTWAIT);
  583                 if (!(m->m_flags & M_EXT)) {
  584                         m_freem(m);
  585                         ifp->if_ierrors++;
  586                         return;
  587                 }
  588 
  589                 m->m_pkthdr.rcvif = ifp;
  590 
  591                 /* now read wi_frame first so we know how much data to read */
  592                 if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
  593                     sizeof(struct wi_frame))) {
  594                         m_freem(m);
  595                         ifp->if_ierrors++;
  596                         return;
  597                 }
  598 
  599                 rx_frame = mtod(m, struct wi_frame *);
  600 
  601                 switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
  602                 case 7:
  603                         switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) {
  604                         case WI_FTYPE_DATA:
  605                                 hdrlen = WI_DATA_HDRLEN;
  606                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  607                                 break;
  608                         case WI_FTYPE_MGMT:
  609                                 hdrlen = WI_MGMT_HDRLEN;
  610                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  611                                 break;
  612                         case WI_FTYPE_CTL:
  613                                 /*
  614                                  * prism2 cards don't pass control packets
  615                                  * down properly or consistently, so we'll only
  616                                  * pass down the header.
  617                                  */
  618                                 hdrlen = WI_CTL_HDRLEN;
  619                                 datlen = 0;
  620                                 break;
  621                         default:
  622                                 device_printf(sc->dev, "received packet of "
  623                                     "unknown type on port 7\n");
  624                                 m_freem(m);
  625                                 ifp->if_ierrors++;
  626                                 return;
  627                         }
  628                         break;
  629                 case 0:
  630                         hdrlen = WI_DATA_HDRLEN;
  631                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  632                         break;
  633                 default:
  634                         device_printf(sc->dev, "received packet on invalid "
  635                             "port (wi_status=0x%x)\n", rx_frame->wi_status);
  636                         m_freem(m);
  637                         ifp->if_ierrors++;
  638                         return;
  639                 }
  640 
  641                 if ((hdrlen + datlen + 2) > MCLBYTES) {
  642                         device_printf(sc->dev, "oversized packet received "
  643                             "(wi_dat_len=%d, wi_status=0x%x)\n",
  644                             datlen, rx_frame->wi_status);
  645                         m_freem(m);
  646                         ifp->if_ierrors++;
  647                         return;
  648                 }
  649 
  650                 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
  651                     datlen + 2)) {
  652                         m_freem(m);
  653                         ifp->if_ierrors++;
  654                         return;
  655                 }
  656 
  657                 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
  658 
  659                 ifp->if_ipackets++;
  660 
  661                 /* Handle BPF listeners. */
  662                 if (ifp->if_bpf)
  663                         bpf_mtap(ifp, m);
  664 
  665                 m_freem(m);
  666         } else {
  667                 struct wi_frame         rx_frame;
  668 
  669                 /* First read in the frame header */
  670                 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
  671                     sizeof(rx_frame))) {
  672                         ifp->if_ierrors++;
  673                         return;
  674                 }
  675 
  676                 if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
  677                         ifp->if_ierrors++;
  678                         return;
  679                 }
  680 
  681                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  682                 if (m == NULL) {
  683                         ifp->if_ierrors++;
  684                         return;
  685                 }
  686                 MCLGET(m, M_DONTWAIT);
  687                 if (!(m->m_flags & M_EXT)) {
  688                         m_freem(m);
  689                         ifp->if_ierrors++;
  690                         return;
  691                 }
  692 
  693                 eh = mtod(m, struct ether_header *);
  694                 m->m_pkthdr.rcvif = ifp;
  695 
  696                 if (rx_frame.wi_status == WI_STAT_MGMT &&
  697                     sc->wi_ptype == WI_PORTTYPE_AP) {
  698                         if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 2) >
  699                             MCLBYTES) {
  700                                 device_printf(sc->dev, "oversized mgmt packet "
  701                                     "received in hostap mode " 
  702                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
  703                                     rx_frame.wi_dat_len, rx_frame.wi_status);
  704                                 m_freem(m);
  705                                 ifp->if_ierrors++;
  706                                 return;
  707                         }
  708 
  709                         /* Put the whole header in there. */
  710                         bcopy(&rx_frame, mtod(m, void *),
  711                             sizeof(struct wi_frame));
  712                         if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW, 
  713                             mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
  714                             rx_frame.wi_dat_len + 2)) {
  715                                 m_freem(m);
  716                                 ifp->if_ierrors++;
  717                                 return;
  718                         }
  719                         m->m_pkthdr.len = m->m_len =
  720                             WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len;
  721                         /* XXX: consider giving packet to bhp? */
  722                         wihap_mgmt_input(sc, &rx_frame, m);
  723                         return;
  724                 }
  725 
  726                 if (rx_frame.wi_status == WI_STAT_1042 ||
  727                     rx_frame.wi_status == WI_STAT_TUNNEL ||
  728                     rx_frame.wi_status == WI_STAT_WMP_MSG) {
  729                         if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
  730                                 device_printf(sc->dev,
  731                                     "oversized packet received "
  732                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
  733                                     rx_frame.wi_dat_len, rx_frame.wi_status);
  734                                 m_freem(m);
  735                                 ifp->if_ierrors++;
  736                                 return;
  737                         }
  738                         m->m_pkthdr.len = m->m_len =
  739                             rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
  740 
  741 #if 0
  742                         bcopy((char *)&rx_frame.wi_addr1,
  743                             (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
  744                         if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {
  745                                 bcopy((char *)&rx_frame.wi_addr2,
  746                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  747                         } else {
  748                                 bcopy((char *)&rx_frame.wi_addr3,
  749                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  750                         }
  751 #else
  752                         bcopy((char *)&rx_frame.wi_dst_addr,
  753                                 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
  754                         bcopy((char *)&rx_frame.wi_src_addr,
  755                                 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  756 #endif
  757 
  758                         bcopy((char *)&rx_frame.wi_type,
  759                             (char *)&eh->ether_type, ETHER_TYPE_LEN);
  760 
  761                         if (wi_read_data(sc, id, WI_802_11_OFFSET,
  762                             mtod(m, caddr_t) + sizeof(struct ether_header),
  763                             m->m_len + 2)) {
  764                                 m_freem(m);
  765                                 ifp->if_ierrors++;
  766                                 return;
  767                         }
  768                 } else {
  769                         if((rx_frame.wi_dat_len +
  770                             sizeof(struct ether_header)) > MCLBYTES) {
  771                                 device_printf(sc->dev,
  772                                     "oversized packet received "
  773                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
  774                                     rx_frame.wi_dat_len, rx_frame.wi_status);
  775                                 m_freem(m);
  776                                 ifp->if_ierrors++;
  777                                 return;
  778                         }
  779                         m->m_pkthdr.len = m->m_len =
  780                             rx_frame.wi_dat_len + sizeof(struct ether_header);
  781 
  782                         if (wi_read_data(sc, id, WI_802_3_OFFSET,
  783                             mtod(m, caddr_t), m->m_len + 2)) {
  784                                 m_freem(m);
  785                                 ifp->if_ierrors++;
  786                                 return;
  787                         }
  788                 }
  789 
  790                 ifp->if_ipackets++;
  791 
  792                 if (sc->wi_ptype == WI_PORTTYPE_AP) {
  793                         /* 
  794                          * Give host AP code first crack at data
  795                          * packets.  If it decides to handle it (or
  796                          * drop it), it will return a non-zero.
  797                          * Otherwise, it is destined for this host.
  798                          */
  799                         if (wihap_data_input(sc, &rx_frame, m))
  800                                 return;
  801                 }
  802                 /* Receive packet. */
  803                 m_adj(m, sizeof(struct ether_header));
  804 #ifdef WICACHE
  805                 wi_cache_store(sc, eh, m, rx_frame.wi_q_info);
  806 #endif  
  807                 ether_input(ifp, eh, m);
  808         }
  809 }
  810 
  811 static void
  812 wi_txeof(sc, status)
  813         struct wi_softc         *sc;
  814         int                     status;
  815 {
  816         struct ifnet            *ifp;
  817 
  818         ifp = &sc->arpcom.ac_if;
  819 
  820         ifp->if_timer = 0;
  821         ifp->if_flags &= ~IFF_OACTIVE;
  822 
  823         if (status & WI_EV_TX_EXC)
  824                 ifp->if_oerrors++;
  825         else
  826                 ifp->if_opackets++;
  827 
  828         return;
  829 }
  830 
  831 void
  832 wi_inquire(xsc)
  833         void                    *xsc;
  834 {
  835         struct wi_softc         *sc;
  836         struct ifnet            *ifp;
  837         int                     s;
  838 
  839         sc = xsc;
  840         ifp = &sc->arpcom.ac_if;
  841 
  842         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
  843 
  844         /* Don't do this while we're transmitting */
  845         if (ifp->if_flags & IFF_OACTIVE)
  846                 return;
  847 
  848         WI_LOCK(sc, s);
  849         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
  850         WI_UNLOCK(sc, s);
  851 
  852         return;
  853 }
  854 
  855 void
  856 wi_update_stats(sc)
  857         struct wi_softc         *sc;
  858 {
  859         struct wi_ltv_gen       gen;
  860         u_int16_t               id;
  861         struct ifnet            *ifp;
  862         u_int32_t               *ptr;
  863         int                     len, i;
  864         u_int16_t               t;
  865 
  866         ifp = &sc->arpcom.ac_if;
  867 
  868         id = CSR_READ_2(sc, WI_INFO_FID);
  869 
  870         wi_read_data(sc, id, 0, (char *)&gen, 4);
  871 
  872         /*
  873          * if we just got our scan results, copy it over into the scan buffer
  874          * so we can return it to anyone that asks for it. (add a little
  875          * compatibility with the prism2 scanning mechanism)
  876          */
  877         if (gen.wi_type == WI_INFO_SCAN_RESULTS)
  878         {
  879                 sc->wi_scanbuf_len = gen.wi_len;
  880                 wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf,
  881                     sc->wi_scanbuf_len * 2);
  882 
  883                 return;
  884         }
  885         else if (gen.wi_type != WI_INFO_COUNTERS)
  886                 return;
  887 
  888         len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
  889                 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
  890         ptr = (u_int32_t *)&sc->wi_stats;
  891 
  892         for (i = 0; i < len - 1; i++) {
  893                 t = CSR_READ_2(sc, WI_DATA1);
  894 #ifdef WI_HERMES_STATS_WAR
  895                 if (t > 0xF000)
  896                         t = ~t & 0xFFFF;
  897 #endif
  898                 ptr[i] += t;
  899         }
  900 
  901         ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
  902             sc->wi_stats.wi_tx_multi_retries +
  903             sc->wi_stats.wi_tx_retry_limit;
  904 
  905         return;
  906 }
  907 
  908 static void
  909 wi_intr(xsc)
  910         void            *xsc;
  911 {
  912         struct wi_softc         *sc = xsc;
  913         struct ifnet            *ifp;
  914         u_int16_t               status;
  915         int                     s;
  916 
  917         WI_LOCK(sc, s);
  918 
  919         ifp = &sc->arpcom.ac_if;
  920 
  921         if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) {
  922                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
  923                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  924                 WI_UNLOCK(sc, s);
  925                 return;
  926         }
  927 
  928         /* Disable interrupts. */
  929         CSR_WRITE_2(sc, WI_INT_EN, 0);
  930 
  931         status = CSR_READ_2(sc, WI_EVENT_STAT);
  932         CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
  933 
  934         if (status & WI_EV_RX) {
  935                 wi_rxeof(sc);
  936                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
  937         }
  938 
  939         if (status & WI_EV_TX) {
  940                 wi_txeof(sc, status);
  941                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
  942         }
  943 
  944         if (status & WI_EV_ALLOC) {
  945                 int                     id;
  946 
  947                 id = CSR_READ_2(sc, WI_ALLOC_FID);
  948                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
  949                 if (id == sc->wi_tx_data_id)
  950                         wi_txeof(sc, status);
  951         }
  952 
  953         if (status & WI_EV_INFO) {
  954                 wi_update_stats(sc);
  955                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
  956         }
  957 
  958         if (status & WI_EV_TX_EXC) {
  959                 wi_txeof(sc, status);
  960                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
  961         }
  962 
  963         if (status & WI_EV_INFO_DROP) {
  964                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
  965         }
  966 
  967         /* Re-enable interrupts. */
  968         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  969 
  970         if (ifp->if_snd.ifq_head != NULL) {
  971                 wi_start(ifp);
  972         }
  973 
  974         WI_UNLOCK(sc, s);
  975 
  976         return;
  977 }
  978 
  979 static int
  980 wi_cmd(sc, cmd, val0, val1, val2)
  981         struct wi_softc         *sc;
  982         int                     cmd;
  983         int                     val0;
  984         int                     val1;
  985         int                     val2;
  986 {
  987         int                     i, s = 0;
  988         static volatile int count  = 0;
  989         int                     tmo = WI_TIMEOUT;
  990         
  991         if (count > 1)
  992                 panic("Hey partner, hold on there!");
  993         count++;
  994 
  995         /* wait for the busy bit to clear */
  996         for (i = 500; i > 0; i--) {     /* 5s */
  997                 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
  998                         break;
  999                 }
 1000                 DELAY(10*1000); /* 10 m sec */
 1001         }
 1002         if (i == 0) {
 1003                 device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" );
 1004                 count--;
 1005                 return(ETIMEDOUT);
 1006         }
 1007 
 1008         CSR_WRITE_2(sc, WI_PARAM0, val0);
 1009         CSR_WRITE_2(sc, WI_PARAM1, val1);
 1010         CSR_WRITE_2(sc, WI_PARAM2, val2);
 1011         CSR_WRITE_2(sc, WI_COMMAND, cmd);
 1012 
 1013         if (cmd == WI_CMD_INI)
 1014                 tmo *= 50;
 1015         for (i = 0; i < tmo; i++) {
 1016                 /*
 1017                  * Wait for 'command complete' bit to be
 1018                  * set in the event status register.
 1019                  */
 1020                 s = CSR_READ_2(sc, WI_EVENT_STAT);
 1021                 if (s & WI_EV_CMD) {
 1022                         /* Ack the event and read result code. */
 1023                         s = CSR_READ_2(sc, WI_STATUS);
 1024                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
 1025 #ifdef foo
 1026                         if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
 1027                                 return(EIO);
 1028 #endif
 1029                         if (s & WI_STAT_CMD_RESULT) {
 1030                                 count--;
 1031                                 return(EIO);
 1032                         }
 1033                         break;
 1034                 }
 1035                 DELAY(WI_DELAY);
 1036         }
 1037 
 1038         count--;
 1039         if (i == WI_TIMEOUT) {
 1040                 device_printf(sc->dev,
 1041                     "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
 1042                 return(ETIMEDOUT);
 1043         }
 1044         return(0);
 1045 }
 1046 
 1047 static void
 1048 wi_reset(sc)
 1049         struct wi_softc         *sc;
 1050 {
 1051 #define WI_INIT_TRIES 3
 1052         int i;
 1053         int tries;
 1054         
 1055         /* Symbol firmware cannot be initialized more than once */
 1056         if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_enabled)
 1057                 return;
 1058         if (sc->sc_firmware_type == WI_SYMBOL)
 1059                 tries = 1;
 1060         else
 1061                 tries = WI_INIT_TRIES;
 1062 
 1063         for (i = 0; i < tries; i++) {
 1064                 if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0)
 1065                         break;
 1066                 DELAY(WI_DELAY * 1000);
 1067         }
 1068         sc->sc_enabled = 1;
 1069 
 1070         if (i == tries) {
 1071                 device_printf(sc->dev, "init failed\n");
 1072                 return;
 1073         }
 1074 
 1075         CSR_WRITE_2(sc, WI_INT_EN, 0);
 1076         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
 1077 
 1078         /* Calibrate timer. */
 1079         WI_SETVAL(WI_RID_TICK_TIME, 8);
 1080 
 1081         return;
 1082 }
 1083 
 1084 /*
 1085  * Read an LTV record from the NIC.
 1086  */
 1087 static int
 1088 wi_read_record(sc, ltv)
 1089         struct wi_softc         *sc;
 1090         struct wi_ltv_gen       *ltv;
 1091 {
 1092         u_int16_t               *ptr;
 1093         int                     i, len, code;
 1094         struct wi_ltv_gen       *oltv, p2ltv;
 1095 
 1096         oltv = ltv;
 1097         if (sc->sc_firmware_type != WI_LUCENT) {
 1098                 switch (ltv->wi_type) {
 1099                 case WI_RID_ENCRYPTION:
 1100                         p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
 1101                         p2ltv.wi_len = 2;
 1102                         ltv = &p2ltv;
 1103                         break;
 1104                 case WI_RID_TX_CRYPT_KEY:
 1105                         p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
 1106                         p2ltv.wi_len = 2;
 1107                         ltv = &p2ltv;
 1108                         break;
 1109                 case WI_RID_ROAMING_MODE:
 1110                         if (sc->sc_firmware_type == WI_INTERSIL)
 1111                                 break;
 1112                         /* not supported */
 1113                         ltv->wi_len = 1;
 1114                         return 0;
 1115                 case WI_RID_MICROWAVE_OVEN:
 1116                         /* not supported */
 1117                         ltv->wi_len = 1;
 1118                         return 0;
 1119                 }
 1120         }
 1121 
 1122         /* Tell the NIC to enter record read mode. */
 1123         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
 1124                 return(EIO);
 1125 
 1126         /* Seek to the record. */
 1127         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
 1128                 return(EIO);
 1129 
 1130         /*
 1131          * Read the length and record type and make sure they
 1132          * match what we expect (this verifies that we have enough
 1133          * room to hold all of the returned data).
 1134          */
 1135         len = CSR_READ_2(sc, WI_DATA1);
 1136         if (len > ltv->wi_len)
 1137                 return(ENOSPC);
 1138         code = CSR_READ_2(sc, WI_DATA1);
 1139         if (code != ltv->wi_type)
 1140                 return(EIO);
 1141 
 1142         ltv->wi_len = len;
 1143         ltv->wi_type = code;
 1144 
 1145         /* Now read the data. */
 1146         ptr = &ltv->wi_val;
 1147         for (i = 0; i < ltv->wi_len - 1; i++)
 1148                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
 1149 
 1150         if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
 1151             && ltv->wi_val == sc->wi_ibss_port) {
 1152                 /*
 1153                  * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
 1154                  * Since Lucent uses port type 1 for BSS *and* IBSS we
 1155                  * have to rely on wi_ptype to distinguish this for us.
 1156                  */
 1157                 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
 1158         } else if (sc->sc_firmware_type != WI_LUCENT) {
 1159                 switch (oltv->wi_type) {
 1160                 case WI_RID_TX_RATE:
 1161                 case WI_RID_CUR_TX_RATE:
 1162                         switch (ltv->wi_val) {
 1163                         case 1: oltv->wi_val = 1; break;
 1164                         case 2: oltv->wi_val = 2; break;
 1165                         case 3: oltv->wi_val = 6; break;
 1166                         case 4: oltv->wi_val = 5; break;
 1167                         case 7: oltv->wi_val = 7; break;
 1168                         case 8: oltv->wi_val = 11; break;
 1169                         case 15: oltv->wi_val = 3; break;
 1170                         default: oltv->wi_val = 0x100 + ltv->wi_val; break;
 1171                         }
 1172                         break;
 1173                 case WI_RID_ENCRYPTION:
 1174                         oltv->wi_len = 2;
 1175                         if (ltv->wi_val & 0x01)
 1176                                 oltv->wi_val = 1;
 1177                         else
 1178                                 oltv->wi_val = 0;
 1179                         break;
 1180                 case WI_RID_TX_CRYPT_KEY:
 1181                         oltv->wi_len = 2;
 1182                         oltv->wi_val = ltv->wi_val;
 1183                         break;
 1184                 case WI_RID_CNFAUTHMODE:
 1185                         oltv->wi_len = 2;
 1186                         if (le16toh(ltv->wi_val) & 0x01)
 1187                                 oltv->wi_val = htole16(1);
 1188                         else if (le16toh(ltv->wi_val) & 0x02)
 1189                                 oltv->wi_val = htole16(2);
 1190                         break;
 1191                 }
 1192         }
 1193 
 1194         return(0);
 1195 }
 1196 
 1197 /*
 1198  * Same as read, except we inject data instead of reading it.
 1199  */
 1200 static int
 1201 wi_write_record(sc, ltv)
 1202         struct wi_softc         *sc;
 1203         struct wi_ltv_gen       *ltv;
 1204 {
 1205         u_int16_t               *ptr;
 1206         int                     i;
 1207         struct wi_ltv_gen       p2ltv;
 1208 
 1209         if (ltv->wi_type == WI_RID_PORTTYPE &&
 1210             le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) {
 1211                 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
 1212                 p2ltv.wi_type = WI_RID_PORTTYPE;
 1213                 p2ltv.wi_len = 2;
 1214                 p2ltv.wi_val = sc->wi_ibss_port;
 1215                 ltv = &p2ltv;
 1216         } else if (sc->sc_firmware_type != WI_LUCENT) {
 1217                 switch (ltv->wi_type) {
 1218                 case WI_RID_TX_RATE:
 1219                         p2ltv.wi_type = WI_RID_TX_RATE;
 1220                         p2ltv.wi_len = 2;
 1221                         switch (ltv->wi_val) {
 1222                         case 1: p2ltv.wi_val = 1; break;
 1223                         case 2: p2ltv.wi_val = 2; break;
 1224                         case 3: p2ltv.wi_val = 15; break;
 1225                         case 5: p2ltv.wi_val = 4; break;
 1226                         case 6: p2ltv.wi_val = 3; break;
 1227                         case 7: p2ltv.wi_val = 7; break;
 1228                         case 11: p2ltv.wi_val = 8; break;
 1229                         default: return EINVAL;
 1230                         }
 1231                         ltv = &p2ltv;
 1232                         break;
 1233                 case WI_RID_ENCRYPTION:
 1234                         p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
 1235                         p2ltv.wi_len = 2;
 1236                         if (le16toh(ltv->wi_val)) {
 1237                                 p2ltv.wi_val =htole16(PRIVACY_INVOKED |
 1238                                     EXCLUDE_UNENCRYPTED);
 1239                                 if (sc->wi_ptype == WI_PORTTYPE_AP)
 1240                                         /* 
 1241                                          * Disable tx encryption...
 1242                                          * it's broken.
 1243                                          */
 1244                                         p2ltv.wi_val |= htole16(HOST_ENCRYPT);
 1245                         } else
 1246                                 p2ltv.wi_val =
 1247                                     htole16(HOST_ENCRYPT | HOST_DECRYPT);
 1248                         ltv = &p2ltv;
 1249                         break;
 1250                 case WI_RID_TX_CRYPT_KEY:
 1251                         p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
 1252                         p2ltv.wi_len = 2;
 1253                         p2ltv.wi_val = ltv->wi_val;
 1254                         ltv = &p2ltv;
 1255                         break;
 1256                 case WI_RID_DEFLT_CRYPT_KEYS:
 1257                     {
 1258                         int error;
 1259                         int keylen;
 1260                         struct wi_ltv_str       ws;
 1261                         struct wi_ltv_keys      *wk =
 1262                             (struct wi_ltv_keys *)ltv;
 1263 
 1264                         keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
 1265 
 1266                         for (i = 0; i < 4; i++) {
 1267                                 bzero(&ws, sizeof(ws));
 1268                                 ws.wi_len = (keylen > 5) ? 8 : 4;
 1269                                 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
 1270                                 memcpy(ws.wi_str,
 1271                                     &wk->wi_keys[i].wi_keydat, keylen);
 1272                                 error = wi_write_record(sc,
 1273                                     (struct wi_ltv_gen *)&ws);
 1274                                 if (error)
 1275                                         return error;
 1276                         }
 1277                         return 0;
 1278                     }
 1279                 case WI_RID_CNFAUTHMODE:
 1280                         p2ltv.wi_type = WI_RID_CNFAUTHMODE;
 1281                         p2ltv.wi_len = 2;
 1282                         if (le16toh(ltv->wi_val) == 1)
 1283                                 p2ltv.wi_val = htole16(0x01);
 1284                         else if (le16toh(ltv->wi_val) == 2)
 1285                                 p2ltv.wi_val = htole16(0x02);
 1286                         ltv = &p2ltv;
 1287                         break;
 1288                 case WI_RID_ROAMING_MODE:
 1289                         if (sc->sc_firmware_type == WI_INTERSIL)
 1290                                 break;
 1291                         /* not supported */
 1292                         return 0;
 1293                 case WI_RID_MICROWAVE_OVEN:
 1294                         /* not supported */
 1295                         return 0;
 1296                 }
 1297         } else {
 1298                 /* LUCENT */
 1299                 switch (ltv->wi_type) {  
 1300                 case WI_RID_TX_RATE:
 1301                         switch (ltv->wi_val) {
 1302                         case 1: ltv->wi_val = 1; break;  /* 1Mb/s fixed */
 1303                         case 2: ltv->wi_val = 2; break;  /* 2Mb/s fixed */
 1304                         case 3: ltv->wi_val = 3; break;  /* 11Mb/s auto */
 1305                         case 5: ltv->wi_val = 4; break;  /* 5.5Mb/s fixed */
 1306                         case 6: ltv->wi_val = 6; break;  /* 2Mb/s auto */
 1307                         case 7: ltv->wi_val = 7; break;  /* 5.5Mb/s auto */
 1308                         case 11: ltv->wi_val = 5; break; /* 11Mb/s fixed */
 1309                         default: return EINVAL;
 1310                         }
 1311                 }
 1312         }
 1313 
 1314         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
 1315                 return(EIO);
 1316 
 1317         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
 1318         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
 1319 
 1320         ptr = &ltv->wi_val;
 1321         for (i = 0; i < ltv->wi_len - 1; i++)
 1322                 CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
 1323 
 1324         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
 1325                 return(EIO);
 1326 
 1327         return(0);
 1328 }
 1329 
 1330 static int
 1331 wi_seek(sc, id, off, chan)
 1332         struct wi_softc         *sc;
 1333         int                     id, off, chan;
 1334 {
 1335         int                     i;
 1336         int                     selreg, offreg;
 1337         int                     status;
 1338 
 1339         switch (chan) {
 1340         case WI_BAP0:
 1341                 selreg = WI_SEL0;
 1342                 offreg = WI_OFF0;
 1343                 break;
 1344         case WI_BAP1:
 1345                 selreg = WI_SEL1;
 1346                 offreg = WI_OFF1;
 1347                 break;
 1348         default:
 1349                 device_printf(sc->dev, "invalid data path: %x\n", chan);
 1350                 return(EIO);
 1351         }
 1352 
 1353         CSR_WRITE_2(sc, selreg, id);
 1354         CSR_WRITE_2(sc, offreg, off);
 1355 
 1356         for (i = 0; i < WI_TIMEOUT; i++) {
 1357                 status = CSR_READ_2(sc, offreg);
 1358                 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
 1359                         break;
 1360                 DELAY(WI_DELAY);
 1361         }
 1362 
 1363         if (i == WI_TIMEOUT) {
 1364                 device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n",
 1365                         id, off, status);
 1366                 return(ETIMEDOUT);
 1367         }
 1368 
 1369         return(0);
 1370 }
 1371 
 1372 static int
 1373 wi_read_data(sc, id, off, buf, len)
 1374         struct wi_softc         *sc;
 1375         int                     id, off;
 1376         caddr_t                 buf;
 1377         int                     len;
 1378 {
 1379         int                     i;
 1380         u_int16_t               *ptr;
 1381 
 1382         if (wi_seek(sc, id, off, WI_BAP1))
 1383                 return(EIO);
 1384 
 1385         ptr = (u_int16_t *)buf;
 1386         for (i = 0; i < len / 2; i++)
 1387                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
 1388 
 1389         return(0);
 1390 }
 1391 
 1392 /*
 1393  * According to the comments in the HCF Light code, there is a bug in
 1394  * the Hermes (or possibly in certain Hermes firmware revisions) where
 1395  * the chip's internal autoincrement counter gets thrown off during
 1396  * data writes: the autoincrement is missed, causing one data word to
 1397  * be overwritten and subsequent words to be written to the wrong memory
 1398  * locations. The end result is that we could end up transmitting bogus
 1399  * frames without realizing it. The workaround for this is to write a
 1400  * couple of extra guard words after the end of the transfer, then
 1401  * attempt to read then back. If we fail to locate the guard words where
 1402  * we expect them, we preform the transfer over again.
 1403  */
 1404 static int
 1405 wi_write_data(sc, id, off, buf, len)
 1406         struct wi_softc         *sc;
 1407         int                     id, off;
 1408         caddr_t                 buf;
 1409         int                     len;
 1410 {
 1411         int                     i;
 1412         u_int16_t               *ptr;
 1413 #ifdef WI_HERMES_AUTOINC_WAR
 1414         int                     retries;
 1415 
 1416         retries = 512;
 1417 again:
 1418 #endif
 1419 
 1420         if (wi_seek(sc, id, off, WI_BAP0))
 1421                 return(EIO);
 1422 
 1423         ptr = (u_int16_t *)buf;
 1424         for (i = 0; i < (len / 2); i++)
 1425                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
 1426 
 1427 #ifdef WI_HERMES_AUTOINC_WAR
 1428         CSR_WRITE_2(sc, WI_DATA0, 0x1234);
 1429         CSR_WRITE_2(sc, WI_DATA0, 0x5678);
 1430 
 1431         if (wi_seek(sc, id, off + len, WI_BAP0))
 1432                 return(EIO);
 1433 
 1434         if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
 1435             CSR_READ_2(sc, WI_DATA0) != 0x5678) {
 1436                 if (--retries >= 0)
 1437                         goto again;
 1438                 device_printf(sc->dev, "wi_write_data device timeout\n");
 1439                 return (EIO);
 1440         }
 1441 #endif
 1442 
 1443         return(0);
 1444 }
 1445 
 1446 /*
 1447  * Allocate a region of memory inside the NIC and zero
 1448  * it out.
 1449  */
 1450 static int
 1451 wi_alloc_nicmem(sc, len, id)
 1452         struct wi_softc         *sc;
 1453         int                     len;
 1454         int                     *id;
 1455 {
 1456         int                     i;
 1457 
 1458         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
 1459                 device_printf(sc->dev,
 1460                     "failed to allocate %d bytes on NIC\n", len);
 1461                 return(ENOMEM);
 1462         }
 1463 
 1464         for (i = 0; i < WI_TIMEOUT; i++) {
 1465                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
 1466                         break;
 1467                 DELAY(WI_DELAY);
 1468         }
 1469 
 1470         if (i == WI_TIMEOUT) {
 1471                 device_printf(sc->dev, "time out allocating memory on card\n");
 1472                 return(ETIMEDOUT);
 1473         }
 1474 
 1475         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 1476         *id = CSR_READ_2(sc, WI_ALLOC_FID);
 1477 
 1478         if (wi_seek(sc, *id, 0, WI_BAP0)) {
 1479                 device_printf(sc->dev, "seek failed while allocating memory on card\n");
 1480                 return(EIO);
 1481         }
 1482 
 1483         for (i = 0; i < len / 2; i++)
 1484                 CSR_WRITE_2(sc, WI_DATA0, 0);
 1485 
 1486         return(0);
 1487 }
 1488 
 1489 static void
 1490 wi_setmulti(sc)
 1491         struct wi_softc         *sc;
 1492 {
 1493         struct ifnet            *ifp;
 1494         int                     i = 0;
 1495         struct ifmultiaddr      *ifma;
 1496         struct wi_ltv_mcast     mcast;
 1497 
 1498         ifp = &sc->arpcom.ac_if;
 1499 
 1500         bzero((char *)&mcast, sizeof(mcast));
 1501 
 1502         mcast.wi_type = WI_RID_MCAST_LIST;
 1503         mcast.wi_len = (3 * 16) + 1;
 1504 
 1505         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
 1506                 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
 1507                 return;
 1508         }
 1509 
 1510 #if __FreeBSD_version < 500000
 1511         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1512 #else
 1513         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1514 #endif
 1515                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1516                         continue;
 1517                 if (i < 16) {
 1518                         bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
 1519                             (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
 1520                         i++;
 1521                 } else {
 1522                         bzero((char *)&mcast, sizeof(mcast));
 1523                         break;
 1524                 }
 1525         }
 1526 
 1527         mcast.wi_len = (i * 3) + 1;
 1528         wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
 1529 
 1530         return;
 1531 }
 1532 
 1533 static void
 1534 wi_setdef(sc, wreq)
 1535         struct wi_softc         *sc;
 1536         struct wi_req           *wreq;
 1537 {
 1538         struct sockaddr_dl      *sdl;
 1539         struct ifaddr           *ifa;
 1540         struct ifnet            *ifp;
 1541 
 1542         ifp = &sc->arpcom.ac_if;
 1543 
 1544         switch(wreq->wi_type) {
 1545         case WI_RID_MAC_NODE:
 1546                 ifa = ifaddr_byindex(ifp->if_index);
 1547                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 1548                 bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
 1549                    ETHER_ADDR_LEN);
 1550                 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
 1551                 break;
 1552         case WI_RID_PORTTYPE:
 1553                 sc->wi_ptype = le16toh(wreq->wi_val[0]);
 1554                 break;
 1555         case WI_RID_TX_RATE:
 1556                 sc->wi_tx_rate = le16toh(wreq->wi_val[0]);
 1557                 break;
 1558         case WI_RID_MAX_DATALEN:
 1559                 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
 1560                 break;
 1561         case WI_RID_RTS_THRESH:
 1562                 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
 1563                 break;
 1564         case WI_RID_SYSTEM_SCALE:
 1565                 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
 1566                 break;
 1567         case WI_RID_CREATE_IBSS:
 1568                 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
 1569                 break;
 1570         case WI_RID_OWN_CHNL:
 1571                 sc->wi_channel = le16toh(wreq->wi_val[0]);
 1572                 break;
 1573         case WI_RID_NODENAME:
 1574                 bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
 1575                 bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
 1576                 break;
 1577         case WI_RID_DESIRED_SSID:
 1578                 bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
 1579                 bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
 1580                 break;
 1581         case WI_RID_OWN_SSID:
 1582                 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
 1583                 bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
 1584                 break;
 1585         case WI_RID_PM_ENABLED:
 1586                 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
 1587                 break;
 1588         case WI_RID_MICROWAVE_OVEN:
 1589                 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
 1590                 break;
 1591         case WI_RID_MAX_SLEEP:
 1592                 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
 1593                 break;
 1594         case WI_RID_CNFAUTHMODE:
 1595                 sc->wi_authtype = le16toh(wreq->wi_val[0]);
 1596                 break;
 1597         case WI_RID_ROAMING_MODE:
 1598                 sc->wi_roaming = le16toh(wreq->wi_val[0]);
 1599                 break;
 1600         case WI_RID_ENCRYPTION:
 1601                 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
 1602                 break;
 1603         case WI_RID_TX_CRYPT_KEY:
 1604                 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
 1605                 break;
 1606         case WI_RID_DEFLT_CRYPT_KEYS:
 1607                 bcopy((char *)wreq, (char *)&sc->wi_keys,
 1608                     sizeof(struct wi_ltv_keys));
 1609                 break;
 1610         default:
 1611                 break;
 1612         }
 1613 
 1614         /* Reinitialize WaveLAN. */
 1615         wi_init(sc);
 1616 
 1617         return;
 1618 }
 1619 
 1620 static int
 1621 wi_ioctl(ifp, command, data)
 1622         struct ifnet            *ifp;
 1623         u_long                  command;
 1624         caddr_t                 data;
 1625 {
 1626         int                     error = 0;
 1627         int                     len;
 1628         u_int8_t                tmpkey[14];
 1629         char                    tmpssid[IEEE80211_NWID_LEN];
 1630         struct wi_softc         *sc;
 1631         struct wi_req           wreq;
 1632         struct ifreq            *ifr;
 1633         struct ieee80211req     *ireq;
 1634 #if __FreeBSD_version >= 500000
 1635         struct thread           *td = curthread;
 1636 #else
 1637         struct proc             *td = curproc;          /* Little white lie */
 1638 #endif
 1639         int                     s;
 1640 
 1641         sc = ifp->if_softc;
 1642         WI_LOCK(sc, s);
 1643         ifr = (struct ifreq *)data;
 1644         ireq = (struct ieee80211req *)data;
 1645 
 1646         if (sc->wi_gone) {
 1647                 error = ENODEV;
 1648                 goto out;
 1649         }
 1650 
 1651         switch(command) {
 1652         case SIOCSIFADDR:
 1653         case SIOCGIFADDR:
 1654         case SIOCSIFMTU:
 1655                 error = ether_ioctl(ifp, command, data);
 1656                 break;
 1657         case SIOCSIFFLAGS:
 1658                 /*
 1659                  * Can't do promisc and hostap at the same time.  If all that's
 1660                  * changing is the promisc flag, try to short-circuit a call to
 1661                  * wi_init() by just setting PROMISC in the hardware.
 1662                  */
 1663                 if (ifp->if_flags & IFF_UP) {
 1664                         if (sc->wi_ptype != WI_PORTTYPE_AP &&
 1665                             ifp->if_flags & IFF_RUNNING) {
 1666                                 if (ifp->if_flags & IFF_PROMISC &&
 1667                                     !(sc->wi_if_flags & IFF_PROMISC)) {
 1668                                         WI_SETVAL(WI_RID_PROMISC, 1);
 1669                                 } else if (!(ifp->if_flags & IFF_PROMISC) &&
 1670                                     sc->wi_if_flags & IFF_PROMISC) {
 1671                                         WI_SETVAL(WI_RID_PROMISC, 0);
 1672                                 } else {
 1673                                         wi_init(sc);
 1674                                 }
 1675                         } else {
 1676                                 wi_init(sc);
 1677                         }
 1678                 } else {
 1679                         if (ifp->if_flags & IFF_RUNNING) {
 1680                                 wi_stop(sc);
 1681                         }
 1682                 }
 1683                 sc->wi_if_flags = ifp->if_flags;
 1684                 error = 0;
 1685                 break;
 1686         case SIOCSIFMEDIA:
 1687         case SIOCGIFMEDIA:
 1688                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
 1689                 break;
 1690         case SIOCADDMULTI:
 1691         case SIOCDELMULTI:
 1692                 wi_setmulti(sc);
 1693                 error = 0;
 1694                 break;
 1695         case SIOCGWAVELAN:
 1696                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1697                 if (error)
 1698                         break;
 1699                 if (wreq.wi_len > WI_MAX_DATALEN) {
 1700                         error = EINVAL;
 1701                         break;
 1702                 }
 1703                 /* Don't show WEP keys to non-root users. */
 1704                 if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && suser(td))
 1705                         break;
 1706                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
 1707                         bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
 1708                             sizeof(sc->wi_stats));
 1709                         wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
 1710                 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
 1711                         bcopy((char *)&sc->wi_keys, (char *)&wreq,
 1712                             sizeof(struct wi_ltv_keys));
 1713                 }
 1714 #ifdef WICACHE
 1715                 else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
 1716                         sc->wi_sigitems = sc->wi_nextitem = 0;
 1717                 } else if (wreq.wi_type == WI_RID_READ_CACHE) {
 1718                         char *pt = (char *)&wreq.wi_val;
 1719                         bcopy((char *)&sc->wi_sigitems,
 1720                             (char *)pt, sizeof(int));
 1721                         pt += (sizeof (int));
 1722                         wreq.wi_len = sizeof(int) / 2;
 1723                         bcopy((char *)&sc->wi_sigcache, (char *)pt,
 1724                             sizeof(struct wi_sigcache) * sc->wi_sigitems);
 1725                         wreq.wi_len += ((sizeof(struct wi_sigcache) *
 1726                             sc->wi_sigitems) / 2) + 1;
 1727                 }
 1728 #endif
 1729                 else if (wreq.wi_type == WI_RID_PROCFRAME) {
 1730                         wreq.wi_len = 2;
 1731                         wreq.wi_val[0] = sc->wi_procframe;
 1732                 } else if (wreq.wi_type == WI_RID_PRISM2) {
 1733                         wreq.wi_len = 2;
 1734                         wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
 1735                 } else if (wreq.wi_type == WI_RID_SCAN_RES && 
 1736                     sc->sc_firmware_type == WI_LUCENT) {
 1737                         memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf,
 1738                             sc->wi_scanbuf_len * 2);
 1739                         wreq.wi_len = sc->wi_scanbuf_len;
 1740                 } else {
 1741                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
 1742                                 error = EINVAL;
 1743                                 break;
 1744                         }
 1745                 }
 1746                 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
 1747                 break;
 1748         case SIOCSWAVELAN:
 1749                 if ((error = suser(td)))
 1750                         goto out;
 1751                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1752                 if (error)
 1753                         break;
 1754                 if (wreq.wi_len > WI_MAX_DATALEN) {
 1755                         error = EINVAL;
 1756                         break;
 1757                 }
 1758                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
 1759                         error = EINVAL;
 1760                         break;
 1761                 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
 1762                         error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
 1763                             wreq.wi_len);
 1764                 } else if (wreq.wi_type == WI_RID_PROCFRAME) {
 1765                         sc->wi_procframe = wreq.wi_val[0];
 1766                 /*
 1767                  * if we're getting a scan request from a wavelan card
 1768                  * (non-prism2), send out a cmd_inquire to the card to scan
 1769                  * results for the scan will be received through the info
 1770                  * interrupt handler. otherwise the scan request can be
 1771                  * directly handled by a prism2 card's rid interface.
 1772                  */
 1773                 } else if (wreq.wi_type == WI_RID_SCAN_REQ && 
 1774                     sc->sc_firmware_type == WI_LUCENT) {
 1775                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 1776                 } else {
 1777                         error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
 1778                         if (!error)
 1779                                 wi_setdef(sc, &wreq);
 1780                 }
 1781                 break;
 1782         case SIOCGPRISM2DEBUG:
 1783                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1784                 if (error)
 1785                         break;
 1786                 if (!(ifp->if_flags & IFF_RUNNING) ||
 1787                     sc->sc_firmware_type == WI_LUCENT) {
 1788                         error = EIO;
 1789                         break;
 1790                 }
 1791                 error = wi_get_debug(sc, &wreq);
 1792                 if (error == 0)
 1793                         error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
 1794                 break;
 1795         case SIOCSPRISM2DEBUG:
 1796                 if ((error = suser(td)))
 1797                         goto out;
 1798                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1799                 if (error)
 1800                         break;
 1801                 error = wi_set_debug(sc, &wreq);
 1802                 break;
 1803         case SIOCG80211:
 1804                 switch(ireq->i_type) {
 1805                 case IEEE80211_IOC_SSID:
 1806                         if(ireq->i_val == -1) {
 1807                                 bzero(tmpssid, IEEE80211_NWID_LEN);
 1808                                 error = wi_get_cur_ssid(sc, tmpssid, &len);
 1809                                 if (error != 0)
 1810                                         break;
 1811                                 error = copyout(tmpssid, ireq->i_data,
 1812                                         IEEE80211_NWID_LEN);
 1813                                 ireq->i_len = len;
 1814                         } else if (ireq->i_val == 0) {
 1815                                 error = copyout(sc->wi_net_name,
 1816                                     ireq->i_data,
 1817                                     IEEE80211_NWID_LEN);
 1818                                 ireq->i_len = IEEE80211_NWID_LEN;
 1819                         } else
 1820                                 error = EINVAL;
 1821                         break;
 1822                 case IEEE80211_IOC_NUMSSIDS:
 1823                         ireq->i_val = 1;
 1824                         break;
 1825                 case IEEE80211_IOC_WEP:
 1826                         if(!sc->wi_has_wep) {
 1827                                 ireq->i_val = IEEE80211_WEP_NOSUP; 
 1828                         } else {
 1829                                 if(sc->wi_use_wep) {
 1830                                         ireq->i_val =
 1831                                             IEEE80211_WEP_MIXED;
 1832                                 } else {
 1833                                         ireq->i_val =
 1834                                             IEEE80211_WEP_OFF;
 1835                                 }
 1836                         }
 1837                         break;
 1838                 case IEEE80211_IOC_WEPKEY:
 1839                         if(!sc->wi_has_wep ||
 1840                             ireq->i_val < 0 || ireq->i_val > 3) {
 1841                                 error = EINVAL;
 1842                                 break;
 1843                         }
 1844                         len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen;
 1845                         if (suser(td))
 1846                                 bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
 1847                                     tmpkey, len);
 1848                         else
 1849                                 bzero(tmpkey, len);
 1850 
 1851                         ireq->i_len = len;
 1852                         error = copyout(tmpkey, ireq->i_data, len);
 1853 
 1854                         break;
 1855                 case IEEE80211_IOC_NUMWEPKEYS:
 1856                         if(!sc->wi_has_wep)
 1857                                 error = EINVAL;
 1858                         else
 1859                                 ireq->i_val = 4;
 1860                         break;
 1861                 case IEEE80211_IOC_WEPTXKEY:
 1862                         if(!sc->wi_has_wep)
 1863                                 error = EINVAL;
 1864                         else
 1865                                 ireq->i_val = sc->wi_tx_key;
 1866                         break;
 1867                 case IEEE80211_IOC_AUTHMODE:
 1868                         ireq->i_val = sc->wi_authmode;
 1869                         break;
 1870                 case IEEE80211_IOC_STATIONNAME:
 1871                         error = copyout(sc->wi_node_name,
 1872                             ireq->i_data, IEEE80211_NWID_LEN);
 1873                         ireq->i_len = IEEE80211_NWID_LEN;
 1874                         break;
 1875                 case IEEE80211_IOC_CHANNEL:
 1876                         wreq.wi_type = WI_RID_CURRENT_CHAN;
 1877                         wreq.wi_len = WI_MAX_DATALEN;
 1878                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
 1879                                 error = EINVAL;
 1880                         else {
 1881                                 ireq->i_val = wreq.wi_val[0];
 1882                         }
 1883                         break;
 1884                 case IEEE80211_IOC_POWERSAVE:
 1885                         if(sc->wi_pm_enabled)
 1886                                 ireq->i_val = IEEE80211_POWERSAVE_ON;
 1887                         else
 1888                                 ireq->i_val = IEEE80211_POWERSAVE_OFF;
 1889                         break;
 1890                 case IEEE80211_IOC_POWERSAVESLEEP:
 1891                         ireq->i_val = sc->wi_max_sleep;
 1892                         break;
 1893                 default:
 1894                         error = EINVAL;
 1895                 }
 1896                 break;
 1897         case SIOCS80211:
 1898                 if ((error = suser(td)))
 1899                         goto out;
 1900                 switch(ireq->i_type) {
 1901                 case IEEE80211_IOC_SSID:
 1902                         if (ireq->i_val > 0 ||
 1903                             ireq->i_len > IEEE80211_NWID_LEN) {
 1904                                 error = EINVAL;
 1905                                 break;
 1906                         }
 1907                         /* We set both of them */
 1908                         bzero(sc->wi_net_name, IEEE80211_NWID_LEN);
 1909                         error = copyin(ireq->i_data,
 1910                             sc->wi_net_name, ireq->i_len);
 1911                         bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN);
 1912                         break;
 1913                 case IEEE80211_IOC_WEP:
 1914                         /*
 1915                          * These cards only support one mode so
 1916                          * we just turn wep on what ever is
 1917                          * passed in if it's not OFF.
 1918                          */
 1919                         if (ireq->i_val == IEEE80211_WEP_OFF) {
 1920                                 sc->wi_use_wep = 0;
 1921                         } else {
 1922                                 sc->wi_use_wep = 1;
 1923                         }
 1924                         break;
 1925                 case IEEE80211_IOC_WEPKEY:
 1926                         if (ireq->i_val < 0 || ireq->i_val > 3 ||
 1927                                 ireq->i_len > 13) {
 1928                                 error = EINVAL;
 1929                                 break;
 1930                         } 
 1931                         bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13);
 1932                         error = copyin(ireq->i_data, 
 1933                             sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
 1934                             ireq->i_len);
 1935                         if(error)
 1936                                 break;
 1937                         sc->wi_keys.wi_keys[ireq->i_val].wi_keylen =
 1938                                     ireq->i_len;
 1939                         break;
 1940                 case IEEE80211_IOC_WEPTXKEY:
 1941                         if (ireq->i_val < 0 || ireq->i_val > 3) {
 1942                                 error = EINVAL;
 1943                                 break;
 1944                         }
 1945                         sc->wi_tx_key = ireq->i_val;
 1946                         break;
 1947                 case IEEE80211_IOC_AUTHMODE:
 1948                         sc->wi_authmode = ireq->i_val;
 1949                         break;
 1950                 case IEEE80211_IOC_STATIONNAME:
 1951                         if (ireq->i_len > 32) {
 1952                                 error = EINVAL;
 1953                                 break;
 1954                         }
 1955                         bzero(sc->wi_node_name, 32);
 1956                         error = copyin(ireq->i_data,
 1957                             sc->wi_node_name, ireq->i_len);
 1958                         break;
 1959                 case IEEE80211_IOC_CHANNEL:
 1960                         /*
 1961                          * The actual range is 1-14, but if you
 1962                          * set it to 0 you get the default. So
 1963                          * we let that work too.
 1964                          */
 1965                         if (ireq->i_val < 0 || ireq->i_val > 14) {
 1966                                 error = EINVAL;
 1967                                 break;
 1968                         }
 1969                         sc->wi_channel = ireq->i_val;
 1970                         break;
 1971                 case IEEE80211_IOC_POWERSAVE:
 1972                         switch (ireq->i_val) {
 1973                         case IEEE80211_POWERSAVE_OFF:
 1974                                 sc->wi_pm_enabled = 0;
 1975                                 break;
 1976                         case IEEE80211_POWERSAVE_ON:
 1977                                 sc->wi_pm_enabled = 1;
 1978                                 break;
 1979                         default:
 1980                                 error = EINVAL;
 1981                                 break;
 1982                         }
 1983                         break;
 1984                 case IEEE80211_IOC_POWERSAVESLEEP:
 1985                         if (ireq->i_val < 0) {
 1986                                 error = EINVAL;
 1987                                 break;
 1988                         }
 1989                         sc->wi_max_sleep = ireq->i_val;
 1990                         break;
 1991                 default:
 1992                         error = EINVAL;
 1993                         break;
 1994                 }
 1995 
 1996                 /* Reinitialize WaveLAN. */
 1997                 wi_init(sc);
 1998 
 1999         break;
 2000         case SIOCHOSTAP_ADD:
 2001         case SIOCHOSTAP_DEL:
 2002         case SIOCHOSTAP_GET:
 2003         case SIOCHOSTAP_GETALL:
 2004         case SIOCHOSTAP_GFLAGS:
 2005         case SIOCHOSTAP_SFLAGS:
 2006                 /* Send all Host AP specific ioctl's to Host AP code. */
 2007                 error = wihap_ioctl(sc, command, data);
 2008                 break;
 2009         default:
 2010                 error = EINVAL;
 2011                 break;
 2012         }
 2013 out:
 2014         WI_UNLOCK(sc, s);
 2015 
 2016         return(error);
 2017 }
 2018 
 2019 static void
 2020 wi_init(xsc)
 2021         void                    *xsc;
 2022 {
 2023         struct wi_softc         *sc = xsc;
 2024         struct ifnet            *ifp = &sc->arpcom.ac_if;
 2025         struct wi_ltv_macaddr   mac;
 2026         int                     id = 0;
 2027         int                     s;
 2028 
 2029         WI_LOCK(sc, s);
 2030 
 2031         if (sc->wi_gone) {
 2032                 WI_UNLOCK(sc, s);
 2033                 return;
 2034         }
 2035 
 2036         if (ifp->if_flags & IFF_RUNNING)
 2037                 wi_stop(sc);
 2038 
 2039         wi_reset(sc);
 2040 
 2041         /* Program max data length. */
 2042         WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
 2043 
 2044         /* Set the port type. */
 2045         WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
 2046 
 2047         /* Enable/disable IBSS creation. */
 2048         WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
 2049 
 2050         /* Program the RTS/CTS threshold. */
 2051         WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
 2052 
 2053         /* Program the TX rate */
 2054         WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
 2055 
 2056         /* Access point density */
 2057         WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
 2058 
 2059         /* Power Management Enabled */
 2060         WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
 2061 
 2062         /* Power Managment Max Sleep */
 2063         WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
 2064 
 2065         /* Roaming type */
 2066         WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
 2067 
 2068         /* Specify the IBSS name */
 2069         WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
 2070 
 2071         /* Specify the network name */
 2072         WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
 2073 
 2074         /* Specify the frequency to use */
 2075         WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
 2076 
 2077         /* Program the nodename. */
 2078         WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
 2079 
 2080         /* Specify the authentication mode. */
 2081         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authmode);
 2082 
 2083         /* Set our MAC address. */
 2084         mac.wi_len = 4;
 2085         mac.wi_type = WI_RID_MAC_NODE;
 2086         bcopy((char *)&sc->arpcom.ac_enaddr,
 2087            (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
 2088         wi_write_record(sc, (struct wi_ltv_gen *)&mac);
 2089 
 2090         /*
 2091          * Initialize promisc mode.
 2092          *      Being in the Host-AP mode causes
 2093          *      great deal of pain if promisc mode is set.
 2094          *      Therefore we avoid confusing the firmware
 2095          *      and always reset promisc mode in Host-AP regime,
 2096          *      it shows us all the packets anyway.
 2097          */
 2098         if (sc->wi_ptype != WI_PORTTYPE_AP && ifp->if_flags & IFF_PROMISC)
 2099                 WI_SETVAL(WI_RID_PROMISC, 1);
 2100         else
 2101                 WI_SETVAL(WI_RID_PROMISC, 0);
 2102 
 2103         /* Configure WEP. */
 2104         if (sc->wi_has_wep) {
 2105                 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
 2106                 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
 2107                 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
 2108                 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
 2109                 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
 2110                 if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
 2111                         /*
 2112                          * ONLY HWB3163 EVAL-CARD Firmware version
 2113                          * less than 0.8 variant2
 2114                          *
 2115                          * If promiscuous mode disable, Prism2 chip
 2116                          * does not work with WEP.
 2117                          * It is under investigation for details.
 2118                          * (ichiro@netbsd.org)
 2119                          *
 2120                          * And make sure that we don't need to do it
 2121                          * in hostap mode, since it interferes with
 2122                          * the above hostap workaround.
 2123                          */
 2124                         if (sc->wi_ptype != WI_PORTTYPE_AP &&
 2125                             sc->sc_firmware_type == WI_INTERSIL &&
 2126                             sc->sc_sta_firmware_ver < 802 ) {
 2127                                 /* firm ver < 0.8 variant 2 */
 2128                                 WI_SETVAL(WI_RID_PROMISC, 1);
 2129                         }
 2130                         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
 2131                 }
 2132         }
 2133 
 2134         /* Set multicast filter. */
 2135         wi_setmulti(sc);
 2136 
 2137         /* Enable desired port */
 2138         wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
 2139 
 2140         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
 2141                 device_printf(sc->dev, "tx buffer allocation failed\n");
 2142         sc->wi_tx_data_id = id;
 2143 
 2144         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
 2145                 device_printf(sc->dev, "mgmt. buffer allocation failed\n");
 2146         sc->wi_tx_mgmt_id = id;
 2147 
 2148         /* enable interrupts */
 2149         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 2150 
 2151         wihap_init(sc);
 2152 
 2153         ifp->if_flags |= IFF_RUNNING;
 2154         ifp->if_flags &= ~IFF_OACTIVE;
 2155 
 2156         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
 2157         WI_UNLOCK(sc, s);
 2158 
 2159         return;
 2160 }
 2161 
 2162 #define RC4STATE 256
 2163 #define RC4KEYLEN 16
 2164 #define RC4SWAP(x,y) \
 2165     do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
 2166 
 2167 static void
 2168 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
 2169 {
 2170         u_int32_t i, crc, klen;
 2171         u_int8_t state[RC4STATE], key[RC4KEYLEN];
 2172         u_int8_t x, y, *dat;
 2173 
 2174         if (!sc->wi_icv_flag) {
 2175                 sc->wi_icv = arc4random();
 2176                 sc->wi_icv_flag++;
 2177         } else
 2178                 sc->wi_icv++;
 2179         /*
 2180          * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
 2181          * (B, 255, N) with 3 <= B < 8
 2182          */
 2183         if (sc->wi_icv >= 0x03ff00 &&
 2184             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
 2185                 sc->wi_icv += 0x000100;
 2186 
 2187         /* prepend 24bit IV to tx key, byte order does not matter */
 2188         key[0] = sc->wi_icv >> 16;
 2189         key[1] = sc->wi_icv >> 8;
 2190         key[2] = sc->wi_icv;
 2191 
 2192         klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen +
 2193             IEEE80211_WEP_IVLEN;
 2194         klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
 2195         bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
 2196             (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
 2197 
 2198         /* rc4 keysetup */
 2199         x = y = 0;
 2200         for (i = 0; i < RC4STATE; i++)
 2201                 state[i] = i;
 2202         for (i = 0; i < RC4STATE; i++) {
 2203                 y = (key[x] + state[i] + y) % RC4STATE;
 2204                 RC4SWAP(i, y);
 2205                 x = (x + 1) % klen;
 2206         }
 2207 
 2208         /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
 2209         dat = buf;
 2210         dat[0] = key[0];
 2211         dat[1] = key[1];
 2212         dat[2] = key[2];
 2213         dat[3] = sc->wi_tx_key << 6;            /* pad and keyid */
 2214         dat += 4;
 2215 
 2216         /* compute rc4 over data, crc32 over data */
 2217         crc = ~0;
 2218         x = y = 0;
 2219         for (i = 0; i < len; i++) {
 2220                 x = (x + 1) % RC4STATE;
 2221                 y = (state[x] + y) % RC4STATE;
 2222                 RC4SWAP(x, y);
 2223                 crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
 2224                 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
 2225         }
 2226         crc = ~crc;
 2227         dat += len;
 2228 
 2229         /* append little-endian crc32 and encrypt */
 2230         dat[0] = crc;
 2231         dat[1] = crc >> 8;
 2232         dat[2] = crc >> 16;
 2233         dat[3] = crc >> 24;
 2234         for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
 2235                 x = (x + 1) % RC4STATE;
 2236                 y = (state[x] + y) % RC4STATE;
 2237                 RC4SWAP(x, y);
 2238                 dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
 2239         }
 2240 }
 2241 
 2242 static void
 2243 wi_start(ifp)
 2244         struct ifnet            *ifp;
 2245 {
 2246         struct wi_softc         *sc;
 2247         struct mbuf             *m0;
 2248         struct wi_frame         tx_frame;
 2249         struct ether_header     *eh;
 2250         int                     id;
 2251         int                     s;
 2252 
 2253         sc = ifp->if_softc;
 2254         WI_LOCK(sc, s);
 2255 
 2256         if (sc->wi_gone) {
 2257                 WI_UNLOCK(sc, s);
 2258                 return;
 2259         }
 2260 
 2261         if (ifp->if_flags & IFF_OACTIVE) {
 2262                 WI_UNLOCK(sc, s);
 2263                 return;
 2264         }
 2265 
 2266 nextpkt:
 2267         IF_DEQUEUE(&ifp->if_snd, m0);
 2268         if (m0 == NULL) {
 2269                 WI_UNLOCK(sc, s);
 2270                 return;
 2271         }
 2272 
 2273         bzero((char *)&tx_frame, sizeof(tx_frame));
 2274         tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
 2275         id = sc->wi_tx_data_id;
 2276         eh = mtod(m0, struct ether_header *);
 2277 
 2278         if (sc->wi_ptype == WI_PORTTYPE_AP) {
 2279                 if (!wihap_check_tx(&sc->wi_hostap_info,
 2280                     eh->ether_dhost, &tx_frame.wi_tx_rate)) {
 2281                         if (ifp->if_flags & IFF_DEBUG)
 2282                                 printf("wi_start: dropping unassoc "
 2283                                        "dst %6D\n", eh->ether_dhost, ":");
 2284                         m_freem(m0);
 2285                         goto nextpkt;
 2286                 }
 2287         }
 2288         /*
 2289          * Use RFC1042 encoding for IP and ARP datagrams,
 2290          * 802.3 for anything else.
 2291          */
 2292         if (ntohs(eh->ether_type) > ETHER_MAX_LEN) {
 2293                 bcopy((char *)&eh->ether_dhost,
 2294                     (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
 2295                 if (sc->wi_ptype == WI_PORTTYPE_AP) {
 2296                         tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT; /* XXX */
 2297                         tx_frame.wi_frame_ctl |= WI_FCTL_FROMDS;
 2298                         if (sc->wi_use_wep)
 2299                                 tx_frame.wi_frame_ctl |= WI_FCTL_WEP;
 2300                         bcopy((char *)&sc->arpcom.ac_enaddr,
 2301                               (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
 2302                         bcopy((char *)&eh->ether_shost,
 2303                               (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
 2304                 }
 2305                 else
 2306                         bcopy((char *)&eh->ether_shost,
 2307                             (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
 2308                 bcopy((char *)&eh->ether_dhost,
 2309                     (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
 2310                 bcopy((char *)&eh->ether_shost,
 2311                     (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
 2312 
 2313                 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
 2314                 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
 2315                 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
 2316                 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
 2317                 tx_frame.wi_type = eh->ether_type;
 2318 
 2319                 if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
 2320                         /* Do host encryption. */
 2321                         bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
 2322                         m_copydata(m0, sizeof(struct ether_header),
 2323                             m0->m_pkthdr.len - sizeof(struct ether_header),
 2324                             (caddr_t)&sc->wi_txbuf[12]);
 2325                         wi_do_hostencrypt(sc, &sc->wi_txbuf[0],
 2326                             tx_frame.wi_dat_len);
 2327                         tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
 2328                             IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
 2329                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
 2330                             sizeof(struct wi_frame));
 2331                         wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
 2332                             (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
 2333                             sizeof(struct ether_header)) + 18);
 2334                 } else {
 2335                         m_copydata(m0, sizeof(struct ether_header),
 2336                             m0->m_pkthdr.len - sizeof(struct ether_header),
 2337                             (caddr_t)&sc->wi_txbuf);
 2338                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
 2339                             sizeof(struct wi_frame));
 2340                         wi_write_data(sc, id, WI_802_11_OFFSET,
 2341                             (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
 2342                             sizeof(struct ether_header)) + 2);
 2343                 }
 2344         } else {
 2345                 tx_frame.wi_dat_len = m0->m_pkthdr.len;
 2346 
 2347                 if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
 2348                         /* Do host encryption. */
 2349                 } else {
 2350                         eh->ether_type = htons(m0->m_pkthdr.len -
 2351                             WI_SNAPHDR_LEN);
 2352                         m_copydata(m0, 0, m0->m_pkthdr.len,
 2353                             (caddr_t)&sc->wi_txbuf);
 2354 
 2355                         wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
 2356                             sizeof(struct wi_frame));
 2357                         wi_write_data(sc, id, WI_802_3_OFFSET,
 2358                             (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
 2359                 }
 2360         }
 2361 
 2362         /*
 2363          * If there's a BPF listner, bounce a copy of
 2364          * this frame to him. Also, don't send this to the bpf sniffer
 2365          * if we're in procframe or monitor sniffing mode.
 2366          */
 2367         if (!(sc->wi_procframe || sc->wi_debug.wi_monitor) && ifp->if_bpf)
 2368                 bpf_mtap(ifp, m0);
 2369 
 2370         m_freem(m0);
 2371 
 2372         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
 2373                 device_printf(sc->dev, "xmit failed\n");
 2374 
 2375         ifp->if_flags |= IFF_OACTIVE;
 2376 
 2377         /*
 2378          * Set a timeout in case the chip goes out to lunch.
 2379          */
 2380         ifp->if_timer = 5;
 2381 
 2382         WI_UNLOCK(sc, s);
 2383         return;
 2384 }
 2385 
 2386 int
 2387 wi_mgmt_xmit(sc, data, len)
 2388         struct wi_softc         *sc;
 2389         caddr_t                 data;
 2390         int                     len;
 2391 {
 2392         struct wi_frame         tx_frame;
 2393         int                     id;
 2394         struct wi_80211_hdr     *hdr;
 2395         caddr_t                 dptr;
 2396 
 2397         if (sc->wi_gone)
 2398                 return(ENODEV);
 2399 
 2400         hdr = (struct wi_80211_hdr *)data;
 2401         dptr = data + sizeof(struct wi_80211_hdr);
 2402 
 2403         bzero((char *)&tx_frame, sizeof(tx_frame));
 2404         id = sc->wi_tx_mgmt_id;
 2405 
 2406         bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
 2407            sizeof(struct wi_80211_hdr));
 2408 
 2409         tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT;
 2410         tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
 2411         tx_frame.wi_len = htons(tx_frame.wi_dat_len);
 2412 
 2413         wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
 2414         wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
 2415             len - sizeof(struct wi_80211_hdr) + 2);
 2416 
 2417         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
 2418                 device_printf(sc->dev, "xmit failed\n");
 2419                 return(EIO);
 2420         }
 2421 
 2422         return(0);
 2423 }
 2424 
 2425 void
 2426 wi_stop(sc)
 2427         struct wi_softc         *sc;
 2428 {
 2429         struct ifnet            *ifp;
 2430         int                     s;
 2431 
 2432         WI_LOCK(sc, s);
 2433 
 2434         if (sc->wi_gone) {
 2435                 WI_UNLOCK(sc, s);
 2436                 return;
 2437         }
 2438 
 2439         wihap_shutdown(sc);
 2440 
 2441         ifp = &sc->arpcom.ac_if;
 2442 
 2443         /*
 2444          * If the card is gone and the memory port isn't mapped, we will
 2445          * (hopefully) get 0xffff back from the status read, which is not
 2446          * a valid status value.
 2447          */
 2448         if (CSR_READ_2(sc, WI_STATUS) != 0xffff) {
 2449                 CSR_WRITE_2(sc, WI_INT_EN, 0);
 2450                 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
 2451         }
 2452 
 2453         untimeout(wi_inquire, sc, sc->wi_stat_ch);
 2454 
 2455         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
 2456 
 2457         WI_UNLOCK(sc, s);
 2458         return;
 2459 }
 2460 
 2461 static void
 2462 wi_watchdog(ifp)
 2463         struct ifnet            *ifp;
 2464 {
 2465         struct wi_softc         *sc;
 2466 
 2467         sc = ifp->if_softc;
 2468 
 2469         device_printf(sc->dev, "watchdog timeout\n");
 2470 
 2471         wi_init(sc);
 2472 
 2473         ifp->if_oerrors++;
 2474 
 2475         return;
 2476 }
 2477 
 2478 int
 2479 wi_alloc(dev, rid)
 2480         device_t                dev;
 2481         int                     rid;
 2482 {
 2483         struct wi_softc         *sc = device_get_softc(dev);
 2484 
 2485         if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
 2486                 sc->iobase_rid = rid;
 2487                 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
 2488                     &sc->iobase_rid, 0, ~0, (1 << 6),
 2489                     rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
 2490                 if (!sc->iobase) {
 2491                         device_printf(dev, "No I/O space?!\n");
 2492                         return (ENXIO);
 2493                 }
 2494 
 2495                 sc->wi_io_addr = rman_get_start(sc->iobase);
 2496                 sc->wi_btag = rman_get_bustag(sc->iobase);
 2497                 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
 2498         } else {
 2499                 sc->mem_rid = rid;
 2500                 sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY,
 2501                     &sc->mem_rid, 0, ~0, 1, RF_ACTIVE);
 2502 
 2503                 if (!sc->mem) {
 2504                         device_printf(dev, "No Mem space on prism2.5?\n");
 2505                         return (ENXIO);
 2506                 }
 2507 
 2508                 sc->wi_btag = rman_get_bustag(sc->mem);
 2509                 sc->wi_bhandle = rman_get_bushandle(sc->mem);
 2510         }
 2511 
 2512 
 2513         sc->irq_rid = 0;
 2514         sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
 2515             0, ~0, 1, RF_ACTIVE |
 2516             ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
 2517 
 2518         if (!sc->irq) {
 2519                 wi_free(dev);
 2520                 device_printf(dev, "No irq?!\n");
 2521                 return (ENXIO);
 2522         }
 2523 
 2524         sc->dev = dev;
 2525         sc->wi_unit = device_get_unit(dev);
 2526 
 2527         return (0);
 2528 }
 2529 
 2530 void
 2531 wi_free(dev)
 2532         device_t                dev;
 2533 {
 2534         struct wi_softc         *sc = device_get_softc(dev);
 2535 
 2536         if (sc->wi_intrhand != NULL) {
 2537                 bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
 2538                 sc->wi_intrhand = NULL;
 2539         }
 2540         if (sc->iobase != NULL) {
 2541                 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
 2542                 sc->iobase = NULL;
 2543         }
 2544         if (sc->irq != NULL) {
 2545                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
 2546                 sc->irq = NULL;
 2547         }
 2548         if (sc->mem != NULL) {
 2549                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
 2550                 sc->mem = NULL;
 2551         }
 2552 
 2553         return;
 2554 }
 2555 
 2556 void
 2557 wi_shutdown(dev)
 2558         device_t                dev;
 2559 {
 2560         struct wi_softc         *sc;
 2561 
 2562         sc = device_get_softc(dev);
 2563         wi_stop(sc);
 2564 
 2565         return;
 2566 }
 2567 
 2568 #ifdef WICACHE
 2569 /* wavelan signal strength cache code.
 2570  * store signal/noise/quality on per MAC src basis in
 2571  * a small fixed cache.  The cache wraps if > MAX slots
 2572  * used.  The cache may be zeroed out to start over.
 2573  * Two simple filters exist to reduce computation:
 2574  * 1. ip only (literally 0x800) which may be used
 2575  * to ignore some packets.  It defaults to ip only.
 2576  * it could be used to focus on broadcast, non-IP 802.11 beacons.
 2577  * 2. multicast/broadcast only.  This may be used to
 2578  * ignore unicast packets and only cache signal strength
 2579  * for multicast/broadcast packets (beacons); e.g., Mobile-IP
 2580  * beacons and not unicast traffic.
 2581  *
 2582  * The cache stores (MAC src(index), IP src (major clue), signal,
 2583  *      quality, noise)
 2584  *
 2585  * No apologies for storing IP src here.  It's easy and saves much
 2586  * trouble elsewhere.  The cache is assumed to be INET dependent, 
 2587  * although it need not be.
 2588  */
 2589 
 2590 #ifdef documentation
 2591 
 2592 int wi_sigitems;                                /* number of cached entries */
 2593 struct wi_sigcache wi_sigcache[MAXWICACHE];  /*  array of cache entries */
 2594 int wi_nextitem;                                /*  index/# of entries */
 2595 
 2596 
 2597 #endif
 2598 
 2599 /* control variables for cache filtering.  Basic idea is
 2600  * to reduce cost (e.g., to only Mobile-IP agent beacons
 2601  * which are broadcast or multicast).  Still you might
 2602  * want to measure signal strength with unicast ping packets
 2603  * on a pt. to pt. ant. setup.
 2604  */
 2605 /* set true if you want to limit cache items to broadcast/mcast 
 2606  * only packets (not unicast).  Useful for mobile-ip beacons which
 2607  * are broadcast/multicast at network layer.  Default is all packets
 2608  * so ping/unicast will work say with pt. to pt. antennae setup.
 2609  */
 2610 static int wi_cache_mcastonly = 0;
 2611 SYSCTL_INT(_machdep, OID_AUTO, wi_cache_mcastonly, CTLFLAG_RW, 
 2612         &wi_cache_mcastonly, 0, "");
 2613 
 2614 /* set true if you want to limit cache items to IP packets only
 2615 */
 2616 static int wi_cache_iponly = 1;
 2617 SYSCTL_INT(_machdep, OID_AUTO, wi_cache_iponly, CTLFLAG_RW, 
 2618         &wi_cache_iponly, 0, "");
 2619 
 2620 /*
 2621  * Original comments:
 2622  * -----------------
 2623  * wi_cache_store, per rx packet store signal
 2624  * strength in MAC (src) indexed cache.
 2625  *
 2626  * follows linux driver in how signal strength is computed.
 2627  * In ad hoc mode, we use the rx_quality field. 
 2628  * signal and noise are trimmed to fit in the range from 47..138.
 2629  * rx_quality field MSB is signal strength.
 2630  * rx_quality field LSB is noise.
 2631  * "quality" is (signal - noise) as is log value.
 2632  * note: quality CAN be negative.
 2633  * 
 2634  * In BSS mode, we use the RID for communication quality.
 2635  * TBD:  BSS mode is currently untested.
 2636  *
 2637  * Bill's comments:
 2638  * ---------------
 2639  * Actually, we use the rx_quality field all the time for both "ad-hoc"
 2640  * and BSS modes. Why? Because reading an RID is really, really expensive:
 2641  * there's a bunch of PIO operations that have to be done to read a record
 2642  * from the NIC, and reading the comms quality RID each time a packet is
 2643  * received can really hurt performance. We don't have to do this anyway:
 2644  * the comms quality field only reflects the values in the rx_quality field
 2645  * anyway. The comms quality RID is only meaningful in infrastructure mode,
 2646  * but the values it contains are updated based on the rx_quality from
 2647  * frames received from the access point.
 2648  *
 2649  * Also, according to Lucent, the signal strength and noise level values
 2650  * can be converted to dBms by subtracting 149, so I've modified the code
 2651  * to do that instead of the scaling it did originally.
 2652  */
 2653 static void
 2654 wi_cache_store(struct wi_softc *sc, struct ether_header *eh,
 2655                      struct mbuf *m, unsigned short rx_quality)
 2656 {
 2657         struct ip *ip = 0; 
 2658         int i;
 2659         static int cache_slot = 0;      /* use this cache entry */
 2660         static int wrapindex = 0;       /* next "free" cache entry */
 2661         int sig, noise;
 2662         int sawip=0;
 2663 
 2664         /* 
 2665          * filters:
 2666          * 1. ip only
 2667          * 2. configurable filter to throw out unicast packets,
 2668          * keep multicast only.
 2669          */
 2670  
 2671         if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
 2672                 sawip = 1;
 2673         }
 2674 
 2675         /* 
 2676          * filter for ip packets only 
 2677         */
 2678         if (wi_cache_iponly && !sawip) {
 2679                 return;
 2680         }
 2681 
 2682         /*
 2683          *  filter for broadcast/multicast only
 2684          */
 2685         if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
 2686                 return;
 2687         }
 2688 
 2689 #ifdef SIGDEBUG
 2690         printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
 2691             rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
 2692 #endif
 2693 
 2694         /*
 2695          *  find the ip header.  we want to store the ip_src
 2696          * address.  
 2697          */
 2698         if (sawip)
 2699                 ip = mtod(m, struct ip *);
 2700         
 2701         /*
 2702          * do a linear search for a matching MAC address 
 2703          * in the cache table
 2704          * . MAC address is 6 bytes,
 2705          * . var w_nextitem holds total number of entries already cached
 2706          */
 2707         for(i = 0; i < sc->wi_nextitem; i++) {
 2708                 if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc,  6 )) {
 2709                         /* 
 2710                          * Match!,
 2711                          * so we already have this entry,
 2712                          * update the data
 2713                          */
 2714                         break;  
 2715                 }
 2716         }
 2717 
 2718         /*
 2719          *  did we find a matching mac address?
 2720          * if yes, then overwrite a previously existing cache entry
 2721          */
 2722         if (i < sc->wi_nextitem )   {
 2723                 cache_slot = i; 
 2724         }
 2725         /*
 2726          * else, have a new address entry,so
 2727          * add this new entry,
 2728          * if table full, then we need to replace LRU entry
 2729          */
 2730         else    {                          
 2731 
 2732                 /* 
 2733                  * check for space in cache table 
 2734                  * note: wi_nextitem also holds number of entries
 2735                  * added in the cache table 
 2736                  */
 2737                 if ( sc->wi_nextitem < MAXWICACHE ) {
 2738                         cache_slot = sc->wi_nextitem;
 2739                         sc->wi_nextitem++;                 
 2740                         sc->wi_sigitems = sc->wi_nextitem;
 2741                 }
 2742                 /* no space found, so simply wrap with wrap index
 2743                  * and "zap" the next entry
 2744                  */
 2745                 else {
 2746                         if (wrapindex == MAXWICACHE) {
 2747                                 wrapindex = 0;
 2748                         }
 2749                         cache_slot = wrapindex++;
 2750                 }
 2751         }
 2752 
 2753         /* 
 2754          * invariant: cache_slot now points at some slot
 2755          * in cache.
 2756          */
 2757         if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
 2758                 log(LOG_ERR, "wi_cache_store, bad index: %d of "
 2759                     "[0..%d], gross cache error\n",
 2760                     cache_slot, MAXWICACHE);
 2761                 return;
 2762         }
 2763 
 2764         /*
 2765          *  store items in cache
 2766          *  .ip source address
 2767          *  .mac src
 2768          *  .signal, etc.
 2769          */
 2770         if (sawip)
 2771                 sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
 2772         bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc,  6);
 2773 
 2774         sig = (rx_quality >> 8) & 0xFF;
 2775         noise = rx_quality & 0xFF;
 2776         sc->wi_sigcache[cache_slot].signal = sig - 149;
 2777         sc->wi_sigcache[cache_slot].noise = noise - 149;
 2778         sc->wi_sigcache[cache_slot].quality = sig - noise;
 2779 
 2780         return;
 2781 }
 2782 #endif
 2783 
 2784 static int
 2785 wi_get_cur_ssid(sc, ssid, len)
 2786         struct wi_softc         *sc;
 2787         char                    *ssid;
 2788         int                     *len;
 2789 {
 2790         int                     error = 0;
 2791         struct wi_req           wreq;
 2792 
 2793         wreq.wi_len = WI_MAX_DATALEN;
 2794         switch (sc->wi_ptype) {
 2795         case WI_PORTTYPE_AP:
 2796                 *len = IEEE80211_NWID_LEN;
 2797                 bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
 2798                 break;
 2799         case WI_PORTTYPE_ADHOC:
 2800                 wreq.wi_type = WI_RID_CURRENT_SSID;
 2801                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2802                 if (error != 0)
 2803                         break;
 2804                 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
 2805                         error = EINVAL;
 2806                         break;
 2807                 }
 2808                 *len = wreq.wi_val[0];
 2809                 bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
 2810                 break;
 2811         case WI_PORTTYPE_BSS:
 2812                 wreq.wi_type = WI_RID_COMMQUAL;
 2813                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2814                 if (error != 0)
 2815                         break;
 2816                 if (wreq.wi_val[0] != 0) /* associated */ {
 2817                         wreq.wi_type = WI_RID_CURRENT_SSID;
 2818                         wreq.wi_len = WI_MAX_DATALEN;
 2819                         error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2820                         if (error != 0)
 2821                                 break;
 2822                         if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
 2823                                 error = EINVAL;
 2824                                 break;
 2825                         }
 2826                         *len = wreq.wi_val[0];
 2827                         bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
 2828                 } else {
 2829                         *len = IEEE80211_NWID_LEN;
 2830                         bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
 2831                 }
 2832                 break;
 2833         default:
 2834                 error = EINVAL;
 2835                 break;
 2836         }
 2837 
 2838         return error;
 2839 }
 2840 
 2841 static int
 2842 wi_media_change(ifp)
 2843         struct ifnet            *ifp;
 2844 {
 2845         struct wi_softc         *sc = ifp->if_softc;
 2846         int                     otype = sc->wi_ptype;
 2847         int                     orate = sc->wi_tx_rate;
 2848         int                     ocreate_ibss = sc->wi_create_ibss;
 2849 
 2850         if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
 2851             sc->sc_firmware_type != WI_INTERSIL)
 2852                 return (EINVAL);
 2853 
 2854         sc->wi_create_ibss = 0;
 2855 
 2856         switch (sc->ifmedia.ifm_cur->ifm_media & IFM_OMASK) {
 2857         case 0:
 2858                 sc->wi_ptype = WI_PORTTYPE_BSS;
 2859                 break;
 2860         case IFM_IEEE80211_ADHOC:
 2861                 sc->wi_ptype = WI_PORTTYPE_ADHOC;
 2862                 break;
 2863         case IFM_IEEE80211_HOSTAP:
 2864                 sc->wi_ptype = WI_PORTTYPE_AP;
 2865                 break;
 2866         case IFM_IEEE80211_IBSSMASTER:
 2867         case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
 2868                 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
 2869                         return (EINVAL);
 2870                 sc->wi_create_ibss = 1;
 2871                 /* FALLTHROUGH */
 2872         case IFM_IEEE80211_IBSS:
 2873                 sc->wi_ptype = WI_PORTTYPE_IBSS;
 2874                 break;
 2875         default:
 2876                 /* Invalid combination. */
 2877                 return (EINVAL);
 2878         }
 2879 
 2880         switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
 2881         case IFM_IEEE80211_DS1:
 2882                 sc->wi_tx_rate = 1;
 2883                 break;
 2884         case IFM_IEEE80211_DS2:
 2885                 sc->wi_tx_rate = 2;
 2886                 break;
 2887         case IFM_IEEE80211_DS5:
 2888                 sc->wi_tx_rate = 5;
 2889                 break;
 2890         case IFM_IEEE80211_DS11:
 2891                 sc->wi_tx_rate = 11;
 2892                 break;
 2893         case IFM_AUTO:
 2894                 sc->wi_tx_rate = 3;
 2895                 break;
 2896         }
 2897 
 2898         if (ocreate_ibss != sc->wi_create_ibss || otype != sc->wi_ptype ||
 2899             orate != sc->wi_tx_rate)
 2900                 wi_init(sc);
 2901 
 2902         return(0);
 2903 }
 2904 
 2905 static void
 2906 wi_media_status(ifp, imr)
 2907         struct ifnet            *ifp;
 2908         struct ifmediareq       *imr;
 2909 {
 2910         struct wi_req           wreq;
 2911         struct wi_softc         *sc = ifp->if_softc;
 2912 
 2913         if (sc->wi_tx_rate == 3) {
 2914                 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
 2915                 if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
 2916                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
 2917                 else if (sc->wi_ptype == WI_PORTTYPE_AP)
 2918                         imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 2919                 else if (sc->wi_ptype == WI_PORTTYPE_IBSS) {
 2920                         if (sc->wi_create_ibss)
 2921                                 imr->ifm_active |= IFM_IEEE80211_IBSSMASTER;
 2922                         else
 2923                                 imr->ifm_active |= IFM_IEEE80211_IBSS;
 2924                 }
 2925                 wreq.wi_type = WI_RID_CUR_TX_RATE;
 2926                 wreq.wi_len = WI_MAX_DATALEN;
 2927                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
 2928                         switch(wreq.wi_val[0]) {
 2929                         case 1:
 2930                                 imr->ifm_active |= IFM_IEEE80211_DS1;
 2931                                 break;
 2932                         case 2:
 2933                                 imr->ifm_active |= IFM_IEEE80211_DS2;
 2934                                 break;
 2935                         case 6:
 2936                                 imr->ifm_active |= IFM_IEEE80211_DS5;
 2937                                 break;
 2938                         case 11:
 2939                                 imr->ifm_active |= IFM_IEEE80211_DS11;
 2940                                 break;
 2941                                 }
 2942                 }
 2943         } else {
 2944                 imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
 2945         }
 2946 
 2947         imr->ifm_status = IFM_AVALID;
 2948         if (sc->wi_ptype == WI_PORTTYPE_ADHOC ||
 2949             sc->wi_ptype == WI_PORTTYPE_IBSS)
 2950                 /*
 2951                  * XXX: It would be nice if we could give some actually
 2952                  * useful status like whether we joined another IBSS or
 2953                  * created one ourselves.
 2954                  */
 2955                 imr->ifm_status |= IFM_ACTIVE;
 2956         else if (sc->wi_ptype == WI_PORTTYPE_AP)
 2957                 imr->ifm_status |= IFM_ACTIVE;
 2958         else {
 2959                 wreq.wi_type = WI_RID_COMMQUAL;
 2960                 wreq.wi_len = WI_MAX_DATALEN;
 2961                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
 2962                     wreq.wi_val[0] != 0)
 2963                         imr->ifm_status |= IFM_ACTIVE;
 2964         }
 2965 }
 2966 
 2967 static int
 2968 wi_get_debug(sc, wreq)
 2969         struct wi_softc         *sc;
 2970         struct wi_req           *wreq;
 2971 {
 2972         int                     error = 0;
 2973 
 2974         wreq->wi_len = 1;
 2975 
 2976         switch (wreq->wi_type) {
 2977         case WI_DEBUG_SLEEP:
 2978                 wreq->wi_len++;
 2979                 wreq->wi_val[0] = sc->wi_debug.wi_sleep;
 2980                 break;
 2981         case WI_DEBUG_DELAYSUPP:
 2982                 wreq->wi_len++;
 2983                 wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
 2984                 break;
 2985         case WI_DEBUG_TXSUPP:
 2986                 wreq->wi_len++;
 2987                 wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
 2988                 break;
 2989         case WI_DEBUG_MONITOR:
 2990                 wreq->wi_len++;
 2991                 wreq->wi_val[0] = sc->wi_debug.wi_monitor;
 2992                 break;
 2993         case WI_DEBUG_LEDTEST:
 2994                 wreq->wi_len += 3;
 2995                 wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
 2996                 wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
 2997                 wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
 2998                 break;
 2999         case WI_DEBUG_CONTTX:
 3000                 wreq->wi_len += 2;
 3001                 wreq->wi_val[0] = sc->wi_debug.wi_conttx;
 3002                 wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
 3003                 break;
 3004         case WI_DEBUG_CONTRX:
 3005                 wreq->wi_len++;
 3006                 wreq->wi_val[0] = sc->wi_debug.wi_contrx;
 3007                 break;
 3008         case WI_DEBUG_SIGSTATE:
 3009                 wreq->wi_len += 2;
 3010                 wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
 3011                 wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
 3012                 break;
 3013         case WI_DEBUG_CONFBITS:
 3014                 wreq->wi_len += 2;
 3015                 wreq->wi_val[0] = sc->wi_debug.wi_confbits;
 3016                 wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
 3017                 break;
 3018         default:
 3019                 error = EIO;
 3020                 break;
 3021         }
 3022 
 3023         return (error);
 3024 }
 3025 
 3026 static int
 3027 wi_set_debug(sc, wreq)
 3028         struct wi_softc         *sc;
 3029         struct wi_req           *wreq;
 3030 {
 3031         int                     error = 0;
 3032         u_int16_t               cmd, param0 = 0, param1 = 0;
 3033 
 3034         switch (wreq->wi_type) {
 3035         case WI_DEBUG_RESET:
 3036         case WI_DEBUG_INIT:
 3037         case WI_DEBUG_CALENABLE:
 3038                 break;
 3039         case WI_DEBUG_SLEEP:
 3040                 sc->wi_debug.wi_sleep = 1;
 3041                 break;
 3042         case WI_DEBUG_WAKE:
 3043                 sc->wi_debug.wi_sleep = 0;
 3044                 break;
 3045         case WI_DEBUG_CHAN:
 3046                 param0 = wreq->wi_val[0];
 3047                 break;
 3048         case WI_DEBUG_DELAYSUPP:
 3049                 sc->wi_debug.wi_delaysupp = 1;
 3050                 break;
 3051         case WI_DEBUG_TXSUPP:
 3052                 sc->wi_debug.wi_txsupp = 1;
 3053                 break;
 3054         case WI_DEBUG_MONITOR:
 3055                 sc->wi_debug.wi_monitor = 1;
 3056                 break;
 3057         case WI_DEBUG_LEDTEST:
 3058                 param0 = wreq->wi_val[0];
 3059                 param1 = wreq->wi_val[1];
 3060                 sc->wi_debug.wi_ledtest = 1;
 3061                 sc->wi_debug.wi_ledtest_param0 = param0;
 3062                 sc->wi_debug.wi_ledtest_param1 = param1;
 3063                 break;
 3064         case WI_DEBUG_CONTTX:
 3065                 param0 = wreq->wi_val[0];
 3066                 sc->wi_debug.wi_conttx = 1;
 3067                 sc->wi_debug.wi_conttx_param0 = param0;
 3068                 break;
 3069         case WI_DEBUG_STOPTEST:
 3070                 sc->wi_debug.wi_delaysupp = 0;
 3071                 sc->wi_debug.wi_txsupp = 0;
 3072                 sc->wi_debug.wi_monitor = 0;
 3073                 sc->wi_debug.wi_ledtest = 0;
 3074                 sc->wi_debug.wi_ledtest_param0 = 0;
 3075                 sc->wi_debug.wi_ledtest_param1 = 0;
 3076                 sc->wi_debug.wi_conttx = 0;
 3077                 sc->wi_debug.wi_conttx_param0 = 0;
 3078                 sc->wi_debug.wi_contrx = 0;
 3079                 sc->wi_debug.wi_sigstate = 0;
 3080                 sc->wi_debug.wi_sigstate_param0 = 0;
 3081                 break;
 3082         case WI_DEBUG_CONTRX:
 3083                 sc->wi_debug.wi_contrx = 1;
 3084                 break;
 3085         case WI_DEBUG_SIGSTATE:
 3086                 param0 = wreq->wi_val[0];
 3087                 sc->wi_debug.wi_sigstate = 1;
 3088                 sc->wi_debug.wi_sigstate_param0 = param0;
 3089                 break;
 3090         case WI_DEBUG_CONFBITS:
 3091                 param0 = wreq->wi_val[0];
 3092                 param1 = wreq->wi_val[1];
 3093                 sc->wi_debug.wi_confbits = param0;
 3094                 sc->wi_debug.wi_confbits_param0 = param1;
 3095                 break;
 3096         default:
 3097                 error = EIO;
 3098                 break;
 3099         }
 3100 
 3101         if (error)
 3102                 return (error);
 3103 
 3104         cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
 3105         error = wi_cmd(sc, cmd, param0, param1, 0);
 3106 
 3107         return (error);
 3108 }

Cache object: 1ad721e800cf351ba023c6895fd5ccb6


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