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/owi/if_owi.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 #include <sys/endian.h>
   65 #include <sys/sockio.h>
   66 #include <sys/mbuf.h>
   67 #include <sys/proc.h>
   68 #include <sys/kernel.h>
   69 #include <sys/socket.h>
   70 #include <sys/module.h>
   71 #include <sys/bus.h>
   72 #include <sys/random.h>
   73 #include <sys/syslog.h>
   74 #include <sys/sysctl.h>
   75 
   76 #include <machine/bus.h>
   77 #include <machine/resource.h>
   78 #include <machine/clock.h>
   79 #include <sys/rman.h>
   80 
   81 #include <net/if.h>
   82 #include <net/if_arp.h>
   83 #include <net/ethernet.h>
   84 #include <net/if_dl.h>
   85 #include <net/if_media.h>
   86 #include <net/if_types.h>
   87 #include <dev/owi/if_ieee80211.h>
   88 
   89 #include <netinet/in.h>
   90 #include <netinet/in_systm.h>
   91 #include <netinet/in_var.h>
   92 #include <netinet/ip.h>
   93 #include <netinet/if_ether.h>
   94 
   95 #include <net/bpf.h>
   96 
   97 #include <dev/wi/if_wavelan_ieee.h>
   98 #include <dev/owi/if_wivar.h>
   99 #include <dev/owi/if_wireg.h>
  100 
  101 #if !defined(lint)
  102 static const char rcsid[] =
  103   "$FreeBSD: releng/5.2/sys/dev/owi/if_owi.c 123387 2003-12-10 15:02:02Z bms $";
  104 #endif
  105 
  106 static void wi_intr(void *);
  107 static void wi_reset(struct wi_softc *);
  108 static int wi_ioctl(struct ifnet *, u_long, caddr_t);
  109 static void wi_init(void *);
  110 static void wi_start(struct ifnet *);
  111 static void wi_watchdog(struct ifnet *);
  112 static void wi_rxeof(struct wi_softc *);
  113 static void wi_txeof(struct wi_softc *, int);
  114 static void wi_update_stats(struct wi_softc *);
  115 static void wi_setmulti(struct wi_softc *);
  116 
  117 static int wi_cmd(struct wi_softc *, int, int, int, int);
  118 static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);
  119 static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *);
  120 static int wi_read_data(struct wi_softc *, int, int, caddr_t, int);
  121 static int wi_write_data(struct wi_softc *, int, int, caddr_t, int);
  122 static int wi_seek(struct wi_softc *, int, int, int);
  123 static int wi_alloc_nicmem(struct wi_softc *, int, int *);
  124 static void wi_inquire(void *);
  125 static void wi_setdef(struct wi_softc *, struct wi_req *);
  126 
  127 #ifdef WICACHE
  128 static
  129 void wi_cache_store(struct wi_softc *, struct ether_header *,
  130         struct mbuf *, unsigned short);
  131 #endif
  132 
  133 static int wi_get_cur_ssid(struct wi_softc *, char *, int *);
  134 static int wi_media_change(struct ifnet *);
  135 static void wi_media_status(struct ifnet *, struct ifmediareq *);
  136 
  137 devclass_t owi_devclass;
  138 
  139 struct wi_card_ident wi_card_ident[] = {
  140         /* CARD_ID                      CARD_NAME               FIRM_TYPE */
  141         { WI_NIC_LUCENT_ID,             WI_NIC_LUCENT_STR,      WI_LUCENT },
  142         { WI_NIC_SONY_ID,               WI_NIC_SONY_STR,        WI_LUCENT },
  143         { WI_NIC_LUCENT_EMB_ID,         WI_NIC_LUCENT_EMB_STR,  WI_LUCENT },
  144         { 0,    NULL,   0 },
  145 };
  146 
  147 int
  148 owi_generic_detach(dev)
  149         device_t                dev;
  150 {
  151         struct wi_softc         *sc;
  152         struct ifnet            *ifp;
  153         int                     s;
  154 
  155         sc = device_get_softc(dev);
  156         WI_LOCK(sc, s);
  157         ifp = &sc->arpcom.ac_if;
  158 
  159         if (sc->wi_gone) {
  160                 device_printf(dev, "already unloaded\n");
  161                 WI_UNLOCK(sc, s);
  162                 return(ENODEV);
  163         }
  164         sc->wi_gone = !bus_child_present(dev);
  165 
  166         owi_stop(sc);
  167 
  168         /* Delete all remaining media. */
  169         ifmedia_removeall(&sc->ifmedia);
  170 
  171         ether_ifdetach(ifp);
  172         bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
  173         owi_free(dev);
  174         sc->wi_gone = 1;
  175 
  176         WI_UNLOCK(sc, s);
  177         mtx_destroy(&sc->wi_mtx);
  178 
  179         return(0);
  180 }
  181 
  182 int
  183 owi_generic_attach(device_t dev)
  184 {
  185         struct wi_softc         *sc;
  186         struct wi_ltv_macaddr   mac;
  187         struct wi_ltv_gen       gen;
  188         struct ifnet            *ifp;
  189         int                     error;
  190         int                     s;
  191 
  192         /* XXX maybe we need the splimp stuff here XXX */
  193         sc = device_get_softc(dev);
  194         ifp = &sc->arpcom.ac_if;
  195 
  196         error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
  197             wi_intr, sc, &sc->wi_intrhand);
  198 
  199         if (error) {
  200                 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
  201                 owi_free(dev);
  202                 return (error);
  203         }
  204 
  205         mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  206             MTX_DEF | MTX_RECURSE);
  207         WI_LOCK(sc, s);
  208 
  209         /* Reset the NIC. */
  210         wi_reset(sc);
  211 
  212         /*
  213          * Read the station address.
  214          * And do it twice. I've seen PRISM-based cards that return
  215          * an error when trying to read it the first time, which causes
  216          * the probe to fail.
  217          */
  218         mac.wi_type = WI_RID_MAC_NODE;
  219         mac.wi_len = 4;
  220         wi_read_record(sc, (struct wi_ltv_gen *)&mac);
  221         if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) {
  222                 device_printf(dev, "mac read failed %d\n", error);
  223                 owi_free(dev);
  224                 return (error);
  225         }
  226         bcopy((char *)&mac.wi_mac_addr,
  227            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  228 
  229         device_printf(dev, "802.11 address: %6D\n", sc->arpcom.ac_enaddr, ":");
  230 
  231         owi_get_id(sc);
  232 
  233         if_initname(ifp, device_get_name(dev), sc->wi_unit);
  234         ifp->if_softc = sc;
  235         ifp->if_mtu = ETHERMTU;
  236         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  237         ifp->if_ioctl = wi_ioctl;
  238         ifp->if_output = ether_output;
  239         ifp->if_start = wi_start;
  240         ifp->if_watchdog = wi_watchdog;
  241         ifp->if_init = wi_init;
  242         ifp->if_baudrate = 10000000;
  243         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  244 
  245         bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
  246         bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
  247             sizeof(WI_DEFAULT_NODENAME) - 1);
  248 
  249         bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
  250         bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
  251             sizeof(WI_DEFAULT_NETNAME) - 1);
  252 
  253         bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
  254         bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
  255             sizeof(WI_DEFAULT_IBSS) - 1);
  256 
  257         sc->wi_portnum = WI_DEFAULT_PORT;
  258         sc->wi_ptype = WI_PORTTYPE_BSS;
  259         sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
  260         sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
  261         sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
  262         sc->wi_max_data_len = WI_DEFAULT_DATALEN;
  263         sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
  264         sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
  265         sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
  266         sc->wi_roaming = WI_DEFAULT_ROAMING;
  267         sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
  268         sc->wi_authmode = IEEE80211_AUTH_OPEN;
  269 
  270         /*
  271          * Read the default channel from the NIC. This may vary
  272          * depending on the country where the NIC was purchased, so
  273          * we can't hard-code a default and expect it to work for
  274          * everyone.
  275          */
  276         gen.wi_type = WI_RID_OWN_CHNL;
  277         gen.wi_len = 2;
  278         wi_read_record(sc, &gen);
  279         sc->wi_channel = gen.wi_val;
  280 
  281         /*
  282          * Set flags based on firmware version.
  283          */
  284         switch (sc->sc_firmware_type) {
  285         case WI_LUCENT:
  286                 sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
  287                 if (sc->sc_sta_firmware_ver >= 60000)
  288                         sc->wi_flags |= WI_FLAGS_HAS_MOR;
  289                 if (sc->sc_sta_firmware_ver >= 60006) {
  290                         sc->wi_flags |= WI_FLAGS_HAS_IBSS;
  291                         sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
  292                 }
  293                 sc->wi_ibss_port = htole16(1);
  294                 break;
  295         }
  296 
  297         /*
  298          * Find out if we support WEP on this card.
  299          */
  300         gen.wi_type = WI_RID_WEP_AVAIL;
  301         gen.wi_len = 2;
  302         wi_read_record(sc, &gen);
  303         sc->wi_has_wep = gen.wi_val;
  304 
  305         if (bootverbose)
  306                 device_printf(sc->dev, "owi_has_wep = %d\n", sc->wi_has_wep);
  307 
  308         /* 
  309          * Find supported rates.
  310          */
  311         gen.wi_type = WI_RID_DATA_RATES;
  312         gen.wi_len = 2;
  313         if (wi_read_record(sc, &gen))
  314                 sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
  315                     WI_SUPPRATES_5M | WI_SUPPRATES_11M;
  316         else
  317                 sc->wi_supprates = gen.wi_val;
  318 
  319         bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
  320 
  321         wi_init(sc);
  322         owi_stop(sc);
  323 
  324         ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);
  325 #define ADD(m, c)       ifmedia_add(&sc->ifmedia, (m), (c), NULL)
  326         if (sc->wi_supprates & WI_SUPPRATES_1M) {
  327                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
  328                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  329                     IFM_IEEE80211_ADHOC, 0), 0);
  330                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  331                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  332                             IFM_IEEE80211_IBSS, 0), 0);
  333                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  334                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  335                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  336         }
  337         if (sc->wi_supprates & WI_SUPPRATES_2M) {
  338                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
  339                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  340                     IFM_IEEE80211_ADHOC, 0), 0);
  341                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  342                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  343                             IFM_IEEE80211_IBSS, 0), 0);
  344                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  345                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  346                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  347         }
  348         if (sc->wi_supprates & WI_SUPPRATES_5M) {
  349                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
  350                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  351                     IFM_IEEE80211_ADHOC, 0), 0);
  352                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  353                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  354                             IFM_IEEE80211_IBSS, 0), 0);
  355                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  356                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  357                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  358         }
  359         if (sc->wi_supprates & WI_SUPPRATES_11M) {
  360                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
  361                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  362                     IFM_IEEE80211_ADHOC, 0), 0);
  363                 if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  364                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  365                             IFM_IEEE80211_IBSS, 0), 0);
  366                 if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  367                         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  368                             IFM_IEEE80211_IBSSMASTER, 0), 0);
  369                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
  370         }
  371         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
  372         if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
  373                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
  374                     0), 0);
  375         if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
  376                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
  377                     IFM_IEEE80211_IBSSMASTER, 0), 0);
  378         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
  379 #undef ADD
  380         ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
  381 
  382         /*
  383          * Call MI attach routine.
  384          */
  385         ether_ifattach(ifp, sc->arpcom.ac_enaddr);
  386         callout_handle_init(&sc->wi_stat_ch);
  387         WI_UNLOCK(sc, s);
  388 
  389         return(0);
  390 }
  391 
  392 void
  393 owi_get_id(sc)
  394         struct wi_softc *sc;
  395 {
  396         struct wi_ltv_ver       ver;
  397         struct wi_card_ident    *id;
  398 
  399         /* getting chip identity */
  400         memset(&ver, 0, sizeof(ver));
  401         ver.wi_type = WI_RID_CARD_ID;
  402         ver.wi_len = 5;
  403         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
  404         device_printf(sc->dev, "using ");
  405         sc->sc_firmware_type = WI_NOTYPE;
  406         for (id = wi_card_ident; id->card_name != NULL; id++) {
  407                 if (le16toh(ver.wi_ver[0]) == id->card_id) {
  408                         printf("%s", id->card_name);
  409                         sc->sc_firmware_type = id->firm_type;
  410                         break;
  411                 }
  412         }
  413         if (sc->sc_firmware_type == WI_NOTYPE) {
  414                 if ((le16toh(ver.wi_ver[0]) & 0x8000) == 0) {
  415                         printf("Unknown Lucent chip");
  416                         sc->sc_firmware_type = WI_LUCENT;
  417                 }
  418         }
  419 
  420         if (sc->sc_firmware_type != WI_LUCENT)
  421                 return;
  422 
  423         /* get station firmware version */
  424         memset(&ver, 0, sizeof(ver));
  425         ver.wi_type = WI_RID_STA_IDENTITY;
  426         ver.wi_len = 5;
  427         wi_read_record(sc, (struct wi_ltv_gen *)&ver);
  428         ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
  429         ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
  430         ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
  431         sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
  432             ver.wi_ver[3] * 100 + ver.wi_ver[1];
  433         printf("\n");
  434         device_printf(sc->dev, "Lucent Firmware: ");
  435 
  436         printf("Station %u.%02u.%02u\n",
  437             sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
  438             sc->sc_sta_firmware_ver % 100);
  439         return;
  440 }
  441 
  442 static void
  443 wi_rxeof(sc)
  444         struct wi_softc         *sc;
  445 {
  446         struct ifnet            *ifp;
  447         struct ether_header     *eh;
  448         struct mbuf             *m;
  449         int                     id;
  450         int                     s;
  451 
  452         WI_LOCK_ASSERT(sc);
  453 
  454         ifp = &sc->arpcom.ac_if;
  455 
  456         id = CSR_READ_2(sc, WI_RX_FID);
  457 
  458         /*
  459          * if we have the procframe flag set, disregard all this and just
  460          * read the data from the device.
  461          */
  462         if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
  463                 struct wi_frame         *rx_frame;
  464                 int                     datlen, hdrlen;
  465 
  466                 /* first allocate mbuf for packet storage */
  467                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  468                 if (m == NULL) {
  469                         ifp->if_ierrors++;
  470                         return;
  471                 }
  472                 MCLGET(m, M_DONTWAIT);
  473                 if (!(m->m_flags & M_EXT)) {
  474                         m_freem(m);
  475                         ifp->if_ierrors++;
  476                         return;
  477                 }
  478 
  479                 m->m_pkthdr.rcvif = ifp;
  480 
  481                 /* now read wi_frame first so we know how much data to read */
  482                 if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
  483                     sizeof(struct wi_frame))) {
  484                         m_freem(m);
  485                         ifp->if_ierrors++;
  486                         return;
  487                 }
  488 
  489                 rx_frame = mtod(m, struct wi_frame *);
  490 
  491                 switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
  492                 case 7:
  493                         switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) {
  494                         case WI_FTYPE_DATA:
  495                                 hdrlen = WI_DATA_HDRLEN;
  496                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  497                                 break;
  498                         case WI_FTYPE_MGMT:
  499                                 hdrlen = WI_MGMT_HDRLEN;
  500                                 datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  501                                 break;
  502                         case WI_FTYPE_CTL:
  503                                 /*
  504                                  * prism2 cards don't pass control packets
  505                                  * down properly or consistently, so we'll only
  506                                  * pass down the header.
  507                                  */
  508                                 hdrlen = WI_CTL_HDRLEN;
  509                                 datlen = 0;
  510                                 break;
  511                         default:
  512                                 device_printf(sc->dev, "received packet of "
  513                                     "unknown type on port 7\n");
  514                                 m_freem(m);
  515                                 ifp->if_ierrors++;
  516                                 return;
  517                         }
  518                         break;
  519                 case 0:
  520                         hdrlen = WI_DATA_HDRLEN;
  521                         datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
  522                         break;
  523                 default:
  524                         device_printf(sc->dev, "received packet on invalid "
  525                             "port (wi_status=0x%x)\n", rx_frame->wi_status);
  526                         m_freem(m);
  527                         ifp->if_ierrors++;
  528                         return;
  529                 }
  530 
  531                 if ((hdrlen + datlen + 2) > MCLBYTES) {
  532                         device_printf(sc->dev, "oversized packet received "
  533                             "(wi_dat_len=%d, wi_status=0x%x)\n",
  534                             datlen, rx_frame->wi_status);
  535                         m_freem(m);
  536                         ifp->if_ierrors++;
  537                         return;
  538                 }
  539 
  540                 if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
  541                     datlen + 2)) {
  542                         m_freem(m);
  543                         ifp->if_ierrors++;
  544                         return;
  545                 }
  546 
  547                 m->m_pkthdr.len = m->m_len = hdrlen + datlen;
  548 
  549                 ifp->if_ipackets++;
  550 
  551                 /* Handle BPF listeners. */
  552                 BPF_MTAP(ifp, m);
  553 
  554                 m_freem(m);
  555         } else {
  556                 struct wi_frame         rx_frame;
  557 
  558                 /* First read in the frame header */
  559                 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
  560                     sizeof(rx_frame))) {
  561                         ifp->if_ierrors++;
  562                         return;
  563                 }
  564 
  565                 if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
  566                         ifp->if_ierrors++;
  567                         return;
  568                 }
  569 
  570                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  571                 if (m == NULL) {
  572                         ifp->if_ierrors++;
  573                         return;
  574                 }
  575                 MCLGET(m, M_DONTWAIT);
  576                 if (!(m->m_flags & M_EXT)) {
  577                         m_freem(m);
  578                         ifp->if_ierrors++;
  579                         return;
  580                 }
  581 
  582                 eh = mtod(m, struct ether_header *);
  583                 m->m_pkthdr.rcvif = ifp;
  584 
  585                 if (rx_frame.wi_status == WI_STAT_1042 ||
  586                     rx_frame.wi_status == WI_STAT_TUNNEL ||
  587                     rx_frame.wi_status == WI_STAT_WMP_MSG) {
  588                         if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
  589                                 device_printf(sc->dev,
  590                                     "oversized packet received "
  591                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
  592                                     rx_frame.wi_dat_len, rx_frame.wi_status);
  593                                 m_freem(m);
  594                                 ifp->if_ierrors++;
  595                                 return;
  596                         }
  597                         m->m_pkthdr.len = m->m_len =
  598                             rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
  599 
  600 #if 0
  601                         bcopy((char *)&rx_frame.wi_addr1,
  602                             (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
  603                         if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {
  604                                 bcopy((char *)&rx_frame.wi_addr2,
  605                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  606                         } else {
  607                                 bcopy((char *)&rx_frame.wi_addr3,
  608                                     (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  609                         }
  610 #else
  611                         bcopy((char *)&rx_frame.wi_dst_addr,
  612                                 (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
  613                         bcopy((char *)&rx_frame.wi_src_addr,
  614                                 (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  615 #endif
  616 
  617                         bcopy((char *)&rx_frame.wi_type,
  618                             (char *)&eh->ether_type, ETHER_TYPE_LEN);
  619 
  620                         if (wi_read_data(sc, id, WI_802_11_OFFSET,
  621                             mtod(m, caddr_t) + sizeof(struct ether_header),
  622                             m->m_len + 2)) {
  623                                 m_freem(m);
  624                                 ifp->if_ierrors++;
  625                                 return;
  626                         }
  627                 } else {
  628                         if((rx_frame.wi_dat_len +
  629                             sizeof(struct ether_header)) > MCLBYTES) {
  630                                 device_printf(sc->dev,
  631                                     "oversized packet received "
  632                                     "(wi_dat_len=%d, wi_status=0x%x)\n",
  633                                     rx_frame.wi_dat_len, rx_frame.wi_status);
  634                                 m_freem(m);
  635                                 ifp->if_ierrors++;
  636                                 return;
  637                         }
  638                         m->m_pkthdr.len = m->m_len =
  639                             rx_frame.wi_dat_len + sizeof(struct ether_header);
  640 
  641                         if (wi_read_data(sc, id, WI_802_3_OFFSET,
  642                             mtod(m, caddr_t), m->m_len + 2)) {
  643                                 m_freem(m);
  644                                 ifp->if_ierrors++;
  645                                 return;
  646                         }
  647                 }
  648 
  649                 ifp->if_ipackets++;
  650 
  651                 /* Receive packet. */
  652 #ifdef WICACHE
  653                 wi_cache_store(sc, eh, m, rx_frame.wi_q_info);
  654 #endif  
  655                 WI_UNLOCK(sc, s);
  656                 (*ifp->if_input)(ifp, m);
  657                 WI_LOCK(sc, s);
  658         }
  659 }
  660 
  661 static void
  662 wi_txeof(sc, status)
  663         struct wi_softc         *sc;
  664         int                     status;
  665 {
  666         struct ifnet            *ifp;
  667 
  668         ifp = &sc->arpcom.ac_if;
  669 
  670         ifp->if_timer = 0;
  671         ifp->if_flags &= ~IFF_OACTIVE;
  672 
  673         if (status & WI_EV_TX_EXC)
  674                 ifp->if_oerrors++;
  675         else
  676                 ifp->if_opackets++;
  677 
  678         return;
  679 }
  680 
  681 static void
  682 wi_inquire(xsc)
  683         void                    *xsc;
  684 {
  685         struct wi_softc         *sc;
  686         struct ifnet            *ifp;
  687         int                     s;
  688 
  689         sc = xsc;
  690         ifp = &sc->arpcom.ac_if;
  691 
  692         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
  693 
  694         /* Don't do this while we're transmitting */
  695         if (ifp->if_flags & IFF_OACTIVE)
  696                 return;
  697 
  698         WI_LOCK(sc, s);
  699         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
  700         WI_UNLOCK(sc, s);
  701 
  702         return;
  703 }
  704 
  705 static void
  706 wi_update_stats(sc)
  707         struct wi_softc         *sc;
  708 {
  709         struct wi_ltv_gen       gen;
  710         u_int16_t               id;
  711         struct ifnet            *ifp;
  712         u_int32_t               *ptr;
  713         int                     len, i;
  714         u_int16_t               t;
  715 
  716         ifp = &sc->arpcom.ac_if;
  717 
  718         id = CSR_READ_2(sc, WI_INFO_FID);
  719 
  720         wi_read_data(sc, id, 0, (char *)&gen, 4);
  721 
  722         /*
  723          * if we just got our scan results, copy it over into the scan buffer
  724          * so we can return it to anyone that asks for it. (add a little
  725          * compatibility with the prism2 scanning mechanism)
  726          */
  727         if (gen.wi_type == WI_INFO_SCAN_RESULTS)
  728         {
  729                 sc->wi_scanbuf_len = gen.wi_len;
  730                 wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf,
  731                     sc->wi_scanbuf_len * 2);
  732 
  733                 return;
  734         }
  735         else if (gen.wi_type != WI_INFO_COUNTERS)
  736                 return;
  737 
  738         len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
  739                 gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
  740         ptr = (u_int32_t *)&sc->wi_stats;
  741 
  742         for (i = 0; i < len - 1; i++) {
  743                 t = CSR_READ_2(sc, WI_DATA1);
  744 #ifdef WI_HERMES_STATS_WAR
  745                 if (t > 0xF000)
  746                         t = ~t & 0xFFFF;
  747 #endif
  748                 ptr[i] += t;
  749         }
  750 
  751         ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
  752             sc->wi_stats.wi_tx_multi_retries +
  753             sc->wi_stats.wi_tx_retry_limit;
  754 
  755         return;
  756 }
  757 
  758 static void
  759 wi_intr(xsc)
  760         void            *xsc;
  761 {
  762         struct wi_softc         *sc = xsc;
  763         struct ifnet            *ifp;
  764         u_int16_t               status;
  765         int                     s;
  766 
  767         WI_LOCK(sc, s);
  768 
  769         ifp = &sc->arpcom.ac_if;
  770 
  771         if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) {
  772                 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
  773                 CSR_WRITE_2(sc, WI_INT_EN, 0);
  774                 WI_UNLOCK(sc, s);
  775                 return;
  776         }
  777 
  778         /* Disable interrupts. */
  779         CSR_WRITE_2(sc, WI_INT_EN, 0);
  780 
  781         status = CSR_READ_2(sc, WI_EVENT_STAT);
  782         CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
  783 
  784         if (status & WI_EV_RX) {
  785                 wi_rxeof(sc);
  786                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
  787         }
  788 
  789         if (status & WI_EV_TX) {
  790                 wi_txeof(sc, status);
  791                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
  792         }
  793 
  794         if (status & WI_EV_ALLOC) {
  795                 int                     id;
  796 
  797                 id = CSR_READ_2(sc, WI_ALLOC_FID);
  798                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
  799                 if (id == sc->wi_tx_data_id)
  800                         wi_txeof(sc, status);
  801         }
  802 
  803         if (status & WI_EV_INFO) {
  804                 wi_update_stats(sc);
  805                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
  806         }
  807 
  808         if (status & WI_EV_TX_EXC) {
  809                 wi_txeof(sc, status);
  810                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
  811         }
  812 
  813         if (status & WI_EV_INFO_DROP) {
  814                 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
  815         }
  816 
  817         /* Re-enable interrupts. */
  818         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
  819 
  820         if (ifp->if_snd.ifq_head != NULL) {
  821                 wi_start(ifp);
  822         }
  823 
  824         WI_UNLOCK(sc, s);
  825 
  826         return;
  827 }
  828 
  829 static int
  830 wi_cmd(sc, cmd, val0, val1, val2)
  831         struct wi_softc         *sc;
  832         int                     cmd;
  833         int                     val0;
  834         int                     val1;
  835         int                     val2;
  836 {
  837         int                     i, s = 0;
  838         static volatile int count  = 0;
  839         
  840         if (count > 1)
  841                 panic("Hey partner, hold on there!");
  842         count++;
  843 
  844         /* wait for the busy bit to clear */
  845         for (i = 500; i > 0; i--) {     /* 5s */
  846                 if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
  847                         break;
  848                 }
  849                 DELAY(10*1000); /* 10 m sec */
  850         }
  851         if (i == 0) {
  852                 device_printf(sc->dev, "owi_cmd: busy bit won't clear.\n" );
  853                 count--;
  854                 return(ETIMEDOUT);
  855         }
  856 
  857         CSR_WRITE_2(sc, WI_PARAM0, val0);
  858         CSR_WRITE_2(sc, WI_PARAM1, val1);
  859         CSR_WRITE_2(sc, WI_PARAM2, val2);
  860         CSR_WRITE_2(sc, WI_COMMAND, cmd);
  861 
  862         for (i = 0; i < WI_TIMEOUT; i++) {
  863                 /*
  864                  * Wait for 'command complete' bit to be
  865                  * set in the event status register.
  866                  */
  867                 s = CSR_READ_2(sc, WI_EVENT_STAT);
  868                 if (s & WI_EV_CMD) {
  869                         /* Ack the event and read result code. */
  870                         s = CSR_READ_2(sc, WI_STATUS);
  871                         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
  872 #ifdef foo
  873                         if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
  874                                 return(EIO);
  875 #endif
  876                         if (s & WI_STAT_CMD_RESULT) {
  877                                 count--;
  878                                 return(EIO);
  879                         }
  880                         break;
  881                 }
  882                 DELAY(WI_DELAY);
  883         }
  884 
  885         count--;
  886         if (i == WI_TIMEOUT) {
  887                 device_printf(sc->dev,
  888                     "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
  889                 return(ETIMEDOUT);
  890         }
  891         return(0);
  892 }
  893 
  894 static void
  895 wi_reset(sc)
  896         struct wi_softc         *sc;
  897 {
  898 #define WI_INIT_TRIES 3
  899         int i;
  900         int tries;
  901         
  902         tries = WI_INIT_TRIES;
  903         for (i = 0; i < tries; i++) {
  904                 if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0)
  905                         break;
  906                 DELAY(WI_DELAY * 1000);
  907         }
  908         sc->sc_enabled = 1;
  909 
  910         if (i == tries) {
  911                 device_printf(sc->dev, "init failed\n");
  912                 return;
  913         }
  914 
  915         CSR_WRITE_2(sc, WI_INT_EN, 0);
  916         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
  917 
  918         /* Calibrate timer. */
  919         WI_SETVAL(WI_RID_TICK_TIME, 8);
  920 
  921         return;
  922 }
  923 
  924 /*
  925  * Read an LTV record from the NIC.
  926  */
  927 static int
  928 wi_read_record(sc, ltv)
  929         struct wi_softc         *sc;
  930         struct wi_ltv_gen       *ltv;
  931 {
  932         u_int16_t               *ptr;
  933         int                     i, len, code;
  934         struct wi_ltv_gen       *oltv;
  935 
  936         oltv = ltv;
  937 
  938         /* Tell the NIC to enter record read mode. */
  939         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
  940                 return(EIO);
  941 
  942         /* Seek to the record. */
  943         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
  944                 return(EIO);
  945 
  946         /*
  947          * Read the length and record type and make sure they
  948          * match what we expect (this verifies that we have enough
  949          * room to hold all of the returned data).
  950          */
  951         len = CSR_READ_2(sc, WI_DATA1);
  952         if (len > ltv->wi_len)
  953                 return(ENOSPC);
  954         code = CSR_READ_2(sc, WI_DATA1);
  955         if (code != ltv->wi_type)
  956                 return(EIO);
  957 
  958         ltv->wi_len = len;
  959         ltv->wi_type = code;
  960 
  961         /* Now read the data. */
  962         ptr = &ltv->wi_val;
  963         for (i = 0; i < ltv->wi_len - 1; i++)
  964                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
  965 
  966         if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
  967             && ltv->wi_val == sc->wi_ibss_port) {
  968                 /*
  969                  * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
  970                  * Since Lucent uses port type 1 for BSS *and* IBSS we
  971                  * have to rely on wi_ptype to distinguish this for us.
  972                  */
  973                 ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
  974         }
  975 
  976         return(0);
  977 }
  978 
  979 /*
  980  * Same as read, except we inject data instead of reading it.
  981  */
  982 static int
  983 wi_write_record(sc, ltv)
  984         struct wi_softc         *sc;
  985         struct wi_ltv_gen       *ltv;
  986 {
  987         uint16_t                *ptr;
  988         int                     i;
  989         struct wi_ltv_gen       p2ltv;
  990 
  991         if (ltv->wi_type == WI_RID_PORTTYPE &&
  992             le16toh(ltv->wi_val) == WI_PORTTYPE_IBSS) {
  993                 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
  994                 p2ltv.wi_type = WI_RID_PORTTYPE;
  995                 p2ltv.wi_len = 2;
  996                 p2ltv.wi_val = sc->wi_ibss_port;
  997                 ltv = &p2ltv;
  998         } else {
  999                 /* LUCENT */
 1000                 switch (ltv->wi_type) {  
 1001                 case WI_RID_TX_RATE:
 1002                         switch (ltv->wi_val) {
 1003                         case 1: ltv->wi_val = 1; break;  /* 1Mb/s fixed */
 1004                         case 2: ltv->wi_val = 2; break;  /* 2Mb/s fixed */
 1005                         case 3: ltv->wi_val = 3; break;  /* 11Mb/s auto */
 1006                         case 5: ltv->wi_val = 4; break;  /* 5.5Mb/s fixed */
 1007                         case 6: ltv->wi_val = 6; break;  /* 2Mb/s auto */
 1008                         case 7: ltv->wi_val = 7; break;  /* 5.5Mb/s auto */
 1009                         case 11: ltv->wi_val = 5; break; /* 11Mb/s fixed */
 1010                         default: return EINVAL;
 1011                         }
 1012                 case WI_RID_TX_CRYPT_KEY:
 1013                         if (ltv->wi_val > WI_NLTV_KEYS)
 1014                                 return (EINVAL);
 1015                         break;
 1016                 }
 1017         }
 1018 
 1019         if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
 1020                 return(EIO);
 1021 
 1022         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
 1023         CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
 1024 
 1025         ptr = &ltv->wi_val;
 1026         for (i = 0; i < ltv->wi_len - 1; i++)
 1027                 CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
 1028 
 1029         if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
 1030                 return(EIO);
 1031 
 1032         return(0);
 1033 }
 1034 
 1035 static int
 1036 wi_seek(sc, id, off, chan)
 1037         struct wi_softc         *sc;
 1038         int                     id, off, chan;
 1039 {
 1040         int                     i;
 1041         int                     selreg, offreg;
 1042         int                     status;
 1043 
 1044         switch (chan) {
 1045         case WI_BAP0:
 1046                 selreg = WI_SEL0;
 1047                 offreg = WI_OFF0;
 1048                 break;
 1049         case WI_BAP1:
 1050                 selreg = WI_SEL1;
 1051                 offreg = WI_OFF1;
 1052                 break;
 1053         default:
 1054                 device_printf(sc->dev, "invalid data path: %x\n", chan);
 1055                 return(EIO);
 1056         }
 1057 
 1058         CSR_WRITE_2(sc, selreg, id);
 1059         CSR_WRITE_2(sc, offreg, off);
 1060 
 1061         for (i = 0; i < WI_TIMEOUT; i++) {
 1062                 status = CSR_READ_2(sc, offreg);
 1063                 if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
 1064                         break;
 1065                 DELAY(WI_DELAY);
 1066         }
 1067 
 1068         if (i == WI_TIMEOUT) {
 1069                 device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n",
 1070                         id, off, status);
 1071                 return(ETIMEDOUT);
 1072         }
 1073 
 1074         return(0);
 1075 }
 1076 
 1077 static int
 1078 wi_read_data(sc, id, off, buf, len)
 1079         struct wi_softc         *sc;
 1080         int                     id, off;
 1081         caddr_t                 buf;
 1082         int                     len;
 1083 {
 1084         int                     i;
 1085         u_int16_t               *ptr;
 1086 
 1087         if (wi_seek(sc, id, off, WI_BAP1))
 1088                 return(EIO);
 1089 
 1090         ptr = (u_int16_t *)buf;
 1091         for (i = 0; i < len / 2; i++)
 1092                 ptr[i] = CSR_READ_2(sc, WI_DATA1);
 1093 
 1094         return(0);
 1095 }
 1096 
 1097 /*
 1098  * According to the comments in the HCF Light code, there is a bug in
 1099  * the Hermes (or possibly in certain Hermes firmware revisions) where
 1100  * the chip's internal autoincrement counter gets thrown off during
 1101  * data writes: the autoincrement is missed, causing one data word to
 1102  * be overwritten and subsequent words to be written to the wrong memory
 1103  * locations. The end result is that we could end up transmitting bogus
 1104  * frames without realizing it. The workaround for this is to write a
 1105  * couple of extra guard words after the end of the transfer, then
 1106  * attempt to read then back. If we fail to locate the guard words where
 1107  * we expect them, we preform the transfer over again.
 1108  */
 1109 static int
 1110 wi_write_data(sc, id, off, buf, len)
 1111         struct wi_softc         *sc;
 1112         int                     id, off;
 1113         caddr_t                 buf;
 1114         int                     len;
 1115 {
 1116         int                     i;
 1117         u_int16_t               *ptr;
 1118 #ifdef WI_HERMES_AUTOINC_WAR
 1119         int                     retries;
 1120 
 1121         retries = 512;
 1122 again:
 1123 #endif
 1124 
 1125         if (wi_seek(sc, id, off, WI_BAP0))
 1126                 return(EIO);
 1127 
 1128         ptr = (u_int16_t *)buf;
 1129         for (i = 0; i < (len / 2); i++)
 1130                 CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
 1131 
 1132 #ifdef WI_HERMES_AUTOINC_WAR
 1133         CSR_WRITE_2(sc, WI_DATA0, 0x1234);
 1134         CSR_WRITE_2(sc, WI_DATA0, 0x5678);
 1135 
 1136         if (wi_seek(sc, id, off + len, WI_BAP0))
 1137                 return(EIO);
 1138 
 1139         if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
 1140             CSR_READ_2(sc, WI_DATA0) != 0x5678) {
 1141                 if (--retries >= 0)
 1142                         goto again;
 1143                 device_printf(sc->dev, "owi_write_data device timeout\n");
 1144                 return (EIO);
 1145         }
 1146 #endif
 1147 
 1148         return(0);
 1149 }
 1150 
 1151 /*
 1152  * Allocate a region of memory inside the NIC and zero
 1153  * it out.
 1154  */
 1155 static int
 1156 wi_alloc_nicmem(sc, len, id)
 1157         struct wi_softc         *sc;
 1158         int                     len;
 1159         int                     *id;
 1160 {
 1161         int                     i;
 1162 
 1163         if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
 1164                 device_printf(sc->dev,
 1165                     "failed to allocate %d bytes on NIC\n", len);
 1166                 return(ENOMEM);
 1167         }
 1168 
 1169         for (i = 0; i < WI_TIMEOUT; i++) {
 1170                 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
 1171                         break;
 1172                 DELAY(WI_DELAY);
 1173         }
 1174 
 1175         if (i == WI_TIMEOUT) {
 1176                 device_printf(sc->dev, "time out allocating memory on card\n");
 1177                 return(ETIMEDOUT);
 1178         }
 1179 
 1180         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
 1181         *id = CSR_READ_2(sc, WI_ALLOC_FID);
 1182 
 1183         if (wi_seek(sc, *id, 0, WI_BAP0)) {
 1184                 device_printf(sc->dev, "seek failed while allocating memory on card\n");
 1185                 return(EIO);
 1186         }
 1187 
 1188         for (i = 0; i < len / 2; i++)
 1189                 CSR_WRITE_2(sc, WI_DATA0, 0);
 1190 
 1191         return(0);
 1192 }
 1193 
 1194 static void
 1195 wi_setmulti(sc)
 1196         struct wi_softc         *sc;
 1197 {
 1198         struct ifnet            *ifp;
 1199         int                     i = 0;
 1200         struct ifmultiaddr      *ifma;
 1201         struct wi_ltv_mcast     mcast;
 1202 
 1203         ifp = &sc->arpcom.ac_if;
 1204 
 1205         bzero((char *)&mcast, sizeof(mcast));
 1206 
 1207         mcast.wi_type = WI_RID_MCAST_LIST;
 1208         mcast.wi_len = (3 * 16) + 1;
 1209 
 1210         if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
 1211                 wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
 1212                 return;
 1213         }
 1214 
 1215         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1216                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1217                         continue;
 1218                 if (i < 16) {
 1219                         bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
 1220                             (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
 1221                         i++;
 1222                 } else {
 1223                         bzero((char *)&mcast, sizeof(mcast));
 1224                         break;
 1225                 }
 1226         }
 1227 
 1228         mcast.wi_len = (i * 3) + 1;
 1229         wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
 1230 
 1231         return;
 1232 }
 1233 
 1234 static void
 1235 wi_setdef(sc, wreq)
 1236         struct wi_softc         *sc;
 1237         struct wi_req           *wreq;
 1238 {
 1239         struct sockaddr_dl      *sdl;
 1240         struct ifaddr           *ifa;
 1241         struct ifnet            *ifp;
 1242 
 1243         ifp = &sc->arpcom.ac_if;
 1244 
 1245         switch(wreq->wi_type) {
 1246         case WI_RID_MAC_NODE:
 1247                 ifa = ifaddr_byindex(ifp->if_index);
 1248                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 1249                 bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
 1250                    ETHER_ADDR_LEN);
 1251                 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
 1252                 break;
 1253         case WI_RID_PORTTYPE:
 1254                 sc->wi_ptype = le16toh(wreq->wi_val[0]);
 1255                 break;
 1256         case WI_RID_TX_RATE:
 1257                 sc->wi_tx_rate = le16toh(wreq->wi_val[0]);
 1258                 break;
 1259         case WI_RID_MAX_DATALEN:
 1260                 sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
 1261                 break;
 1262         case WI_RID_RTS_THRESH:
 1263                 sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
 1264                 break;
 1265         case WI_RID_SYSTEM_SCALE:
 1266                 sc->wi_ap_density = le16toh(wreq->wi_val[0]);
 1267                 break;
 1268         case WI_RID_CREATE_IBSS:
 1269                 sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
 1270                 break;
 1271         case WI_RID_OWN_CHNL:
 1272                 sc->wi_channel = le16toh(wreq->wi_val[0]);
 1273                 break;
 1274         case WI_RID_NODENAME:
 1275                 bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
 1276                 bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
 1277                 break;
 1278         case WI_RID_DESIRED_SSID:
 1279                 bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
 1280                 bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
 1281                 break;
 1282         case WI_RID_OWN_SSID:
 1283                 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
 1284                 bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
 1285                 break;
 1286         case WI_RID_PM_ENABLED:
 1287                 sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
 1288                 break;
 1289         case WI_RID_MICROWAVE_OVEN:
 1290                 sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
 1291                 break;
 1292         case WI_RID_MAX_SLEEP:
 1293                 sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
 1294                 break;
 1295         case WI_RID_CNFAUTHMODE:
 1296                 sc->wi_authtype = le16toh(wreq->wi_val[0]);
 1297                 break;
 1298         case WI_RID_ROAMING_MODE:
 1299                 sc->wi_roaming = le16toh(wreq->wi_val[0]);
 1300                 break;
 1301         case WI_RID_ENCRYPTION:
 1302                 sc->wi_use_wep = le16toh(wreq->wi_val[0]);
 1303                 break;
 1304         case WI_RID_TX_CRYPT_KEY:
 1305                 sc->wi_tx_key = le16toh(wreq->wi_val[0]);
 1306                 break;
 1307         case WI_RID_DEFLT_CRYPT_KEYS:
 1308                 bcopy((char *)wreq, (char *)&sc->wi_keys,
 1309                     sizeof(struct wi_ltv_keys));
 1310                 break;
 1311         default:
 1312                 break;
 1313         }
 1314 
 1315         /* Reinitialize WaveLAN. */
 1316         wi_init(sc);
 1317 
 1318         return;
 1319 }
 1320 
 1321 static int
 1322 wi_ioctl(ifp, command, data)
 1323         struct ifnet            *ifp;
 1324         u_long                  command;
 1325         caddr_t                 data;
 1326 {
 1327         int                     error = 0;
 1328         int                     len;
 1329         int                     s;
 1330         uint16_t                mif;
 1331         uint16_t                val;
 1332         u_int8_t                tmpkey[14];
 1333         char                    tmpssid[IEEE80211_NWID_LEN];
 1334         struct wi_softc         *sc;
 1335         struct wi_req           wreq;
 1336         struct ifreq            *ifr;
 1337         struct ieee80211req     *ireq;
 1338         struct thread           *td = curthread;
 1339 
 1340         sc = ifp->if_softc;
 1341         WI_LOCK(sc, s);
 1342         ifr = (struct ifreq *)data;
 1343         ireq = (struct ieee80211req *)data;
 1344 
 1345         if (sc->wi_gone) {
 1346                 error = ENODEV;
 1347                 goto out;
 1348         }
 1349 
 1350         switch(command) {
 1351         case SIOCSIFFLAGS:
 1352                 /*
 1353                  * Can't do promisc and hostap at the same time.  If all that's
 1354                  * changing is the promisc flag, try to short-circuit a call to
 1355                  * wi_init() by just setting PROMISC in the hardware.
 1356                  */
 1357                 if (ifp->if_flags & IFF_UP) {
 1358                         if (ifp->if_flags & IFF_RUNNING) {
 1359                                 if (ifp->if_flags & IFF_PROMISC &&
 1360                                     !(sc->wi_if_flags & IFF_PROMISC)) {
 1361                                         WI_SETVAL(WI_RID_PROMISC, 1);
 1362                                 } else if (!(ifp->if_flags & IFF_PROMISC) &&
 1363                                     sc->wi_if_flags & IFF_PROMISC) {
 1364                                         WI_SETVAL(WI_RID_PROMISC, 0);
 1365                                 } else {
 1366                                         wi_init(sc);
 1367                                 }
 1368                         } else {
 1369                                 wi_init(sc);
 1370                         }
 1371                 } else {
 1372                         if (ifp->if_flags & IFF_RUNNING) {
 1373                                 owi_stop(sc);
 1374                         }
 1375                 }
 1376                 sc->wi_if_flags = ifp->if_flags;
 1377                 error = 0;
 1378                 break;
 1379         case SIOCSIFMEDIA:
 1380         case SIOCGIFMEDIA:
 1381                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
 1382                 break;
 1383         case SIOCADDMULTI:
 1384         case SIOCDELMULTI:
 1385                 wi_setmulti(sc);
 1386                 error = 0;
 1387                 break;
 1388         case SIOCGWAVELAN:
 1389                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1390                 if (error)
 1391                         break;
 1392                 if (wreq.wi_len > WI_MAX_DATALEN) {
 1393                         error = EINVAL;
 1394                         break;
 1395                 }
 1396                 /* Don't show WEP keys to non-root users. */
 1397                 if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && suser(td))
 1398                         break;
 1399                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
 1400                         bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
 1401                             sizeof(sc->wi_stats));
 1402                         wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
 1403                 } else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
 1404                         bcopy((char *)&sc->wi_keys, (char *)&wreq,
 1405                             sizeof(struct wi_ltv_keys));
 1406                 }
 1407 #ifdef WICACHE
 1408                 else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
 1409                         error = suser(td);
 1410                         if (error)
 1411                                 break;
 1412                         sc->wi_sigitems = sc->wi_nextitem = 0;
 1413                 } else if (wreq.wi_type == WI_RID_READ_CACHE) {
 1414                         char *pt = (char *)&wreq.wi_val;
 1415                         bcopy((char *)&sc->wi_sigitems,
 1416                             (char *)pt, sizeof(int));
 1417                         pt += (sizeof (int));
 1418                         wreq.wi_len = sizeof(int) / 2;
 1419                         bcopy((char *)&sc->wi_sigcache, (char *)pt,
 1420                             sizeof(struct wi_sigcache) * sc->wi_sigitems);
 1421                         wreq.wi_len += ((sizeof(struct wi_sigcache) *
 1422                             sc->wi_sigitems) / 2) + 1;
 1423                 }
 1424 #endif
 1425                 else if (wreq.wi_type == WI_RID_PROCFRAME) {
 1426                         wreq.wi_len = 2;
 1427                         wreq.wi_val[0] = sc->wi_procframe;
 1428                 } else if (wreq.wi_type == WI_RID_SCAN_RES) {
 1429                         memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf,
 1430                             sc->wi_scanbuf_len * 2);
 1431                         wreq.wi_len = sc->wi_scanbuf_len;
 1432                 } else if (wreq.wi_type == WI_RID_MIF) {
 1433                         mif = wreq.wi_val[0];
 1434                         error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
 1435                         val = CSR_READ_2(sc, WI_RESP0);
 1436                         wreq.wi_len = 2;
 1437                         wreq.wi_val[0] = val;
 1438                 } else {
 1439                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
 1440                                 error = EINVAL;
 1441                                 break;
 1442                         }
 1443                 }
 1444                 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
 1445                 break;
 1446         case SIOCSWAVELAN:
 1447                 if ((error = suser(td)))
 1448                         goto out;
 1449                 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
 1450                 if (error)
 1451                         break;
 1452                 if (wreq.wi_len > WI_MAX_DATALEN) {
 1453                         error = EINVAL;
 1454                         break;
 1455                 }
 1456                 if (wreq.wi_type == WI_RID_IFACE_STATS) {
 1457                         error = EINVAL;
 1458                         break;
 1459                 } else if (wreq.wi_type == WI_RID_PROCFRAME) {
 1460                         sc->wi_procframe = wreq.wi_val[0];
 1461                 /*
 1462                  * if we're getting a scan request from a wavelan card
 1463                  * (non-prism2), send out a cmd_inquire to the card to scan
 1464                  * results for the scan will be received through the info
 1465                  * interrupt handler. otherwise the scan request can be
 1466                  * directly handled by a prism2 card's rid interface.
 1467                  */
 1468                 } else if (wreq.wi_type == WI_RID_SCAN_REQ) {
 1469                         wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
 1470                 } else if (wreq.wi_type == WI_RID_MIF) {
 1471                         mif = wreq.wi_val[0];
 1472                         val = wreq.wi_val[1];
 1473                         error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
 1474                 } else {
 1475                         error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
 1476                         if (!error)
 1477                                 wi_setdef(sc, &wreq);
 1478                 }
 1479                 break;
 1480         case SIOCG80211:
 1481                 switch(ireq->i_type) {
 1482                 case IEEE80211_IOC_SSID:
 1483                         if(ireq->i_val == -1) {
 1484                                 bzero(tmpssid, IEEE80211_NWID_LEN);
 1485                                 error = wi_get_cur_ssid(sc, tmpssid, &len);
 1486                                 if (error != 0)
 1487                                         break;
 1488                                 error = copyout(tmpssid, ireq->i_data,
 1489                                         IEEE80211_NWID_LEN);
 1490                                 ireq->i_len = len;
 1491                         } else if (ireq->i_val == 0) {
 1492                                 error = copyout(sc->wi_net_name,
 1493                                     ireq->i_data,
 1494                                     IEEE80211_NWID_LEN);
 1495                                 ireq->i_len = IEEE80211_NWID_LEN;
 1496                         } else
 1497                                 error = EINVAL;
 1498                         break;
 1499                 case IEEE80211_IOC_NUMSSIDS:
 1500                         ireq->i_val = 1;
 1501                         break;
 1502                 case IEEE80211_IOC_WEP:
 1503                         if(!sc->wi_has_wep) {
 1504                                 ireq->i_val = IEEE80211_WEP_NOSUP; 
 1505                         } else {
 1506                                 if(sc->wi_use_wep) {
 1507                                         ireq->i_val =
 1508                                             IEEE80211_WEP_MIXED;
 1509                                 } else {
 1510                                         ireq->i_val =
 1511                                             IEEE80211_WEP_OFF;
 1512                                 }
 1513                         }
 1514                         break;
 1515                 case IEEE80211_IOC_WEPKEY:
 1516                         if(!sc->wi_has_wep ||
 1517                             ireq->i_val < 0 || ireq->i_val > 3) {
 1518                                 error = EINVAL;
 1519                                 break;
 1520                         }
 1521                         len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen;
 1522                         if (suser(td))
 1523                                 bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
 1524                                     tmpkey, len);
 1525                         else
 1526                                 bzero(tmpkey, len);
 1527 
 1528                         ireq->i_len = len;
 1529                         error = copyout(tmpkey, ireq->i_data, len);
 1530 
 1531                         break;
 1532                 case IEEE80211_IOC_NUMWEPKEYS:
 1533                         if(!sc->wi_has_wep)
 1534                                 error = EINVAL;
 1535                         else
 1536                                 ireq->i_val = 4;
 1537                         break;
 1538                 case IEEE80211_IOC_WEPTXKEY:
 1539                         if(!sc->wi_has_wep)
 1540                                 error = EINVAL;
 1541                         else
 1542                                 ireq->i_val = sc->wi_tx_key;
 1543                         break;
 1544                 case IEEE80211_IOC_AUTHMODE:
 1545                         ireq->i_val = sc->wi_authmode;
 1546                         break;
 1547                 case IEEE80211_IOC_STATIONNAME:
 1548                         error = copyout(sc->wi_node_name,
 1549                             ireq->i_data, IEEE80211_NWID_LEN);
 1550                         ireq->i_len = IEEE80211_NWID_LEN;
 1551                         break;
 1552                 case IEEE80211_IOC_CHANNEL:
 1553                         wreq.wi_type = WI_RID_CURRENT_CHAN;
 1554                         wreq.wi_len = WI_MAX_DATALEN;
 1555                         if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
 1556                                 error = EINVAL;
 1557                         else {
 1558                                 ireq->i_val = wreq.wi_val[0];
 1559                         }
 1560                         break;
 1561                 case IEEE80211_IOC_POWERSAVE:
 1562                         if(sc->wi_pm_enabled)
 1563                                 ireq->i_val = IEEE80211_POWERSAVE_ON;
 1564                         else
 1565                                 ireq->i_val = IEEE80211_POWERSAVE_OFF;
 1566                         break;
 1567                 case IEEE80211_IOC_POWERSAVESLEEP:
 1568                         ireq->i_val = sc->wi_max_sleep;
 1569                         break;
 1570                 default:
 1571                         error = EINVAL;
 1572                 }
 1573                 break;
 1574         case SIOCS80211:
 1575                 if ((error = suser(td)))
 1576                         goto out;
 1577                 switch(ireq->i_type) {
 1578                 case IEEE80211_IOC_SSID:
 1579                         if (ireq->i_val != 0 ||
 1580                             ireq->i_len > IEEE80211_NWID_LEN) {
 1581                                 error = EINVAL;
 1582                                 break;
 1583                         }
 1584                         /* We set both of them */
 1585                         bzero(sc->wi_net_name, IEEE80211_NWID_LEN);
 1586                         error = copyin(ireq->i_data,
 1587                             sc->wi_net_name, ireq->i_len);
 1588                         bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN);
 1589                         break;
 1590                 case IEEE80211_IOC_WEP:
 1591                         /*
 1592                          * These cards only support one mode so
 1593                          * we just turn wep on what ever is
 1594                          * passed in if it's not OFF.
 1595                          */
 1596                         if (ireq->i_val == IEEE80211_WEP_OFF) {
 1597                                 sc->wi_use_wep = 0;
 1598                         } else {
 1599                                 sc->wi_use_wep = 1;
 1600                         }
 1601                         break;
 1602                 case IEEE80211_IOC_WEPKEY:
 1603                         if (ireq->i_val < 0 || ireq->i_val > 3 ||
 1604                                 ireq->i_len > 13) {
 1605                                 error = EINVAL;
 1606                                 break;
 1607                         } 
 1608                         bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13);
 1609                         error = copyin(ireq->i_data, 
 1610                             sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
 1611                             ireq->i_len);
 1612                         if(error)
 1613                                 break;
 1614                         sc->wi_keys.wi_keys[ireq->i_val].wi_keylen =
 1615                                     ireq->i_len;
 1616                         break;
 1617                 case IEEE80211_IOC_WEPTXKEY:
 1618                         if (ireq->i_val < 0 || ireq->i_val > 3) {
 1619                                 error = EINVAL;
 1620                                 break;
 1621                         }
 1622                         sc->wi_tx_key = ireq->i_val;
 1623                         break;
 1624                 case IEEE80211_IOC_AUTHMODE:
 1625                         sc->wi_authmode = ireq->i_val;
 1626                         break;
 1627                 case IEEE80211_IOC_STATIONNAME:
 1628                         if (ireq->i_len > 32) {
 1629                                 error = EINVAL;
 1630                                 break;
 1631                         }
 1632                         bzero(sc->wi_node_name, 32);
 1633                         error = copyin(ireq->i_data,
 1634                             sc->wi_node_name, ireq->i_len);
 1635                         break;
 1636                 case IEEE80211_IOC_CHANNEL:
 1637                         /*
 1638                          * The actual range is 1-14, but if you
 1639                          * set it to 0 you get the default. So
 1640                          * we let that work too.
 1641                          */
 1642                         if (ireq->i_val < 0 || ireq->i_val > 14) {
 1643                                 error = EINVAL;
 1644                                 break;
 1645                         }
 1646                         sc->wi_channel = ireq->i_val;
 1647                         break;
 1648                 case IEEE80211_IOC_POWERSAVE:
 1649                         switch (ireq->i_val) {
 1650                         case IEEE80211_POWERSAVE_OFF:
 1651                                 sc->wi_pm_enabled = 0;
 1652                                 break;
 1653                         case IEEE80211_POWERSAVE_ON:
 1654                                 sc->wi_pm_enabled = 1;
 1655                                 break;
 1656                         default:
 1657                                 error = EINVAL;
 1658                                 break;
 1659                         }
 1660                         break;
 1661                 case IEEE80211_IOC_POWERSAVESLEEP:
 1662                         if (ireq->i_val < 0) {
 1663                                 error = EINVAL;
 1664                                 break;
 1665                         }
 1666                         sc->wi_max_sleep = ireq->i_val;
 1667                         break;
 1668                 default:
 1669                         error = EINVAL;
 1670                         break;
 1671                 }
 1672 
 1673                 /* Reinitialize WaveLAN. */
 1674                 wi_init(sc);
 1675 
 1676         break;
 1677         default:
 1678                 error = ether_ioctl(ifp, command, data);
 1679                 break;
 1680         }
 1681 out:
 1682         WI_UNLOCK(sc, s);
 1683 
 1684         return(error);
 1685 }
 1686 
 1687 static void
 1688 wi_init(xsc)
 1689         void                    *xsc;
 1690 {
 1691         struct wi_softc         *sc = xsc;
 1692         struct ifnet            *ifp = &sc->arpcom.ac_if;
 1693         struct wi_ltv_macaddr   mac;
 1694         int                     id = 0;
 1695         int                     s;
 1696 
 1697         WI_LOCK(sc, s);
 1698 
 1699         if (sc->wi_gone) {
 1700                 WI_UNLOCK(sc, s);
 1701                 return;
 1702         }
 1703 
 1704         if (ifp->if_flags & IFF_RUNNING)
 1705                 owi_stop(sc);
 1706 
 1707         wi_reset(sc);
 1708 
 1709         /* Program max data length. */
 1710         WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
 1711 
 1712         /* Set the port type. */
 1713         WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
 1714 
 1715         /* Enable/disable IBSS creation. */
 1716         WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
 1717 
 1718         /* Program the RTS/CTS threshold. */
 1719         WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
 1720 
 1721         /* Program the TX rate */
 1722         WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
 1723 
 1724         /* Access point density */
 1725         WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
 1726 
 1727         /* Power Management Enabled */
 1728         WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
 1729 
 1730         /* Power Managment Max Sleep */
 1731         WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
 1732 
 1733         /* Roaming type */
 1734         WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
 1735 
 1736         /* Specify the IBSS name */
 1737         WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
 1738 
 1739         /* Specify the network name */
 1740         WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
 1741 
 1742         /* Specify the frequency to use */
 1743         WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
 1744 
 1745         /* Program the nodename. */
 1746         WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
 1747 
 1748         /* Specify the authentication mode. */
 1749         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authmode);
 1750 
 1751         /* Set our MAC address. */
 1752         mac.wi_len = 4;
 1753         mac.wi_type = WI_RID_MAC_NODE;
 1754         bcopy((char *)&sc->arpcom.ac_enaddr,
 1755            (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
 1756         wi_write_record(sc, (struct wi_ltv_gen *)&mac);
 1757 
 1758         /*
 1759          * Initialize promisc mode.
 1760          */
 1761         if (ifp->if_flags & IFF_PROMISC)
 1762                 WI_SETVAL(WI_RID_PROMISC, 1);
 1763         else
 1764                 WI_SETVAL(WI_RID_PROMISC, 0);
 1765 
 1766         /* Configure WEP. */
 1767         if (sc->wi_has_wep) {
 1768                 WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
 1769                 WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
 1770                 sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
 1771                 sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
 1772                 wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
 1773         }
 1774 
 1775         /* Set multicast filter. */
 1776         wi_setmulti(sc);
 1777 
 1778         /* Enable desired port */
 1779         wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
 1780 
 1781         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
 1782                 device_printf(sc->dev, "tx buffer allocation failed\n");
 1783         sc->wi_tx_data_id = id;
 1784 
 1785         if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
 1786                 device_printf(sc->dev, "mgmt. buffer allocation failed\n");
 1787         sc->wi_tx_mgmt_id = id;
 1788 
 1789         /* enable interrupts */
 1790         CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 1791 
 1792         ifp->if_flags |= IFF_RUNNING;
 1793         ifp->if_flags &= ~IFF_OACTIVE;
 1794 
 1795         sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
 1796         WI_UNLOCK(sc, s);
 1797 
 1798         return;
 1799 }
 1800 
 1801 static void
 1802 wi_start(ifp)
 1803         struct ifnet            *ifp;
 1804 {
 1805         struct wi_softc         *sc;
 1806         struct mbuf             *m0;
 1807         struct wi_frame         tx_frame;
 1808         struct ether_header     *eh;
 1809         int                     id;
 1810         int                     s;
 1811 
 1812         sc = ifp->if_softc;
 1813         WI_LOCK(sc, s);
 1814 
 1815         if (sc->wi_gone) {
 1816                 WI_UNLOCK(sc, s);
 1817                 return;
 1818         }
 1819 
 1820         if (ifp->if_flags & IFF_OACTIVE) {
 1821                 WI_UNLOCK(sc, s);
 1822                 return;
 1823         }
 1824 
 1825         IF_DEQUEUE(&ifp->if_snd, m0);
 1826         if (m0 == NULL) {
 1827                 WI_UNLOCK(sc, s);
 1828                 return;
 1829         }
 1830 
 1831         bzero((char *)&tx_frame, sizeof(tx_frame));
 1832         tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
 1833         id = sc->wi_tx_data_id;
 1834         eh = mtod(m0, struct ether_header *);
 1835 
 1836         /*
 1837          * Use RFC1042 encoding for IP and ARP datagrams,
 1838          * 802.3 for anything else.
 1839          */
 1840         if (ntohs(eh->ether_type) > ETHER_MAX_LEN) {
 1841                 bcopy((char *)&eh->ether_dhost,
 1842                     (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
 1843                 bcopy((char *)&eh->ether_shost,
 1844                     (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
 1845                 bcopy((char *)&eh->ether_dhost,
 1846                     (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
 1847                 bcopy((char *)&eh->ether_shost,
 1848                     (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
 1849 
 1850                 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
 1851                 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
 1852                 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
 1853                 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
 1854                 tx_frame.wi_type = eh->ether_type;
 1855 
 1856                 m_copydata(m0, sizeof(struct ether_header),
 1857                     m0->m_pkthdr.len - sizeof(struct ether_header),
 1858                     (caddr_t)&sc->wi_txbuf);
 1859                 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
 1860                     sizeof(struct wi_frame));
 1861                 wi_write_data(sc, id, WI_802_11_OFFSET,
 1862                     (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
 1863                         sizeof(struct ether_header)) + 2);
 1864         } else {
 1865                 tx_frame.wi_dat_len = m0->m_pkthdr.len;
 1866 
 1867                 eh->ether_type = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
 1868                 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf);
 1869                 wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
 1870                     sizeof(struct wi_frame));
 1871                 wi_write_data(sc, id, WI_802_3_OFFSET,
 1872                     (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
 1873         }
 1874 
 1875         /*
 1876          * If there's a BPF listner, bounce a copy of
 1877          * this frame to him. Also, don't send this to the bpf sniffer
 1878          * if we're in procframe or monitor sniffing mode.
 1879          */
 1880         if (!(sc->wi_procframe || sc->wi_debug.wi_monitor))
 1881                 BPF_MTAP(ifp, m0);
 1882 
 1883         m_freem(m0);
 1884 
 1885         if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
 1886                 device_printf(sc->dev, "xmit failed\n");
 1887 
 1888         ifp->if_flags |= IFF_OACTIVE;
 1889 
 1890         /*
 1891          * Set a timeout in case the chip goes out to lunch.
 1892          */
 1893         ifp->if_timer = 5;
 1894 
 1895         WI_UNLOCK(sc, s);
 1896         return;
 1897 }
 1898 
 1899 void
 1900 owi_stop(sc)
 1901         struct wi_softc         *sc;
 1902 {
 1903         struct ifnet            *ifp;
 1904         int                     s;
 1905 
 1906         WI_LOCK(sc, s);
 1907 
 1908         untimeout(wi_inquire, sc, sc->wi_stat_ch);
 1909 
 1910         if (sc->wi_gone) {
 1911                 WI_UNLOCK(sc, s);
 1912                 return;
 1913         }
 1914 
 1915         ifp = &sc->arpcom.ac_if;
 1916 
 1917         /*
 1918          * If the card is gone and the memory port isn't mapped, we will
 1919          * (hopefully) get 0xffff back from the status read, which is not
 1920          * a valid status value.
 1921          */
 1922         if (CSR_READ_2(sc, WI_STATUS) != 0xffff) {
 1923                 CSR_WRITE_2(sc, WI_INT_EN, 0);
 1924                 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
 1925         }
 1926 
 1927         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
 1928 
 1929         WI_UNLOCK(sc, s);
 1930         return;
 1931 }
 1932 
 1933 static void
 1934 wi_watchdog(ifp)
 1935         struct ifnet            *ifp;
 1936 {
 1937         struct wi_softc         *sc;
 1938 
 1939         sc = ifp->if_softc;
 1940 
 1941         device_printf(sc->dev, "watchdog timeout\n");
 1942 
 1943         wi_init(sc);
 1944 
 1945         ifp->if_oerrors++;
 1946 
 1947         return;
 1948 }
 1949 
 1950 int
 1951 owi_alloc(dev, rid)
 1952         device_t                dev;
 1953         int                     rid;
 1954 {
 1955         struct wi_softc         *sc = device_get_softc(dev);
 1956 
 1957         if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
 1958                 sc->iobase_rid = rid;
 1959                 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
 1960                     &sc->iobase_rid, 0, ~0, (1 << 6),
 1961                     rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
 1962                 if (!sc->iobase) {
 1963                         device_printf(dev, "No I/O space?!\n");
 1964                         return (ENXIO);
 1965                 }
 1966 
 1967                 sc->wi_io_addr = rman_get_start(sc->iobase);
 1968                 sc->wi_btag = rman_get_bustag(sc->iobase);
 1969                 sc->wi_bhandle = rman_get_bushandle(sc->iobase);
 1970         } else {
 1971                 sc->mem_rid = rid;
 1972                 sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY,
 1973                     &sc->mem_rid, 0, ~0, 1, RF_ACTIVE);
 1974 
 1975                 if (!sc->mem) {
 1976                         device_printf(dev, "No Mem space on prism2.5?\n");
 1977                         return (ENXIO);
 1978                 }
 1979 
 1980                 sc->wi_btag = rman_get_bustag(sc->mem);
 1981                 sc->wi_bhandle = rman_get_bushandle(sc->mem);
 1982         }
 1983 
 1984 
 1985         sc->irq_rid = 0;
 1986         sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
 1987             0, ~0, 1, RF_ACTIVE |
 1988             ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
 1989 
 1990         if (!sc->irq) {
 1991                 owi_free(dev);
 1992                 device_printf(dev, "No irq?!\n");
 1993                 return (ENXIO);
 1994         }
 1995 
 1996         sc->dev = dev;
 1997         sc->wi_unit = device_get_unit(dev);
 1998 
 1999         return (0);
 2000 }
 2001 
 2002 void
 2003 owi_free(dev)
 2004         device_t                dev;
 2005 {
 2006         struct wi_softc         *sc = device_get_softc(dev);
 2007 
 2008         if (sc->iobase != NULL) {
 2009                 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
 2010                 sc->iobase = NULL;
 2011         }
 2012         if (sc->irq != NULL) {
 2013                 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
 2014                 sc->irq = NULL;
 2015         }
 2016         if (sc->mem != NULL) {
 2017                 bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
 2018                 sc->mem = NULL;
 2019         }
 2020 
 2021         return;
 2022 }
 2023 
 2024 void
 2025 owi_shutdown(dev)
 2026         device_t                dev;
 2027 {
 2028         struct wi_softc         *sc;
 2029 
 2030         sc = device_get_softc(dev);
 2031         owi_stop(sc);
 2032 
 2033         return;
 2034 }
 2035 
 2036 #ifdef WICACHE
 2037 /* wavelan signal strength cache code.
 2038  * store signal/noise/quality on per MAC src basis in
 2039  * a small fixed cache.  The cache wraps if > MAX slots
 2040  * used.  The cache may be zeroed out to start over.
 2041  * Two simple filters exist to reduce computation:
 2042  * 1. ip only (literally 0x800) which may be used
 2043  * to ignore some packets.  It defaults to ip only.
 2044  * it could be used to focus on broadcast, non-IP 802.11 beacons.
 2045  * 2. multicast/broadcast only.  This may be used to
 2046  * ignore unicast packets and only cache signal strength
 2047  * for multicast/broadcast packets (beacons); e.g., Mobile-IP
 2048  * beacons and not unicast traffic.
 2049  *
 2050  * The cache stores (MAC src(index), IP src (major clue), signal,
 2051  *      quality, noise)
 2052  *
 2053  * No apologies for storing IP src here.  It's easy and saves much
 2054  * trouble elsewhere.  The cache is assumed to be INET dependent, 
 2055  * although it need not be.
 2056  */
 2057 
 2058 #ifdef documentation
 2059 
 2060 int wi_sigitems;                                /* number of cached entries */
 2061 struct wi_sigcache wi_sigcache[MAXWICACHE];  /*  array of cache entries */
 2062 int wi_nextitem;                                /*  index/# of entries */
 2063 
 2064 
 2065 #endif
 2066 
 2067 /* control variables for cache filtering.  Basic idea is
 2068  * to reduce cost (e.g., to only Mobile-IP agent beacons
 2069  * which are broadcast or multicast).  Still you might
 2070  * want to measure signal strength with unicast ping packets
 2071  * on a pt. to pt. ant. setup.
 2072  */
 2073 /* set true if you want to limit cache items to broadcast/mcast 
 2074  * only packets (not unicast).  Useful for mobile-ip beacons which
 2075  * are broadcast/multicast at network layer.  Default is all packets
 2076  * so ping/unicast will work say with pt. to pt. antennae setup.
 2077  */
 2078 static int wi_cache_mcastonly = 0;
 2079 SYSCTL_INT(_machdep, OID_AUTO, wi_cache_mcastonly, CTLFLAG_RW, 
 2080         &wi_cache_mcastonly, 0, "");
 2081 
 2082 /* set true if you want to limit cache items to IP packets only
 2083 */
 2084 static int wi_cache_iponly = 1;
 2085 SYSCTL_INT(_machdep, OID_AUTO, wi_cache_iponly, CTLFLAG_RW, 
 2086         &wi_cache_iponly, 0, "");
 2087 
 2088 /*
 2089  * Original comments:
 2090  * -----------------
 2091  * wi_cache_store, per rx packet store signal
 2092  * strength in MAC (src) indexed cache.
 2093  *
 2094  * follows linux driver in how signal strength is computed.
 2095  * In ad hoc mode, we use the rx_quality field. 
 2096  * signal and noise are trimmed to fit in the range from 47..138.
 2097  * rx_quality field MSB is signal strength.
 2098  * rx_quality field LSB is noise.
 2099  * "quality" is (signal - noise) as is log value.
 2100  * note: quality CAN be negative.
 2101  * 
 2102  * In BSS mode, we use the RID for communication quality.
 2103  * TBD:  BSS mode is currently untested.
 2104  *
 2105  * Bill's comments:
 2106  * ---------------
 2107  * Actually, we use the rx_quality field all the time for both "ad-hoc"
 2108  * and BSS modes. Why? Because reading an RID is really, really expensive:
 2109  * there's a bunch of PIO operations that have to be done to read a record
 2110  * from the NIC, and reading the comms quality RID each time a packet is
 2111  * received can really hurt performance. We don't have to do this anyway:
 2112  * the comms quality field only reflects the values in the rx_quality field
 2113  * anyway. The comms quality RID is only meaningful in infrastructure mode,
 2114  * but the values it contains are updated based on the rx_quality from
 2115  * frames received from the access point.
 2116  *
 2117  * Also, according to Lucent, the signal strength and noise level values
 2118  * can be converted to dBms by subtracting 149, so I've modified the code
 2119  * to do that instead of the scaling it did originally.
 2120  */
 2121 static void
 2122 wi_cache_store(struct wi_softc *sc, struct ether_header *eh,
 2123                      struct mbuf *m, unsigned short rx_quality)
 2124 {
 2125         struct ip *ip = 0; 
 2126         int i;
 2127         static int cache_slot = 0;      /* use this cache entry */
 2128         static int wrapindex = 0;       /* next "free" cache entry */
 2129         int sig, noise;
 2130         int sawip=0;
 2131 
 2132         /* 
 2133          * filters:
 2134          * 1. ip only
 2135          * 2. configurable filter to throw out unicast packets,
 2136          * keep multicast only.
 2137          */
 2138  
 2139         if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
 2140                 sawip = 1;
 2141         }
 2142 
 2143         /* 
 2144          * filter for ip packets only 
 2145         */
 2146         if (wi_cache_iponly && !sawip) {
 2147                 return;
 2148         }
 2149 
 2150         /*
 2151          *  filter for broadcast/multicast only
 2152          */
 2153         if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
 2154                 return;
 2155         }
 2156 
 2157 #ifdef SIGDEBUG
 2158         printf("owi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
 2159             rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
 2160 #endif
 2161 
 2162         /*
 2163          *  find the ip header.  we want to store the ip_src
 2164          * address.  
 2165          */
 2166         if (sawip)
 2167                 ip = mtod(m, struct ip *);
 2168         
 2169         /*
 2170          * do a linear search for a matching MAC address 
 2171          * in the cache table
 2172          * . MAC address is 6 bytes,
 2173          * . var w_nextitem holds total number of entries already cached
 2174          */
 2175         for(i = 0; i < sc->wi_nextitem; i++) {
 2176                 if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc,  6 )) {
 2177                         /* 
 2178                          * Match!,
 2179                          * so we already have this entry,
 2180                          * update the data
 2181                          */
 2182                         break;  
 2183                 }
 2184         }
 2185 
 2186         /*
 2187          *  did we find a matching mac address?
 2188          * if yes, then overwrite a previously existing cache entry
 2189          */
 2190         if (i < sc->wi_nextitem )   {
 2191                 cache_slot = i; 
 2192         }
 2193         /*
 2194          * else, have a new address entry,so
 2195          * add this new entry,
 2196          * if table full, then we need to replace LRU entry
 2197          */
 2198         else    {                          
 2199 
 2200                 /* 
 2201                  * check for space in cache table 
 2202                  * note: wi_nextitem also holds number of entries
 2203                  * added in the cache table 
 2204                  */
 2205                 if ( sc->wi_nextitem < MAXWICACHE ) {
 2206                         cache_slot = sc->wi_nextitem;
 2207                         sc->wi_nextitem++;                 
 2208                         sc->wi_sigitems = sc->wi_nextitem;
 2209                 }
 2210                 /* no space found, so simply wrap with wrap index
 2211                  * and "zap" the next entry
 2212                  */
 2213                 else {
 2214                         if (wrapindex == MAXWICACHE) {
 2215                                 wrapindex = 0;
 2216                         }
 2217                         cache_slot = wrapindex++;
 2218                 }
 2219         }
 2220 
 2221         /* 
 2222          * invariant: cache_slot now points at some slot
 2223          * in cache.
 2224          */
 2225         if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
 2226                 log(LOG_ERR, "owi_cache_store, bad index: %d of "
 2227                     "[0..%d], gross cache error\n",
 2228                     cache_slot, MAXWICACHE);
 2229                 return;
 2230         }
 2231 
 2232         /*
 2233          *  store items in cache
 2234          *  .ip source address
 2235          *  .mac src
 2236          *  .signal, etc.
 2237          */
 2238         if (sawip)
 2239                 sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
 2240         bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc,  6);
 2241 
 2242         sig = (rx_quality >> 8) & 0xFF;
 2243         noise = rx_quality & 0xFF;
 2244 
 2245         /*
 2246          * -149 is Lucent specific to convert to dBm.  Prism2 cards do
 2247          * things differently, sometimes don't have a noise measurement,
 2248          * and is firmware dependent :-(
 2249          */
 2250         sc->wi_sigcache[cache_slot].signal = sig - 149;
 2251         sc->wi_sigcache[cache_slot].noise = noise - 149;
 2252         sc->wi_sigcache[cache_slot].quality = sig - noise;
 2253 
 2254         return;
 2255 }
 2256 #endif
 2257 
 2258 static int
 2259 wi_get_cur_ssid(sc, ssid, len)
 2260         struct wi_softc         *sc;
 2261         char                    *ssid;
 2262         int                     *len;
 2263 {
 2264         int                     error = 0;
 2265         struct wi_req           wreq;
 2266 
 2267         wreq.wi_len = WI_MAX_DATALEN;
 2268         switch (sc->wi_ptype) {
 2269         case WI_PORTTYPE_IBSS:
 2270         case WI_PORTTYPE_ADHOC:
 2271                 wreq.wi_type = WI_RID_CURRENT_SSID;
 2272                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2273                 if (error != 0)
 2274                         break;
 2275                 if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
 2276                         error = EINVAL;
 2277                         break;
 2278                 }
 2279                 *len = wreq.wi_val[0];
 2280                 bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
 2281                 break;
 2282         case WI_PORTTYPE_BSS:
 2283                 wreq.wi_type = WI_RID_COMMQUAL;
 2284                 error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2285                 if (error != 0)
 2286                         break;
 2287                 if (wreq.wi_val[0] != 0) /* associated */ {
 2288                         wreq.wi_type = WI_RID_CURRENT_SSID;
 2289                         wreq.wi_len = WI_MAX_DATALEN;
 2290                         error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
 2291                         if (error != 0)
 2292                                 break;
 2293                         if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
 2294                                 error = EINVAL;
 2295                                 break;
 2296                         }
 2297                         *len = wreq.wi_val[0];
 2298                         bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
 2299                 } else {
 2300                         *len = IEEE80211_NWID_LEN;
 2301                         bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
 2302                 }
 2303                 break;
 2304         default:
 2305                 error = EINVAL;
 2306                 break;
 2307         }
 2308 
 2309         return error;
 2310 }
 2311 
 2312 static int
 2313 wi_media_change(ifp)
 2314         struct ifnet            *ifp;
 2315 {
 2316         struct wi_softc         *sc = ifp->if_softc;
 2317         int                     otype = sc->wi_ptype;
 2318         int                     orate = sc->wi_tx_rate;
 2319         int                     ocreate_ibss = sc->wi_create_ibss;
 2320 
 2321         sc->wi_create_ibss = 0;
 2322 
 2323         switch (sc->ifmedia.ifm_cur->ifm_media & IFM_OMASK) {
 2324         case 0:
 2325                 sc->wi_ptype = WI_PORTTYPE_BSS;
 2326                 break;
 2327         case IFM_IEEE80211_ADHOC:
 2328                 sc->wi_ptype = WI_PORTTYPE_ADHOC;
 2329                 break;
 2330         case IFM_IEEE80211_IBSSMASTER:
 2331         case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
 2332                 if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
 2333                         return (EINVAL);
 2334                 sc->wi_create_ibss = 1;
 2335                 /* FALLTHROUGH */
 2336         case IFM_IEEE80211_IBSS:
 2337                 sc->wi_ptype = WI_PORTTYPE_IBSS;
 2338                 break;
 2339         default:
 2340                 /* Invalid combination. */
 2341                 return (EINVAL);
 2342         }
 2343 
 2344         switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
 2345         case IFM_IEEE80211_DS1:
 2346                 sc->wi_tx_rate = 1;
 2347                 break;
 2348         case IFM_IEEE80211_DS2:
 2349                 sc->wi_tx_rate = 2;
 2350                 break;
 2351         case IFM_IEEE80211_DS5:
 2352                 sc->wi_tx_rate = 5;
 2353                 break;
 2354         case IFM_IEEE80211_DS11:
 2355                 sc->wi_tx_rate = 11;
 2356                 break;
 2357         case IFM_AUTO:
 2358                 sc->wi_tx_rate = 3;
 2359                 break;
 2360         }
 2361 
 2362         if (ocreate_ibss != sc->wi_create_ibss || otype != sc->wi_ptype ||
 2363             orate != sc->wi_tx_rate)
 2364                 wi_init(sc);
 2365 
 2366         return(0);
 2367 }
 2368 
 2369 static void
 2370 wi_media_status(ifp, imr)
 2371         struct ifnet            *ifp;
 2372         struct ifmediareq       *imr;
 2373 {
 2374         struct wi_req           wreq;
 2375         struct wi_softc         *sc = ifp->if_softc;
 2376 
 2377         if (sc->wi_tx_rate == 3) {
 2378                 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
 2379                 if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
 2380                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
 2381                 else if (sc->wi_ptype == WI_PORTTYPE_IBSS) {
 2382                         if (sc->wi_create_ibss)
 2383                                 imr->ifm_active |= IFM_IEEE80211_IBSSMASTER;
 2384                         else
 2385                                 imr->ifm_active |= IFM_IEEE80211_IBSS;
 2386                 }
 2387                 wreq.wi_type = WI_RID_CUR_TX_RATE;
 2388                 wreq.wi_len = WI_MAX_DATALEN;
 2389                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
 2390                         switch(wreq.wi_val[0]) {
 2391                         case 1:
 2392                                 imr->ifm_active |= IFM_IEEE80211_DS1;
 2393                                 break;
 2394                         case 2:
 2395                                 imr->ifm_active |= IFM_IEEE80211_DS2;
 2396                                 break;
 2397                         case 6:
 2398                                 imr->ifm_active |= IFM_IEEE80211_DS5;
 2399                                 break;
 2400                         case 11:
 2401                                 imr->ifm_active |= IFM_IEEE80211_DS11;
 2402                                 break;
 2403                                 }
 2404                 }
 2405         } else {
 2406                 imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
 2407         }
 2408 
 2409         imr->ifm_status = IFM_AVALID;
 2410         if (sc->wi_ptype == WI_PORTTYPE_ADHOC ||
 2411             sc->wi_ptype == WI_PORTTYPE_IBSS)
 2412                 /*
 2413                  * XXX: It would be nice if we could give some actually
 2414                  * useful status like whether we joined another IBSS or
 2415                  * created one ourselves.
 2416                  */
 2417                 imr->ifm_status |= IFM_ACTIVE;
 2418         else {
 2419                 wreq.wi_type = WI_RID_COMMQUAL;
 2420                 wreq.wi_len = WI_MAX_DATALEN;
 2421                 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
 2422                     wreq.wi_val[0] != 0)
 2423                         imr->ifm_status |= IFM_ACTIVE;
 2424         }
 2425 }

Cache object: 0ff6b9b60009003b57478a69d3b21a59


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