home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / mobile / wi.44.patches / if_wi.c < prev    next >
C/C++ Source or Header  |  2002-01-17  |  67KB  |  2,704 lines

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