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


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

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

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

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

Cache object: 54c29770e1c317af18239bea9fb5f4b4


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