aironet 802.11 ds driver from freebsd, isa and pci are missing
authormickey <mickey@openbsd.org>
Mon, 3 Apr 2000 01:01:58 +0000 (01:01 +0000)
committermickey <mickey@openbsd.org>
Mon, 3 Apr 2000 01:01:58 +0000 (01:01 +0000)
sys/conf/files
sys/dev/ic/an.c [new file with mode: 0644]
sys/dev/ic/anreg.h [new file with mode: 0644]
sys/dev/ic/anvar.h [new file with mode: 0644]
sys/dev/pcmcia/files.pcmcia
sys/dev/pcmcia/if_an_pcmcia.c [new file with mode: 0644]

index 3897329..2bad87b 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files,v 1.155 2000/03/23 09:59:56 art Exp $
+#      $OpenBSD: files,v 1.156 2000/04/03 01:02:00 mickey Exp $
 #      $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
@@ -103,6 +103,10 @@ file       dev/ic/elink3.c         ep
 # WaveLan
 # device wlp: ether, ifnet
 
+# Aironet 802.11 DS Ethernet controller
+device an: ether, ifnet, ifmedia
+file   dev/ic/an.c             an
+
 # RangeLAN2
 device rln: ether, ifnet
 file   dev/ic/rln.c            rln
diff --git a/sys/dev/ic/an.c b/sys/dev/ic/an.c
new file mode 100644 (file)
index 0000000..19be0d7
--- /dev/null
@@ -0,0 +1,1415 @@
+/*     $OpenBSD: an.c,v 1.1 2000/04/03 01:01:58 mickey Exp $   */
+
+/*
+ * Copyright (c) 1997, 1998, 1999
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/an/if_an.c,v 1.2 2000/01/16 06:41:49 wpaul Exp $
+ */
+
+/*
+ * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Electrical Engineering Department
+ * Columbia University, New York City
+ */
+
+/*
+ * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form.
+ * This driver supports all three device types (PCI devices are supported
+ * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be
+ * supported either using hard-coded IO port/IRQ settings or via Plug
+ * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
+ * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
+ *
+ * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
+ * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
+ * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
+ * a couple of important differences though:
+ *
+ * - Lucent doesn't currently offer a PCI card, however Aironet does
+ * - Lucent ISA card looks to the host like a PCMCIA controller with
+ *   a PCMCIA WaveLAN card inserted. This means that even desktop
+ *   machines need to be configured with PCMCIA support in order to
+ *   use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
+ *   actually look like normal ISA and PCI devices to the host, so
+ *   no PCMCIA controller support is needed
+ *
+ * The latter point results in a small gotcha. The Aironet PCMCIA
+ * cards can be configured for one of two operating modes depending
+ * on how the Vpp1 and Vpp2 programming voltages are set when the
+ * card is activated. In order to put the card in proper PCMCIA
+ * operation (where the CIS table is visible and the interface is
+ * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
+ * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
+ * which leaves the card in ISA/PCI mode, which prevents it from
+ * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c
+ * has to be patched slightly in order to enable the Vpp voltages in
+ * order to make the Aironet PCMCIA cards work.
+ *
+ * Note that some PCMCIA controller software packages for Windows NT
+ * fail to set the voltages as well.
+ *
+ * The Aironet devices can operate in both station mode and access point
+ * mode. Typically, when programmed for station mode, the card can be set
+ * to automatically perform encapsulation/decapsulation of Ethernet II
+ * and 802.3 frames within 802.11 frames so that the host doesn't have
+ * to do it itself. This driver doesn't program the card that way: the
+ * driver handles all of the encapsulation/decapsulation itself.
+ */
+
+#ifdef INET
+#define ANCACHE                        /* enable signal strength cache */
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/timeout.h>
+#ifdef ANCACHE
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/ic/anvar.h>
+#include <dev/ic/anreg.h>
+
+#define TIMEOUT(handle,func,sc,time) timeout_add(&(handle), (time))
+#define UNTIMEOUT(func,sc,handle) timeout_del(&(handle))
+#define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf))
+#define BPFATTACH(if_bpf,if,dlt,sz) bpfattach((if_bpf), (if), (dlt), (sz))
+
+struct cfdriver an_cd = {
+       NULL, "an", DV_IFNET
+};
+
+void an_reset          __P((struct an_softc *));
+int an_ioctl           __P((struct ifnet *, u_long, caddr_t));
+int an_init_tx_ring    __P((struct an_softc *));
+void an_start          __P((struct ifnet *));
+void an_watchdog               __P((struct ifnet *));
+void an_rxeof          __P((struct an_softc *));
+void an_txeof          __P((struct an_softc *, int));
+
+void an_promisc                __P((struct an_softc *, int));
+int an_cmd             __P((struct an_softc *, int, int));
+int an_read_record     __P((struct an_softc *, struct an_ltv_gen *));
+int an_write_record    __P((struct an_softc *, struct an_ltv_gen *));
+int an_read_data               __P((struct an_softc *, int,
+                                       int, caddr_t, int));
+int an_write_data      __P((struct an_softc *, int,
+                                       int, caddr_t, int));
+int an_seek            __P((struct an_softc *, int, int, int));
+int an_alloc_nicmem    __P((struct an_softc *, int, int *));
+void an_stats_update   __P((void *));
+void an_setdef         __P((struct an_softc *, struct an_req *));
+#ifdef ANCACHE
+void an_cache_store    __P((struct an_softc *, struct ether_header *,
+                                       struct mbuf *, unsigned short));
+#endif
+
+int
+an_attach(sc)
+       struct an_softc *sc;
+{
+       struct ifnet    *ifp = &sc->arpcom.ac_if;
+
+       sc->an_gone = 0;
+       sc->an_associated = 0;
+
+       /* disable interrupts */
+       CSR_WRITE_2(sc, AN_INT_EN, 0);
+       CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff);
+
+       /* Reset the NIC. */
+       an_reset(sc);
+
+       /* Load factory config */
+       if (an_cmd(sc, AN_CMD_READCFG, 0)) {
+               printf("%s: failed to load config data\n", ifp->if_xname);
+               return(EIO);
+       }
+
+       /* Read the current configuration */
+       sc->an_config.an_type = AN_RID_GENCONFIG;
+       sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
+       if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
+               printf("%s: read record failed\n", ifp->if_xname);
+               return(EIO);
+       }
+
+       /* Read the card capabilities */
+       sc->an_caps.an_type = AN_RID_CAPABILITIES;
+       sc->an_caps.an_len = sizeof(struct an_ltv_caps);
+       if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
+               printf("%s: read record failed\n", ifp->if_xname);
+               return(EIO);
+       }
+
+       /* Read ssid list */
+       sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
+       sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
+       if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
+               printf("%s: read record failed\n", ifp->if_xname);
+               return(EIO);
+       }
+
+       /* Read AP list */
+       sc->an_aplist.an_type = AN_RID_APLIST;
+       sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
+       if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
+               printf("%s: read record failed\n", ifp->if_xname);
+               return(EIO);
+       }
+
+       bcopy((char *)&sc->an_caps.an_oemaddr,
+          (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
+
+       printf(": address: %6s\n", ether_sprintf(sc->arpcom.ac_enaddr));
+
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
+       ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_ioctl = an_ioctl;
+       ifp->if_start = an_start;
+       ifp->if_watchdog = an_watchdog;
+       ifp->if_baudrate = 10000000;
+       ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+
+       bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
+       bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename,
+           sizeof(AN_DEFAULT_NODENAME) - 1);
+
+       bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1));
+       bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1,
+           sizeof(AN_DEFAULT_NETNAME) - 1);
+       sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME);
+
+       sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
+
+       sc->an_tx_rate = 0;
+       bzero((char *)&sc->an_stats, sizeof(sc->an_stats));
+
+       /*
+        * Call MI attach routines.
+        */
+       if_attach(ifp);
+       ether_ifattach(ifp);
+       timeout_set(&sc->an_stat_ch, an_stats_update, sc);
+#if NBPFILTER > 0
+       BPFATTACH(&sc->arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
+           sizeof(struct ether_header));
+#endif
+
+       shutdownhook_establish(an_shutdown, sc);
+
+       an_init(sc);
+
+       return(0);
+}
+
+void
+an_rxeof(sc)
+       struct an_softc  *sc;
+{
+       struct ifnet            *ifp;
+       struct ether_header     *eh;
+#ifdef ANCACHE
+       struct an_rxframe       rx_frame;
+#endif
+       struct an_rxframe_802_3 rx_frame_802_3;
+       struct mbuf             *m;
+       int                     id, error = 0;
+
+       ifp = &sc->arpcom.ac_if;
+
+       id = CSR_READ_2(sc, AN_RX_FID);
+
+       MGETHDR(m, M_DONTWAIT, MT_DATA);
+       if (m == NULL) {
+               ifp->if_ierrors++;
+               return;
+       }
+       MCLGET(m, M_DONTWAIT);
+       if (!(m->m_flags & M_EXT)) {
+               m_freem(m);
+               ifp->if_ierrors++;
+               return;
+       }
+
+       m->m_pkthdr.rcvif = ifp;
+
+       eh = mtod(m, struct ether_header *);
+
+#ifdef ANCACHE
+       /* Read NIC frame header */
+       if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
+               ifp->if_ierrors++;
+               return;
+       }
+#endif
+       /* Read in the 802_3 frame header */
+       if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3,
+                        sizeof(rx_frame_802_3))) {
+               ifp->if_ierrors++;
+               return;
+       }
+
+       if (rx_frame_802_3.an_rx_802_3_status != 0) {
+               ifp->if_ierrors++;
+               return;
+       }
+
+       /* Check for insane frame length */
+       if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) {
+               ifp->if_ierrors++;
+               return;
+       }
+
+       m->m_pkthdr.len = m->m_len =
+           rx_frame_802_3.an_rx_802_3_payload_len + 12;
+
+
+       bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,
+           (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
+       bcopy((char *)&rx_frame_802_3.an_rx_src_addr,
+           (char *)&eh->ether_shost, ETHER_ADDR_LEN);
+
+       /* in mbuf header type is just before payload */
+       error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),
+                            rx_frame_802_3.an_rx_802_3_payload_len);
+
+       if (error) {
+               m_freem(m);
+               ifp->if_ierrors++;
+               return;
+       }
+
+       ifp->if_ipackets++;
+
+       /* Handle BPF listeners. */
+       if (ifp->if_bpf) {
+               BPF_MTAP(ifp, m);
+               if (ifp->if_flags & IFF_PROMISC &&
+                   (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
+                   ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) {
+                       m_freem(m);
+                       return;
+               }
+       }
+
+       /* Receive packet. */
+       m_adj(m, sizeof(struct ether_header));
+#ifdef ANCACHE
+       an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);
+#endif
+       ether_input(ifp, eh, m);
+
+       return;
+}
+
+void
+an_txeof(sc, status)
+       struct an_softc         *sc;
+       int                     status;
+{
+       struct ifnet            *ifp;
+       int                     id;
+
+       ifp = &sc->arpcom.ac_if;
+
+       ifp->if_timer = 0;
+       ifp->if_flags &= ~IFF_OACTIVE;
+
+       id = CSR_READ_2(sc, AN_TX_CMP_FID);
+
+       if (status & AN_EV_TX_EXC) {
+               ifp->if_oerrors++;
+       } else
+               ifp->if_opackets++;
+
+       if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons])
+               printf("%s: id mismatch: expected %x, got %x\n", ifp->if_xname,
+                   sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id);
+
+       sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] = 0;
+       AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
+
+       return;
+}
+
+/*
+ * We abuse the stats updater to check the current NIC status. This
+ * is important because we don't want to allow transmissions until
+ * the NIC has synchronized to the current cell (either as the master
+ * in an ad-hoc group, or as a station connected to an access point).
+ */
+void
+an_stats_update(xsc)
+       void                    *xsc;
+{
+       struct an_softc         *sc;
+       struct ifnet            *ifp;
+       int                     s;
+
+       s = splimp();
+
+       sc = xsc;
+       ifp = &sc->arpcom.ac_if;
+
+       sc->an_status.an_type = AN_RID_STATUS;
+       sc->an_status.an_len = sizeof(struct an_ltv_status);
+       an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
+
+       if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
+               sc->an_associated = 1;
+       else
+               sc->an_associated = 0;
+
+       /* Don't do this while we're transmitting */
+       if (!(ifp->if_flags & IFF_OACTIVE)) {
+               sc->an_stats.an_len = sizeof(struct an_ltv_stats);
+               sc->an_stats.an_type = AN_RID_32BITS_CUM;
+               an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
+       }
+
+       splx(s);
+       TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz);
+}
+
+int
+an_intr(xsc)
+       void    *xsc;
+{
+       struct an_softc         *sc;
+       struct ifnet            *ifp;
+       u_int16_t               status;
+
+       sc = (struct an_softc*)xsc;
+
+       if (sc->an_gone)
+               return 0;
+
+       ifp = &sc->arpcom.ac_if;
+
+       if (!(ifp->if_flags & IFF_UP)) {
+               CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF);
+               CSR_WRITE_2(sc, AN_INT_EN, 0);
+               return 0;
+       }
+
+       /* Disable interrupts. */
+       CSR_WRITE_2(sc, AN_INT_EN, 0);
+
+       status = CSR_READ_2(sc, AN_EVENT_STAT);
+       CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS);
+
+       if (status & AN_EV_AWAKE) {
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE);
+       }
+
+       if (status & AN_EV_LINKSTAT) {
+               if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED)
+                       sc->an_associated = 1;
+               else
+                       sc->an_associated = 0;
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
+       }
+
+       if (status & AN_EV_RX) {
+               an_rxeof(sc);
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
+       }
+
+       if (status & AN_EV_TX) {
+               an_txeof(sc, status);
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX);
+       }
+
+       if (status & AN_EV_TX_EXC) {
+               an_txeof(sc, status);
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC);
+       }
+
+       if (status & AN_EV_ALLOC)
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
+
+       /* Re-enable interrupts. */
+       CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
+
+       if (ifp->if_snd.ifq_head != NULL)
+               an_start(ifp);
+
+       return 1;
+}
+
+int
+an_cmd(sc, cmd, val)
+       struct an_softc *sc;
+       int cmd;
+       int val;
+{
+       int i;
+
+       CSR_WRITE_2(sc, AN_PARAM0, val);
+       CSR_WRITE_2(sc, AN_PARAM1, 0);
+       CSR_WRITE_2(sc, AN_PARAM2, 0);
+       DELAY(10);
+       CSR_WRITE_2(sc, AN_COMMAND, cmd);
+       DELAY(10);
+
+       for (i = AN_TIMEOUT; i--; DELAY(10)) {
+               if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
+                       break;
+               else {
+                       if (CSR_READ_2(sc, AN_COMMAND) == cmd) {
+                               DELAY(10);
+                               CSR_WRITE_2(sc, AN_COMMAND, cmd);
+                       }
+               }
+       }
+/* printf("<<cmd %x,%d>>", cmd, i); */
+#if 0
+       DELAY(100);
+       for (i = AN_TIMEOUT; i--; DELAY(100)) {
+               int s = CSR_READ_2(sc, AN_STATUS);
+               CSR_READ_2(sc, AN_RESP0);
+               CSR_READ_2(sc, AN_RESP1);
+               CSR_READ_2(sc, AN_RESP2);
+               if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE))
+                       break;
+       }
+printf("<<resp %d, %x>>", i, s);
+#endif
+       /* Ack the command */
+       CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
+
+       if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
+printf("busy");
+               CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
+       }
+
+       if (i <= 0)
+               return(ETIMEDOUT);
+
+       return(0);
+}
+
+/*
+ * This reset sequence may look a little strange, but this is the
+ * most reliable method I've found to really kick the NIC in the
+ * head and force it to reboot correctly.
+ */
+void an_reset(sc)
+       struct an_softc         *sc;
+{
+       if (sc->an_gone)
+               return;
+printf("ena ");
+       an_cmd(sc, AN_CMD_ENABLE, 0);
+printf("rst ");
+       an_cmd(sc, AN_CMD_FW_RESTART, 0);
+printf("nop ");
+       an_cmd(sc, AN_CMD_NOOP2, 0);
+
+       if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
+               printf("%s: reset failed\n", sc->sc_dev.dv_xname);
+
+       an_cmd(sc, AN_CMD_DISABLE, 0);
+
+       return;
+}
+
+/*
+ * Read an LTV record from the NIC.
+ */
+int an_read_record(sc, ltv)
+       struct an_softc         *sc;
+       struct an_ltv_gen       *ltv;
+{
+       u_int16_t               *ptr;
+       int                     i, len;
+
+       if (ltv->an_len == 0 || ltv->an_type == 0)
+               return(EINVAL);
+
+       /* Tell the NIC to enter record read mode. */
+       if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {
+               printf("%s: RID access failed\n", sc->sc_dev.dv_xname);
+               return(EIO);
+       }
+
+       /* Seek to the record. */
+       if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {
+               printf("%s: seek to record failed\n", sc->sc_dev.dv_xname);
+               return(EIO);
+       }
+
+       /*
+        * Read the length and record type and make sure they
+        * match what we expect (this verifies that we have enough
+        * room to hold all of the returned data).
+        */
+       len = CSR_READ_2(sc, AN_DATA1);
+       if (len > ltv->an_len) {
+               printf("%s: record length mismatch -- expected %d, got %d\n",
+                   sc->sc_dev.dv_xname, ltv->an_len, len);
+               return(ENOSPC);
+       }
+
+       ltv->an_len = len;
+
+       /* Now read the data. */
+       ptr = &ltv->an_val;
+       for (i = 0; i < (ltv->an_len - 1) >> 1; i++)
+               ptr[i] = CSR_READ_2(sc, AN_DATA1);
+
+       return(0);
+}
+
+/*
+ * Same as read, except we inject data instead of reading it.
+ */
+int an_write_record(sc, ltv)
+       struct an_softc         *sc;
+       struct an_ltv_gen       *ltv;
+{
+       u_int16_t               *ptr;
+       int                     i;
+
+       if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
+               return(EIO);
+
+       if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
+               return(EIO);
+
+       CSR_WRITE_2(sc, AN_DATA1, ltv->an_len);
+
+       ptr = &ltv->an_val;
+       for (i = 0; i < (ltv->an_len - 1) >> 1; i++)
+               CSR_WRITE_2(sc, AN_DATA1, ptr[i]);
+
+       if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
+               return(EIO);
+
+       return(0);
+}
+
+int an_seek(sc, id, off, chan)
+       struct an_softc         *sc;
+       int                     id, off, chan;
+{
+       int                     i;
+       int                     selreg, offreg;
+
+       switch (chan) {
+       case AN_BAP0:
+               selreg = AN_SEL0;
+               offreg = AN_OFF0;
+               break;
+       case AN_BAP1:
+               selreg = AN_SEL1;
+               offreg = AN_OFF1;
+               break;
+       default:
+               printf("%s: invalid data path: %x\n",
+                   sc->sc_dev.dv_xname, chan);
+               return(EIO);
+       }
+
+       CSR_WRITE_2(sc, selreg, id);
+       CSR_WRITE_2(sc, offreg, off);
+
+       for (i = AN_TIMEOUT; i--; DELAY(10)) {
+               if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
+                       break;
+       }
+
+       if (i <= 0)
+               return(ETIMEDOUT);
+
+       return(0);
+}
+
+int an_read_data(sc, id, off, buf, len)
+       struct an_softc         *sc;
+       int                     id, off;
+       caddr_t                 buf;
+       int                     len;
+{
+       int                     i;
+       u_int16_t               *ptr;
+       u_int8_t                *ptr2;
+
+       if (off != -1) {
+               if (an_seek(sc, id, off, AN_BAP1))
+                       return(EIO);
+       }
+
+       ptr = (u_int16_t *)buf;
+       for (i = 0; i < len / 2; i++)
+               ptr[i] = CSR_READ_2(sc, AN_DATA1);
+       i*=2;
+       if (i<len){
+               ptr2 = (u_int8_t *)buf;
+               ptr2[i] = CSR_READ_1(sc, AN_DATA1);
+       }
+
+       return(0);
+}
+
+int an_write_data(sc, id, off, buf, len)
+       struct an_softc         *sc;
+       int                     id, off;
+       caddr_t                 buf;
+       int                     len;
+{
+       int                     i;
+       u_int16_t               *ptr;
+       u_int8_t                *ptr2;
+
+       if (off != -1) {
+               if (an_seek(sc, id, off, AN_BAP0))
+                       return(EIO);
+       }
+
+       ptr = (u_int16_t *)buf;
+       for (i = 0; i < (len / 2); i++)
+               CSR_WRITE_2(sc, AN_DATA0, ptr[i]);
+       i*=2;
+       if (i<len){
+               ptr2 = (u_int8_t *)buf;
+               CSR_WRITE_1(sc, AN_DATA0, ptr2[i]);
+       }
+
+       return(0);
+}
+
+/*
+ * Allocate a region of memory inside the NIC and zero
+ * it out.
+ */
+int an_alloc_nicmem(sc, len, id)
+       struct an_softc         *sc;
+       int                     len;
+       int                     *id;
+{
+       int                     i;
+
+       if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
+               printf("%s: failed to allocate %d bytes on NIC\n",
+                   sc->sc_dev.dv_xname, len);
+               return(ENOMEM);
+       }
+
+       for (i = AN_TIMEOUT; i--; DELAY(10)) {
+               if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
+                       break;
+       }
+
+       if (i <= 0)
+               return(ETIMEDOUT);
+
+       CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
+       *id = CSR_READ_2(sc, AN_ALLOC_FID);
+
+       if (an_seek(sc, *id, 0, AN_BAP0))
+               return(EIO);
+
+       for (i = 0; i < len / 2; i++)
+               CSR_WRITE_2(sc, AN_DATA0, 0);
+
+       return(0);
+}
+
+void
+an_setdef(sc, areq)
+       struct an_softc         *sc;
+       struct an_req           *areq;
+{
+       struct sockaddr_dl      *sdl;
+       struct ifaddr           *ifa;
+       struct ifnet            *ifp;
+       struct an_ltv_genconfig *cfg;
+       struct an_ltv_ssidlist  *ssid;
+       struct an_ltv_aplist    *ap;
+       struct an_ltv_gen       *sp;
+       extern struct ifaddr    **ifnet_addrs;
+
+       ifp = &sc->arpcom.ac_if;
+
+       switch (areq->an_type) {
+       case AN_RID_GENCONFIG:
+               cfg = (struct an_ltv_genconfig *)areq;
+
+               ifa = ifnet_addrs[ifp->if_index - 1];
+               sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+               bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr,
+                   ETHER_ADDR_LEN);
+               bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN);
+
+               bcopy((char *)cfg, (char *)&sc->an_config,
+                       sizeof(struct an_ltv_genconfig));
+               break;
+       case AN_RID_SSIDLIST:
+               ssid = (struct an_ltv_ssidlist *)areq;
+               bcopy((char *)ssid, (char *)&sc->an_ssidlist,
+                       sizeof(struct an_ltv_ssidlist));
+               break;
+       case AN_RID_APLIST:
+               ap = (struct an_ltv_aplist *)areq;
+               bcopy((char *)ap, (char *)&sc->an_aplist,
+                       sizeof(struct an_ltv_aplist));
+               break;
+       case AN_RID_TX_SPEED:
+               sp = (struct an_ltv_gen *)areq;
+               sc->an_tx_rate = sp->an_val;
+               break;
+       default:
+               printf("%s: unknown RID: %x\n",
+                   sc->sc_dev.dv_xname, areq->an_type);
+               return;
+       }
+
+       /* Reinitialize the card. */
+       if (ifp->if_flags & IFF_UP)
+               an_init(sc);
+
+       return;
+}
+
+/*
+ * We can't change the NIC configuration while the MAC is enabled,
+ * so in order to turn on RX monitor mode, we have to turn the MAC
+ * off first.
+ */
+void an_promisc(sc, promisc)
+       struct an_softc         *sc;
+       int                     promisc;
+{
+       /* Disable the MAC. */
+       an_cmd(sc, AN_CMD_DISABLE, 0);
+
+       /* Set RX mode. */
+       if (promisc &&
+           !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS)
+           ) {
+               sc->an_rxmode = sc->an_config.an_rxmode;
+               sc->an_config.an_rxmode |=
+                   AN_RXMODE_LAN_MONITOR_CURBSS;
+       } else {
+               sc->an_config.an_rxmode = sc->an_rxmode;
+       }
+
+       /* Transfer the configuration to the NIC */
+       sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
+       sc->an_config.an_type = AN_RID_GENCONFIG;
+       if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
+               printf("%s: failed to set configuration\n",
+                   sc->sc_dev.dv_xname);
+               return;
+       }
+       /* Turn the MAC back on. */
+       an_cmd(sc, AN_CMD_ENABLE, 0);
+
+       return;
+}
+
+int an_ioctl(ifp, command, data)
+       struct ifnet            *ifp;
+       u_long                  command;
+       caddr_t                 data;
+{
+       int                     s, error = 0;
+       struct an_softc         *sc;
+       struct an_req           areq;
+       struct ifreq            *ifr;
+       struct ifaddr           *ifa = (struct ifaddr *)data;
+
+       s = splimp();
+
+       sc = ifp->if_softc;
+       ifr = (struct ifreq *)data;
+
+       if (sc->an_gone)
+               return(ENODEV);
+
+       if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
+               splx(s);
+               return error;
+       }
+
+       switch(command) {
+       case SIOCSIFADDR:
+               ifp->if_flags |= IFF_UP;
+               switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       an_init(sc);
+                       arp_ifinit(&sc->arpcom, ifa);
+                       break;
+#endif
+               default:
+                       an_init(sc);
+                       break;
+               }
+               break;
+       case SIOCSIFFLAGS:
+               if (ifp->if_flags & IFF_UP) {
+                       if (ifp->if_flags & IFF_RUNNING &&
+                           ifp->if_flags & IFF_PROMISC &&
+                           !(sc->an_if_flags & IFF_PROMISC)) {
+                               an_promisc(sc, 1);
+                       } else if (ifp->if_flags & IFF_RUNNING &&
+                           !(ifp->if_flags & IFF_PROMISC) &&
+                           sc->an_if_flags & IFF_PROMISC) {
+                               an_promisc(sc, 0);
+                       } else
+                               an_init(sc);
+               } else {
+                       if (ifp->if_flags & IFF_RUNNING)
+                               an_stop(sc);
+               }
+               sc->an_if_flags = ifp->if_flags;
+               error = 0;
+               break;
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               /* The Aironet has no multicast filter. */
+               error = 0;
+               break;
+       case SIOCGAIRONET:
+               error = copyin(ifr->ifr_data, &areq, sizeof(areq));
+               if (error)
+                       break;
+#ifdef ANCACHE
+               if (areq.an_type == AN_RID_ZERO_CACHE) {
+                       sc->an_sigitems = sc->an_nextitem = 0;
+                       break;
+               } else if (areq.an_type == AN_RID_READ_CACHE) {
+                       char *pt = (char *)&areq.an_val;
+                       bcopy((char *)&sc->an_sigitems, (char *)pt,
+                           sizeof(int));
+                       pt += sizeof(int);
+                       areq.an_len = sizeof(int) / 2;
+                       bcopy((char *)&sc->an_sigcache, (char *)pt,
+                           sizeof(struct an_sigcache) * sc->an_sigitems);
+                       areq.an_len += ((sizeof(struct an_sigcache) *
+                           sc->an_sigitems) / 2) + 1;
+               } else
+#endif
+               if (an_read_record(sc, (struct an_ltv_gen *)&areq)) {
+                       error = EINVAL;
+                       break;
+               }
+               error = copyout(&areq, ifr->ifr_data, sizeof(areq));
+               break;
+       case SIOCSAIRONET:
+               error = copyin(ifr->ifr_data, &areq, sizeof(areq));
+               if (error)
+                       break;
+               an_setdef(sc, &areq);
+               break;
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       splx(s);
+
+       return(error);
+}
+
+int
+an_init_tx_ring(sc)
+       struct an_softc         *sc;
+{
+       int                     i;
+       int                     id;
+
+       if (sc->an_gone)
+               return (0);
+
+       for (i = 0; i < AN_TX_RING_CNT; i++) {
+               if (an_alloc_nicmem(sc, 1518 + 0x44, &id))
+                       return(ENOMEM);
+               sc->an_rdata.an_tx_fids[i] = id;
+               sc->an_rdata.an_tx_ring[i] = 0;
+       }
+
+       sc->an_rdata.an_tx_prod = 0;
+       sc->an_rdata.an_tx_cons = 0;
+
+       return(0);
+}
+
+void
+an_init(sc)
+       struct an_softc *sc;
+{
+       struct ifnet            *ifp = &sc->arpcom.ac_if;
+       int                     s;
+
+       if (sc->an_gone)
+               return;
+
+       s = splimp();
+
+       if (ifp->if_flags & IFF_RUNNING)
+               an_stop(sc);
+
+       sc->an_associated = 0;
+
+       /* Allocate the TX buffers */
+       if (an_init_tx_ring(sc)) {
+               an_reset(sc);
+               if (an_init_tx_ring(sc)) {
+                       printf("%s: tx buffer allocation failed\n",
+                           sc->sc_dev.dv_xname);
+                       splx(s);
+                       return;
+               }
+       }
+
+       /* Set our MAC address. */
+       bcopy((char *)&sc->arpcom.ac_enaddr,
+           (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN);
+
+       if (ifp->if_flags & IFF_BROADCAST)
+               sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
+       else
+               sc->an_config.an_rxmode = AN_RXMODE_ADDR;
+
+       if (ifp->if_flags & IFF_MULTICAST)
+               sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
+
+       /* Initialize promisc mode. */
+       if (ifp->if_flags & IFF_PROMISC)
+               sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS;
+
+       sc->an_rxmode = sc->an_config.an_rxmode;
+
+       /* Set the ssid list */
+       sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
+       sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
+       if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
+               printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname);
+               splx(s);
+               return;
+       }
+
+       /* Set the AP list */
+       sc->an_aplist.an_type = AN_RID_APLIST;
+       sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
+       if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
+               printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname);
+               splx(s);
+               return;
+       }
+
+       /* Set the configuration in the NIC */
+       sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
+       sc->an_config.an_type = AN_RID_GENCONFIG;
+       if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
+               printf("%s: failed to set configuration\n",
+                   sc->sc_dev.dv_xname);
+               splx(s);
+               return;
+       }
+
+       /* Enable the MAC */
+       if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
+               printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname);
+               splx(s);
+               return;
+       }
+
+       /* enable interrupts */
+       CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
+
+       splx(s);
+
+       ifp->if_flags |= IFF_RUNNING;
+       ifp->if_flags &= ~IFF_OACTIVE;
+
+       TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz);
+
+       return;
+}
+
+void an_start(ifp)
+       struct ifnet            *ifp;
+{
+       struct an_softc         *sc;
+       struct mbuf             *m0 = NULL;
+       struct an_txframe_802_3 tx_frame_802_3;
+       struct ether_header     *eh;
+       int                     id;
+       int                     idx;
+       unsigned char           txcontrol;
+
+       sc = ifp->if_softc;
+
+       if (sc->an_gone)
+               return;
+
+       if (ifp->if_flags & IFF_OACTIVE)
+               return;
+
+       if (!sc->an_associated)
+               return;
+
+       idx = sc->an_rdata.an_tx_prod;
+       bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3));
+
+       while(sc->an_rdata.an_tx_ring[idx] == 0) {
+               IF_DEQUEUE(&ifp->if_snd, m0);
+               if (m0 == NULL)
+                       break;
+
+               id = sc->an_rdata.an_tx_fids[idx];
+               eh = mtod(m0, struct ether_header *);
+
+               bcopy((char *)&eh->ether_dhost,
+                   (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN);
+               bcopy((char *)&eh->ether_shost,
+                   (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN);
+
+               tx_frame_802_3.an_tx_802_3_payload_len =
+                 m0->m_pkthdr.len - 12;  /* minus src/dest mac & type */
+
+               m_copydata(m0, sizeof(struct ether_header) - 2 ,
+                   tx_frame_802_3.an_tx_802_3_payload_len,
+                   (caddr_t)&sc->an_txbuf);
+
+               txcontrol=AN_TXCTL_8023;
+               /* write the txcontrol only */
+               an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
+                             sizeof(txcontrol));
+
+               /* 802_3 header */
+               an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3,
+                             sizeof(struct an_txframe_802_3));
+
+               /* in mbuf header type is just before payload */
+               an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf,
+                           tx_frame_802_3.an_tx_802_3_payload_len);
+
+               /*
+                * If there's a BPF listner, bounce a copy of
+                * this frame to him.
+                */
+               if (ifp->if_bpf)
+                       BPF_MTAP(ifp, m0);
+
+               m_freem(m0);
+               m0 = NULL;
+
+               sc->an_rdata.an_tx_ring[idx] = id;
+               if (an_cmd(sc, AN_CMD_TX, id))
+                       printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
+
+               AN_INC(idx, AN_TX_RING_CNT);
+       }
+
+       if (m0 != NULL)
+               ifp->if_flags |= IFF_OACTIVE;
+
+       sc->an_rdata.an_tx_prod = idx;
+
+       /*
+        * Set a timeout in case the chip goes out to lunch.
+        */
+       ifp->if_timer = 5;
+
+       return;
+}
+
+void an_stop(sc)
+       struct an_softc         *sc;
+{
+       struct ifnet            *ifp;
+       int                     i;
+
+       if (sc->an_gone)
+               return;
+
+       ifp = &sc->arpcom.ac_if;
+
+       an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
+       CSR_WRITE_2(sc, AN_INT_EN, 0);
+       an_cmd(sc, AN_CMD_DISABLE, 0);
+
+       for (i = 0; i < AN_TX_RING_CNT; i++)
+               an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
+
+       UNTIMEOUT(an_stats_update, sc, sc->an_stat_ch);
+
+       ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
+
+       return;
+}
+
+void an_watchdog(ifp)
+       struct ifnet            *ifp;
+{
+       struct an_softc         *sc;
+
+       sc = ifp->if_softc;
+
+       if (sc->an_gone)
+               return;
+
+       printf("%s: device timeout\n", sc->sc_dev.dv_xname);
+
+       an_reset(sc);
+       an_init(sc);
+
+       ifp->if_oerrors++;
+
+       return;
+}
+
+void
+an_shutdown(self)
+       void *self;
+{
+       an_stop(self);
+}
+
+#ifdef ANCACHE
+/* Aironet signal strength cache code.
+ * store signal/noise/quality on per MAC src basis in
+ * a small fixed cache.  The cache wraps if > MAX slots
+ * used.  The cache may be zeroed out to start over.
+ * Two simple filters exist to reduce computation:
+ * 1. ip only (literally 0x800) which may be used
+ * to ignore some packets.  It defaults to ip only.
+ * it could be used to focus on broadcast, non-IP 802.11 beacons.
+ * 2. multicast/broadcast only.  This may be used to
+ * ignore unicast packets and only cache signal strength
+ * for multicast/broadcast packets (beacons); e.g., Mobile-IP
+ * beacons and not unicast traffic.
+ *
+ * The cache stores (MAC src(index), IP src (major clue), signal,
+ *     quality, noise)
+ *
+ * No apologies for storing IP src here.  It's easy and saves much
+ * trouble elsewhere.  The cache is assumed to be INET dependent,
+ * although it need not be.
+ *
+ * Note: the Aironet only has a single byte of signal strength value
+ * in the rx frame header, and it's not scaled to anything sensible.
+ * This is kind of lame, but it's all we've got.
+ */
+
+#ifdef documentation
+
+int an_sigitems;                                /* number of cached entries */
+struct an_sigcache an_sigcache[MAXANCACHE];  /*  array of cache entries */
+int an_nextitem;                                /*  index/# of entries */
+
+
+#endif
+
+/* control variables for cache filtering.  Basic idea is
+ * to reduce cost (e.g., to only Mobile-IP agent beacons
+ * which are broadcast or multicast).  Still you might
+ * want to measure signal strength anth unicast ping packets
+ * on a pt. to pt. ant. setup.
+ */
+/* set true if you want to limit cache items to broadcast/mcast
+ * only packets (not unicast).  Useful for mobile-ip beacons which
+ * are broadcast/multicast at network layer.  Default is all packets
+ * so ping/unicast anll work say anth pt. to pt. antennae setup.
+ */
+#if 0
+static int an_cache_mcastonly = 0;
+SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
+       &an_cache_mcastonly, 0, "");
+
+/* set true if you want to limit cache items to IP packets only
+*/
+static int an_cache_iponly = 1;
+SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
+       &an_cache_iponly, 0, "");
+#endif
+
+/*
+ * an_cache_store, per rx packet store signal
+ * strength in MAC (src) indexed cache.
+ */
+void
+an_cache_store (sc, eh, m, rx_quality)
+       struct an_softc *sc;
+       struct ether_header *eh;
+       struct mbuf *m;
+       unsigned short rx_quality;
+{
+       struct ip *ip = 0;
+       int i;
+       static int cache_slot = 0;      /* use this cache entry */
+       static int wrapindex = 0;       /* next "free" cache entry */
+       int saanp=0;
+
+       /* filters:
+        * 1. ip only
+        * 2. configurable filter to throw out unicast packets,
+        * keep multicast only.
+        */
+
+       if ((ntohs(eh->ether_type) == 0x800)) {
+               saanp = 1;
+       }
+
+       /* filter for ip packets only
+       */
+       if (sc->an_cache_iponly && !saanp) {
+               return;
+       }
+
+       /* filter for broadcast/multicast only
+        */
+       if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
+               return;
+       }
+
+#ifdef SIGDEBUG
+       printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
+           rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
+#endif
+
+       /* find the ip header.  we want to store the ip_src
+        * address.
+        */
+       if (saanp) {
+               ip = mtod(m, struct ip *);
+       }
+
+       /* do a linear search for a matching MAC address
+        * in the cache table
+        * . MAC address is 6 bytes,
+        * . var w_nextitem holds total number of entries already cached
+        */
+       for(i = 0; i < sc->an_nextitem; i++) {
+               if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc,  6 )) {
+                       /* Match!,
+                        * so we already have this entry,
+                        * update the data
+                        */
+                       break;
+               }
+       }
+
+       /* did we find a matching mac address?
+        * if yes, then overwrite a previously existing cache entry
+        */
+       if (i < sc->an_nextitem )   {
+               cache_slot = i;
+       }
+       /* else, have a new address entry,so
+        * add this new entry,
+        * if table full, then we need to replace LRU entry
+        */
+       else    {
+
+               /* check for space in cache table
+                * note: an_nextitem also holds number of entries
+                * added in the cache table
+                */
+               if ( sc->an_nextitem < MAXANCACHE ) {
+                       cache_slot = sc->an_nextitem;
+                       sc->an_nextitem++;
+                       sc->an_sigitems = sc->an_nextitem;
+               }
+               /* no space found, so simply wrap anth wrap index
+                * and "zap" the next entry
+                */
+               else {
+                       if (wrapindex == MAXANCACHE) {
+                               wrapindex = 0;
+                       }
+                       cache_slot = wrapindex++;
+               }
+       }
+
+       /* invariant: cache_slot now points at some slot
+        * in cache.
+        */
+       if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
+               log(LOG_ERR, "an_cache_store, bad index: %d of "
+                   "[0..%d], gross cache error\n",
+                   cache_slot, MAXANCACHE);
+               return;
+       }
+
+       /*  store items in cache
+        *  .ip source address
+        *  .mac src
+        *  .signal, etc.
+        */
+       if (saanp) {
+               sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
+       }
+       bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc,  6);
+
+       sc->an_sigcache[cache_slot].signal = rx_quality;
+
+       return;
+}
+#endif
diff --git a/sys/dev/ic/anreg.h b/sys/dev/ic/anreg.h
new file mode 100644 (file)
index 0000000..e446c66
--- /dev/null
@@ -0,0 +1,850 @@
+/*     $OpenBSD: anreg.h,v 1.1 2000/04/03 01:01:59 mickey Exp $        */
+
+/*
+ * Copyright (c) 1997, 1998, 1999
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/an/if_anreg.h,v 1.1 2000/01/14 20:40:56 wpaul Exp $
+ */
+
+#define AN_TIMEOUT     65536
+
+/* Default network name: ANY */
+#define AN_DEFAULT_NETNAME     "ANY"
+
+/* The nodename must be less than 16 bytes */
+#define AN_DEFAULT_NODENAME    "FreeBSD"
+
+#define AN_DEFAULT_IBSS                "FreeBSD IBSS"
+
+/*
+ * register space access macros
+ */
+#define CSR_WRITE_2(sc, reg, val)      \
+       bus_space_write_2(sc->an_btag, sc->an_bhandle, reg, val)
+
+#define CSR_READ_2(sc, reg)            \
+       bus_space_read_2(sc->an_btag, sc->an_bhandle, reg)
+
+#define CSR_WRITE_1(sc, reg, val)      \
+       bus_space_write_1(sc->an_btag, sc->an_bhandle, reg, val)
+
+#define CSR_READ_1(sc, reg)            \
+       bus_space_read_1(sc->an_btag, sc->an_bhandle, reg)
+
+/*
+ * Size of Aironet I/O space.
+ */
+#define AN_IOSIZ               0x40
+
+/*
+ * Hermes register definitions and what little I know about them.
+ */
+
+/* Hermes command/status registers. */
+#define AN_COMMAND             0x00
+#define AN_PARAM0              0x02
+#define AN_PARAM1              0x04
+#define AN_PARAM2              0x06
+#define AN_STATUS              0x08
+#define AN_RESP0               0x0A
+#define AN_RESP1               0x0C
+#define AN_RESP2               0x0E
+#define AN_LINKSTAT            0x10
+
+/* Command register */
+#define AN_CMD_BUSY            0x8000 /* busy bit */
+#define AN_CMD_NO_ACK          0x0080 /* don't acknowledge command */
+#define AN_CMD_CODE_MASK       0x003F
+#define AN_CMD_QUAL_MASK       0x7F00
+
+/* Command codes */
+#define AN_CMD_NOOP            0x0000 /* no-op */
+#define AN_CMD_ENABLE          0x0001 /* enable */
+#define AN_CMD_DISABLE         0x0002 /* disable */
+#define AN_CMD_FORCE_SYNCLOSS  0x0003 /* force loss of sync */
+#define AN_CMD_FW_RESTART      0x0004 /* firmware resrart */
+#define AN_CMD_HOST_SLEEP      0x0005
+#define AN_CMD_MAGIC_PKT       0x0006
+#define AN_CMD_READCFG         0x0008
+#define AN_CMD_ALLOC_MEM       0x000A /* allocate NIC memory */
+#define AN_CMD_TX              0x000B /* transmit */
+#define AN_CMD_DEALLOC_MEM     0x000C
+#define AN_CMD_NOOP2           0x0010
+#define AN_CMD_ACCESS          0x0021
+#define AN_CMD_ALLOC_BUF       0x0028
+#define AN_CMD_PSP_NODES       0x0030
+#define AN_CMD_SET_PHYREG      0x003E
+#define AN_CMD_TX_TEST         0x003F
+#define AN_CMD_SLEEP           0x0085
+#define AN_CMD_SAVECFG         0x0108
+
+/*
+ * Reclaim qualifier bit, applicable to the
+ * TX command.
+ */
+#define AN_RECLAIM             0x0100 /* reclaim NIC memory */
+
+/*
+ * ACCESS command qualifier bits.
+ */
+#define AN_ACCESS_READ         0x0000
+#define AN_ACCESS_WRITE                0x0100
+
+/*
+ * PROGRAM command qualifier bits.
+ */
+#define AN_PROGRAM_DISABLE     0x0000
+#define AN_PROGRAM_ENABLE_RAM  0x0100
+#define AN_PROGRAM_ENABLE_NVRAM        0x0200
+#define AN_PROGRAM_NVRAM       0x0300
+
+/* Status register values */
+#define AN_STAT_CMD_CODE       0x003F
+#define AN_STAT_CMD_RESULT     0x7F00
+
+/* Linkstat register */
+#define AN_LINKSTAT_ASSOCIATED         0x0400
+#define AN_LINKSTAT_AUTHFAIL           0x0300
+#define AN_LINKSTAT_ASSOC_FAIL         0x8400
+#define AN_LINKSTAT_DISASSOC           0x8200
+#define AN_LINKSTAT_DEAUTH             0x8100
+#define AN_LINKSTAT_SYNCLOST_TSF       0x8004
+#define AN_LINKSTAT_SYNCLOST_HOSTREQ   0x8003
+#define AN_LINKSTAT_SYNCLOST_AVGRETRY  0x8002
+#define AN_LINKSTAT_SYNCLOST_MAXRETRY  0x8001
+#define AN_LINKSTAT_SYNCLOST_MISSBEACON        0x8000
+
+/* memory handle management registers */
+#define AN_RX_FID              0x20
+#define AN_ALLOC_FID           0x22
+#define AN_TX_CMP_FID          0x24
+
+/*
+ * Buffer Access Path (BAP) registers.
+ * These are I/O channels. I believe you can use each one for
+ * any desired purpose independently of the other. In general
+ * though, we use BAP1 for reading and writing LTV records and
+ * reading received data frames, and BAP0 for writing transmit
+ * frames. This is a convention though, not a rule.
+ */
+#define AN_SEL0                        0x18
+#define AN_SEL1                        0x1A
+#define AN_OFF0                        0x1C
+#define AN_OFF1                        0x1E
+#define AN_DATA0               0x36
+#define AN_DATA1               0x38
+#define AN_BAP0                        AN_DATA0
+#define AN_BAP1                        AN_DATA1
+
+#define AN_OFF_BUSY            0x8000
+#define AN_OFF_ERR             0x4000
+#define AN_OFF_DONE            0x2000
+#define AN_OFF_DATAOFF         0x0FFF
+
+/* Event registers */
+#define AN_EVENT_STAT          0x30    /* Event status */
+#define AN_INT_EN              0x32    /* Interrupt enable/disable */
+#define AN_EVENT_ACK           0x34    /* Ack event */
+
+/* Events */
+#define AN_EV_CLR_STUCK_BUSY   0x4000  /* clear stuck busy bit */
+#define AN_EV_WAKEREQUEST      0x2000  /* awaken from PSP mode */
+#define AN_EV_AWAKE            0x0100  /* station woke up from PSP mode*/
+#define AN_EV_LINKSTAT         0x0080  /* link status available */
+#define AN_EV_CMD              0x0010  /* command completed */
+#define AN_EV_ALLOC            0x0008  /* async alloc/reclaim completed */
+#define AN_EV_TX_EXC           0x0004  /* async xmit completed with failure */
+#define AN_EV_TX               0x0002  /* async xmit completed succesfully */
+#define AN_EV_RX               0x0001  /* async rx completed */
+
+#define AN_INTRS       \
+       (AN_EV_RX|AN_EV_TX|AN_EV_TX_EXC|AN_EV_ALLOC|AN_EV_LINKSTAT)
+
+/* Host software registers */
+#define AN_SW0                 0x28
+#define AN_SW1                 0x2A
+#define AN_SW2                 0x2C
+#define AN_SW3                 0x2E
+
+#define AN_CNTL                        0x14
+
+#define AN_CNTL_AUX_ENA                0xC000
+#define AN_CNTL_AUX_ENA_STAT   0xC000
+#define AN_CNTL_AUX_DIS_STAT   0x0000
+#define AN_CNTL_AUX_ENA_CNTL   0x8000
+#define AN_CNTL_AUX_DIS_CNTL   0x4000
+
+#define AN_AUX_PAGE            0x3A
+#define AN_AUX_OFFSET          0x3C
+#define AN_AUX_DATA            0x3E
+
+/*
+ * Length, Type, Value (LTV) record definitions and RID values.
+ */
+struct an_ltv_gen {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_val;
+};
+
+/*
+ * General configuration information.
+ */
+#define AN_RID_GENCONFIG       0xFF10
+struct an_ltv_genconfig {
+       /* General configuration. */
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* XXXX */
+       u_int16_t               an_opmode;              /* 0x02 */
+       u_int16_t               an_rxmode;              /* 0x04 */
+       u_int16_t               an_fragthresh;          /* 0x06 */
+       u_int16_t               an_rtsthresh;           /* 0x08 */
+       u_int8_t                an_macaddr[6];          /* 0x0A */
+       u_int8_t                an_rates[8];            /* 0x10 */
+       u_int16_t               an_shortretry_limit;    /* 0x18 */
+       u_int16_t               an_longretry_limit;     /* 0x1A */
+       u_int16_t               an_tx_msdu_lifetime;    /* 0x1C */
+       u_int16_t               an_rx_msdu_lifetime;    /* 0x1E */
+       u_int16_t               an_stationary;          /* 0x20 */
+       u_int16_t               an_ordering;            /* 0x22 */
+       u_int16_t               an_devtype;             /* 0x24 */
+       u_int16_t               an_rsvd0[5];            /* 0x26 */
+       /* Scanning associating. */
+       u_int16_t               an_scanmode;            /* 0x30 */
+       u_int16_t               an_probedelay;          /* 0x32 */
+       u_int16_t               an_probe_energy_timeout;/* 0x34 */
+       u_int16_t               an_probe_response_timeout;/*0x36 */
+       u_int16_t               an_beacon_listen_timeout;/*0x38 */
+       u_int16_t               an_ibss_join_net_timeout;/*0x3A */
+       u_int16_t               an_auth_timeout;        /* 0x3C */
+       u_int16_t               an_authtype;            /* 0x3E */
+       u_int16_t               an_assoc_timeout;       /* 0x40 */
+       u_int16_t               an_specified_ap_timeout;/* 0x42 */
+       u_int16_t               an_offline_scan_interval;/*0x44 */
+       u_int16_t               an_offline_scan_duration;/*0x46 */
+       u_int16_t               an_link_loss_delay;     /* 0x48 */
+       u_int16_t               an_max_beacon_lost_time;/* 0x4A */
+       u_int16_t               an_refresh_interval;    /* 0x4C */
+       u_int16_t               an_rsvd1;               /* 0x4E */
+       /* Power save operation */
+       u_int16_t               an_psave_mode;          /* 0x50 */
+       u_int16_t               an_sleep_for_dtims;     /* 0x52 */
+       u_int16_t               an_listen_interval;     /* 0x54 */
+       u_int16_t               an_fast_listen_interval;/* 0x56 */
+       u_int16_t               an_listen_decay;        /* 0x58 */
+       u_int16_t               an_fast_listen_decay;   /* 0x5A */
+       u_int16_t               an_rsvd2[2];            /* 0x5C */
+       /* Ad-hoc (or AP) operation. */
+       u_int16_t               an_beacon_period;       /* 0x60 */
+       u_int16_t               an_atim_duration;       /* 0x62 */
+       u_int16_t               an_rsvd3;               /* 0x64 */
+       u_int16_t               an_ds_channel;          /* 0x66 */
+       u_int16_t               an_rsvd4;               /* 0x68 */
+       u_int16_t               an_dtim_period;         /* 0x6A */
+       u_int16_t               an_rsvd5[2];            /* 0x6C */
+       /* Radio operation. */
+       u_int16_t               an_radiotype;           /* 0x70 */
+       u_int16_t               an_diversity;           /* 0x72 */
+       u_int16_t               an_tx_power;            /* 0x74 */
+       u_int16_t               an_rss_thresh;          /* 0x76 */
+       u_int16_t               an_rsvd6[4];            /* 0x78 */
+       /* Aironet extensions. */
+       u_int8_t                an_nodename[16];        /* 0x80 */
+       u_int16_t               an_arl_thresh;          /* 0x90 */
+       u_int16_t               an_arl_decay;           /* 0x92 */
+       u_int16_t               an_arl_delay;           /* 0x94 */
+       u_int8_t                an_rsvd7;               /* 0x96 */
+       u_int8_t                an_rsvd8;               /* 0x97 */
+       u_int8_t                an_magic_packet_action; /* 0x98 */
+       u_int8_t                an_magic_packet_ctl;    /* 0x99 */
+       u_int16_t               an_rsvd9;
+};
+
+#define AN_OPMODE_IBSS_ADHOC                   0x0000
+#define AN_OPMODE_INFRASTRUCTURE_STATION       0x0001
+#define AN_OPMODE_AP                           0x0002
+#define AN_OPMODE_AP_REPEATER                  0x0003
+#define AN_OPMODE_UNMODIFIED_PAYLOAD           0x0100
+#define AN_OPMODE_AIRONET_EXTENSIONS           0x0200
+#define AN_OPMODE_AP_EXTENSIONS                        0x0400
+
+#define AN_RXMODE_BC_MC_ADDR                   0x0000
+#define AN_RXMODE_BC_ADDR                      0x0001
+#define AN_RXMODE_ADDR                         0x0002
+#define AN_RXMODE_80211_MONITOR_CURBSS         0x0003
+#define AN_RXMODE_80211_MONITOR_ANYBSS         0x0004
+#define AN_RXMODE_LAN_MONITOR_CURBSS           0x0005
+#define AN_RXMODE_NO_8023_HEADER               0x0100
+
+#define AN_RATE_1MBPS                          0x0002
+#define AN_RATE_2MBPS                          0x0004
+#define AN_RATE_5_5MBPS                                0x000B
+#define AN_RATE_11MBPS                         0x0016
+
+#define AN_DEVTYPE_PC4500                      0x0065
+#define AN_DEVTYPE_PC4800                      0x006D
+
+#define AN_SCANMODE_ACTIVE                     0x0000
+#define AN_SCANMODE_PASSIVE                    0x0001
+#define AN_SCANMODE_AIRONET_ACTIVE             0x0002
+
+#define AN_AUTHTYPE_NONE                       0x0000
+#define AN_AUTHTYPE_OPEN                       0x0001
+#define AN_AUTHTYPE_SHAREDKEY                  0x0002
+#define AN_AUTHTYPE_EXCLUDE_UNENCRYPTED                0x0004
+
+#define AN_PSAVE_NONE                          0x0000
+#define AN_PSAVE_CAM                           0x0001
+#define AN_PSAVE_PSP                           0x0002
+#define AN_PSAVE_PSP_CAM                       0x0003
+
+#define AN_RADIOTYPE_80211_FH                  0x0001
+#define AN_RADIOTYPE_80211_DS                  0x0002
+#define AN_RADIOTYPE_LM2000_DS                 0x0004
+
+#define AN_DIVERSITY_FACTORY_DEFAULT           0x0000
+#define AN_DIVERSITY_ANTENNA_1_ONLY            0x0001
+#define AN_DIVERSITY_ANTENNA_2_ONLY            0x0002
+#define AN_DIVERSITY_ANTENNA_1_AND_2           0x0003
+
+#define AN_TXPOWER_FACTORY_DEFAULT             0x0000
+#define AN_TXPOWER_50MW                                50
+#define AN_TXPOWER_100MW                       100
+#define AN_TXPOWER_250MW                       250
+
+/*
+ * Valid SSID list. You can specify up to three SSIDs denoting
+ * the service sets that you want to join. The first SSID always
+ * defaults to "tsunami" which is a handy way to detect the
+ * card.
+ */
+#define AN_RID_SSIDLIST                0xFF11
+struct an_ltv_ssidlist {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_ssid1_len;
+       char                    an_ssid1[32];
+       u_int16_t               an_ssid2_len;
+       char                    an_ssid2[32];
+       u_int16_t               an_ssid3_len;
+       char                    an_ssid3[32];
+};
+
+#define AN_DEF_SSID_LEN                7
+#define AN_DEF_SSID            "tsunami"
+
+/*
+ * Valid AP list.
+ */
+#define AN_RID_APLIST          0xFF12
+struct an_ltv_aplist {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int8_t                an_ap1[8];
+       u_int8_t                an_ap2[8];
+       u_int8_t                an_ap3[8];
+       u_int8_t                an_ap4[8];
+};
+
+/*
+ * Driver name.
+ */
+#define AN_RID_DRVNAME         0xFF13
+struct an_ltv_drvname {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int8_t                an_drvname[16];
+};
+
+/*
+ * Frame encapsulation.
+ */
+#define AN_RID_ENCAP           0xFF14
+struct an_rid_encap {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_ethertype_default;
+       u_int16_t               an_action_default;
+       u_int16_t               an_ethertype0;
+       u_int16_t               an_action0;
+       u_int16_t               an_ethertype1;
+       u_int16_t               an_action1;
+       u_int16_t               an_ethertype2;
+       u_int16_t               an_action2;
+       u_int16_t               an_ethertype3;
+       u_int16_t               an_action3;
+       u_int16_t               an_ethertype4;
+       u_int16_t               an_action4;
+       u_int16_t               an_ethertype5;
+       u_int16_t               an_action5;
+       u_int16_t               an_ethertype6;
+       u_int16_t               an_action6;
+};
+
+#define AN_ENCAP_ACTION_RX     0x0001
+#define AN_ENCAP_ACTION_TX     0x0002
+
+#define AN_RXENCAP_NONE                0x0000
+#define AN_RXENCAP_RFC1024     0x0001
+
+#define AN_TXENCAP_RFC1024     0x0000
+#define AN_TXENCAP_80211       0x0002
+
+/*
+ * Actual config, same structure as general config (read only).
+ */
+#define AN_RID_ACTUALCFG       0xFF20
+
+/*
+ * Card capabilities (read only).
+ */
+#define AN_RID_CAPABILITIES    0xFF00
+struct an_ltv_caps {
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* XXXX */
+       u_int8_t                an_oui[3];              /* 0x02 */
+       u_int8_t                an_rsvd0;               /* 0x05 */
+       u_int16_t               an_prodnum;             /* 0x06 */
+       u_int8_t                an_manufname[32];       /* 0x08 */
+       u_int8_t                an_prodname[16];        /* 0x28 */
+       u_int8_t                an_prodvers[8];         /* 0x38 */
+       u_int8_t                an_oemaddr[6];          /* 0x40 */
+       u_int8_t                an_aironetaddr[6];      /* 0x46 */
+       u_int16_t               an_radiotype;           /* 0x4C */
+       u_int16_t               an_regdomain;           /* 0x4E */
+       u_int8_t                an_callid[6];           /* 0x50 */
+       u_int8_t                an_rates[8];            /* 0x56 */
+       u_int8_t                an_rx_diversity;        /* 0x5E */
+       u_int8_t                an_tx_diversity;        /* 0x5F */
+       u_int16_t               an_tx_powerlevels[8];   /* 0x60 */
+       u_int16_t               an_hwrev;               /* 0x70 */
+       u_int16_t               an_hwcaps;              /* 0x72 */
+       u_int16_t               an_temprange;           /* 0x74 */
+       u_int16_t               an_fwrev;               /* 0x76 */
+       u_int16_t               an_fwsubrev;            /* 0x78 */
+       u_int16_t               an_ifacerev;            /* 0x7A */
+       u_int16_t               an_softcaps;            /* 0x7C */
+       u_int16_t               an_bootblockrev;        /* 0x7E */
+};
+
+/*
+ * Access point (read only)
+ */
+#define AN_RID_APINFO          0xFF01
+struct an_ltv_apinfo {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_tim_addr;
+       u_int16_t               an_airo_addr;
+};
+
+/*
+ * Radio info (read only).
+ */
+#define AN_RID_RADIOINFO       0xFF02
+struct an_ltv_radioinfo {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       /* ??? */
+};
+
+/*
+ * Status (read only). Note: the manual claims this RID is 108 bytes
+ * long (0x6A is the last datum, which is 2 bytes long) however when
+ * this RID is read from the NIC, it returns a length of 110. To be
+ * on the safe side, this structure is padded with an extra 16-bit
+ * word. (There is a misprint in the manual which says the macaddr
+ * field is 8 bytes long.)
+ *
+ * Also, the channel_set and current_channel fields appear to be
+ * reversed. Either that, or the hop_period field is unused.
+ */
+#define AN_RID_STATUS          0xFF50
+struct an_ltv_status {
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* 0xXX */
+       u_int8_t                an_macaddr[6];          /* 0x02 */
+       u_int16_t               an_opmode;              /* 0x08 */
+       u_int16_t               an_errcode;             /* 0x0A */
+       u_int16_t               an_cur_signal_quality;  /* 0x0C */
+       u_int16_t               an_ssidlen;             /* 0x0E */
+       u_int8_t                an_ssid[32];            /* 0x10 */
+       u_int8_t                an_ap_name[16];         /* 0x30 */
+       u_int8_t                an_cur_bssid[6];        /* 0x40 */
+       u_int8_t                an_prev_bssid1[6];      /* 0x46 */
+       u_int8_t                an_prev_bssid2[6];      /* 0x4C */
+       u_int8_t                an_prev_bssid3[6];      /* 0x52 */
+       u_int16_t               an_beacon_period;       /* 0x58 */
+       u_int16_t               an_dtim_period;         /* 0x5A */
+       u_int16_t               an_atim_duration;       /* 0x5C */
+       u_int16_t               an_hop_period;          /* 0x5E */
+       u_int16_t               an_cur_channel;         /* 0x62 */
+       u_int16_t               an_channel_set;         /* 0x60 */
+       u_int16_t               an_hops_to_backbone;    /* 0x64 */
+       u_int16_t               an_ap_total_load;       /* 0x66 */
+       u_int16_t               an_our_generated_load;  /* 0x68 */
+       u_int16_t               an_accumulated_arl;     /* 0x6A */
+       u_int16_t               an_rsvd0[10];           /* 0x6C */
+};
+
+#define AN_STATUS_OPMODE_CONFIGURED            0x0001
+#define AN_STATUS_OPMODE_MAC_ENABLED           0x0002
+#define AN_STATUS_OPMODE_RX_ENABLED            0x0004
+#define AN_STATUS_OPMODE_IN_SYNC               0x0010
+#define AN_STATUS_OPMODE_ASSOCIATED            0x0020
+#define AN_STATUS_OPMODE_ERROR                 0x8000
+
+
+/*
+ * Statistics
+ */
+#define AN_RID_16BITS_CUM      0xFF60  /* Cumulative 16-bit stats counters */
+#define AN_RID_16BITS_DELTA    0xFF61  /* 16-bit stats (since last clear) */
+#define AN_RID_16BITS_DELTACLR 0xFF62  /* 16-bit stats, clear on read */
+#define AN_RID_32BITS_CUM      0xFF68  /* Cumulative 32-bit stats counters */
+#define AN_RID_32BITS_DELTA    0xFF69  /* 32-bit stats (since last clear) */
+#define AN_RID_32BITS_DELTACLR 0xFF6A  /* 32-bit stats, clear on read */
+
+/*
+ * Grrr. The manual says the statistics record is 384 bytes in length,
+ * but the card says the record is 404 bytes. There's some padding left
+ * at the end of this structure to account for any discrepancies.
+ */
+struct an_ltv_stats {
+       u_int16_t               an_fudge;
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* 0xXX */
+       u_int16_t               an_spacer;              /* 0x02 */
+       u_int32_t               an_rx_overruns;         /* 0x04 */
+       u_int32_t               an_rx_plcp_csum_errs;   /* 0x08 */
+       u_int32_t               an_rx_plcp_format_errs; /* 0x0C */
+       u_int32_t               an_rx_plcp_len_errs;    /* 0x10 */
+       u_int32_t               an_rx_mac_crc_errs;     /* 0x14 */
+       u_int32_t               an_rx_mac_crc_ok;       /* 0x18 */
+       u_int32_t               an_rx_wep_errs;         /* 0x1C */
+       u_int32_t               an_rx_wep_ok;           /* 0x20 */
+       u_int32_t               an_retry_long;          /* 0x24 */
+       u_int32_t               an_retry_short;         /* 0x28 */
+       u_int32_t               an_retry_max;           /* 0x2C */
+       u_int32_t               an_no_ack;              /* 0x30 */
+       u_int32_t               an_no_cts;              /* 0x34 */
+       u_int32_t               an_rx_ack_ok;           /* 0x38 */
+       u_int32_t               an_rx_cts_ok;           /* 0x3C */
+       u_int32_t               an_tx_ack_ok;           /* 0x40 */
+       u_int32_t               an_tx_rts_ok;           /* 0x44 */
+       u_int32_t               an_tx_cts_ok;           /* 0x48 */
+       u_int32_t               an_tx_lmac_mcasts;      /* 0x4C */
+       u_int32_t               an_tx_lmac_bcasts;      /* 0x50 */
+       u_int32_t               an_tx_lmac_ucast_frags; /* 0x54 */
+       u_int32_t               an_tx_lmac_ucasts;      /* 0x58 */
+       u_int32_t               an_tx_beacons;          /* 0x5C */
+       u_int32_t               an_rx_beacons;          /* 0x60 */
+       u_int32_t               an_tx_single_cols;      /* 0x64 */
+       u_int32_t               an_tx_multi_cols;       /* 0x68 */
+       u_int32_t               an_tx_defers_no;        /* 0x6C */
+       u_int32_t               an_tx_defers_prot;      /* 0x70 */
+       u_int32_t               an_tx_defers_energy;    /* 0x74 */
+       u_int32_t               an_rx_dups;             /* 0x78 */
+       u_int32_t               an_rx_partial;          /* 0x7C */
+       u_int32_t               an_tx_too_old;          /* 0x80 */
+       u_int32_t               an_rx_too_old;          /* 0x84 */
+       u_int32_t               an_lostsync_max_retries;/* 0x88 */
+       u_int32_t               an_lostsync_missed_beacons;/* 0x8C */
+       u_int32_t               an_lostsync_arl_exceeded;/*0x90 */
+       u_int32_t               an_lostsync_deauthed;   /* 0x94 */
+       u_int32_t               an_lostsync_disassociated;/*0x98 */
+       u_int32_t               an_lostsync_tsf_timing; /* 0x9C */
+       u_int32_t               an_tx_host_mcasts;      /* 0xA0 */
+       u_int32_t               an_tx_host_bcasts;      /* 0xA4 */
+       u_int32_t               an_tx_host_ucasts;      /* 0xA8 */
+       u_int32_t               an_tx_host_failed;      /* 0xAC */
+       u_int32_t               an_rx_host_mcasts;      /* 0xB0 */
+       u_int32_t               an_rx_host_bcasts;      /* 0xB4 */
+       u_int32_t               an_rx_host_ucasts;      /* 0xB8 */
+       u_int32_t               an_rx_host_discarded;   /* 0xBC */
+       u_int32_t               an_tx_hmac_mcasts;      /* 0xC0 */
+       u_int32_t               an_tx_hmac_bcasts;      /* 0xC4 */
+       u_int32_t               an_tx_hmac_ucasts;      /* 0xC8 */
+       u_int32_t               an_tx_hmac_failed;      /* 0xCC */
+       u_int32_t               an_rx_hmac_mcasts;      /* 0xD0 */
+       u_int32_t               an_rx_hmac_bcasts;      /* 0xD4 */
+       u_int32_t               an_rx_hmac_ucasts;      /* 0xD8 */
+       u_int32_t               an_rx_hmac_discarded;   /* 0xDC */
+       u_int32_t               an_tx_hmac_accepted;    /* 0xE0 */
+       u_int32_t               an_ssid_mismatches;     /* 0xE4 */
+       u_int32_t               an_ap_mismatches;       /* 0xE8 */
+       u_int32_t               an_rates_mismatches;    /* 0xEC */
+       u_int32_t               an_auth_rejects;        /* 0xF0 */
+       u_int32_t               an_auth_timeouts;       /* 0xF4 */
+       u_int32_t               an_assoc_rejects;       /* 0xF8 */
+       u_int32_t               an_assoc_timeouts;      /* 0xFC */
+       u_int32_t               an_reason_outside_table;/* 0x100 */
+       u_int32_t               an_reason1;             /* 0x104 */
+       u_int32_t               an_reason2;             /* 0x108 */
+       u_int32_t               an_reason3;             /* 0x10C */
+       u_int32_t               an_reason4;             /* 0x110 */
+       u_int32_t               an_reason5;             /* 0x114 */
+       u_int32_t               an_reason6;             /* 0x118 */
+       u_int32_t               an_reason7;             /* 0x11C */
+       u_int32_t               an_reason8;             /* 0x120 */
+       u_int32_t               an_reason9;             /* 0x124 */
+       u_int32_t               an_reason10;            /* 0x128 */
+       u_int32_t               an_reason11;            /* 0x12C */
+       u_int32_t               an_reason12;            /* 0x130 */
+       u_int32_t               an_reason13;            /* 0x134 */
+       u_int32_t               an_reason14;            /* 0x138 */
+       u_int32_t               an_reason15;            /* 0x13C */
+       u_int32_t               an_reason16;            /* 0x140 */
+       u_int32_t               an_reason17;            /* 0x144 */
+       u_int32_t               an_reason18;            /* 0x148 */
+       u_int32_t               an_reason19;            /* 0x14C */
+       u_int32_t               an_rx_mgmt_pkts;        /* 0x150 */
+       u_int32_t               an_tx_mgmt_pkts;        /* 0x154 */
+       u_int32_t               an_rx_refresh_pkts;     /* 0x158 */
+       u_int32_t               an_tx_refresh_pkts;     /* 0x15C */
+       u_int32_t               an_rx_poll_pkts;        /* 0x160 */
+       u_int32_t               an_tx_poll_pkts;        /* 0x164 */
+       u_int32_t               an_host_retries;        /* 0x168 */
+       u_int32_t               an_lostsync_hostreq;    /* 0x16C */
+       u_int32_t               an_host_tx_bytes;       /* 0x170 */
+       u_int32_t               an_host_rx_bytes;       /* 0x174 */
+       u_int32_t               an_uptime_usecs;        /* 0x178 */
+       u_int32_t               an_uptime_secs;         /* 0x17C */
+       u_int32_t               an_lostsync_better_ap;  /* 0x180 */
+       u_int32_t               an_rsvd[10];
+};
+
+/*
+ * Receive frame structure.
+ */
+struct an_rxframe {
+       u_int32_t               an_rx_time;             /* 0x00 */
+       u_int16_t               an_rx_status;           /* 0x04 */
+       u_int16_t               an_rx_payload_len;      /* 0x06 */
+       u_int8_t                an_rsvd0;               /* 0x08 */
+       u_int8_t                an_rx_signal_strength;  /* 0x09 */
+       u_int8_t                an_rx_rate;             /* 0x0A */
+       u_int8_t                an_rx_chan;             /* 0x0B */
+       u_int8_t                an_rx_assoc_cnt;        /* 0x0C */
+       u_int8_t                an_rsvd1[3];            /* 0x0D */
+       u_int8_t                an_plcp_hdr[4];         /* 0x10 */
+       u_int16_t               an_frame_ctl;           /* 0x14 */
+       u_int16_t               an_duration;            /* 0x16 */
+       u_int8_t                an_addr1[6];            /* 0x18 */
+       u_int8_t                an_addr2[6];            /* 0x1E */
+       u_int8_t                an_addr3[6];            /* 0x24 */
+       u_int16_t               an_seq_ctl;             /* 0x2A */
+       u_int8_t                an_addr4[6];            /* 0x2C */
+       u_int16_t               an_gaplen;              /* 0x32 */
+};
+
+#define AN_RXGAP_MAX   8
+
+/*
+ * Transmit frame structure.
+ */
+struct an_txframe {
+       u_int32_t               an_tx_sw;               /* 0x00 */
+       u_int16_t               an_tx_status;           /* 0x04 */
+       u_int16_t               an_tx_payload_len;      /* 0x06 */
+       u_int16_t               an_tx_ctl;              /* 0x08 */
+       u_int16_t               an_tx_assoc_id;         /* 0x0A */
+       u_int16_t               an_tx_retry;            /* 0x0C */
+       u_int8_t                an_tx_assoc_cnt;        /* 0x0E */
+       u_int8_t                an_tx_rate;             /* 0x0F */
+       u_int8_t                an_tx_max_long_retries; /* 0x10 */
+       u_int8_t                an_tx_max_short_retries; /*0x11 */
+       u_int8_t                an_rsvd0[2];            /* 0x12 */
+       u_int16_t               an_frame_ctl;           /* 0x14 */
+       u_int16_t               an_duration;            /* 0x16 */
+       u_int8_t                an_addr1[6];            /* 0x18 */
+       u_int8_t                an_addr2[6];            /* 0x1E */
+       u_int8_t                an_addr3[6];            /* 0x24 */
+       u_int16_t               an_seq_ctl;             /* 0x2A */
+       u_int8_t                an_addr4[6];            /* 0x2C */
+       u_int16_t               an_gaplen;              /* 0x32 */
+};
+
+struct an_rxframe_802_3 {
+       u_int16_t               an_rx_802_3_status;     /* 0x34 */
+       u_int16_t               an_rx_802_3_payload_len;/* 0x36 */
+       u_int8_t                an_rx_dst_addr[6];      /* 0x38 */
+       u_int8_t                an_rx_src_addr[6];      /* 0x3E */
+};
+#define AN_RXGAP_MAX   8
+
+
+struct an_txframe_802_3 {
+/*
+ * Transmit 802.3 header structure.
+ */
+       u_int16_t               an_tx_802_3_status;     /* 0x34 */
+       u_int16_t               an_tx_802_3_payload_len;/* 0x36 */
+       u_int8_t                an_tx_dst_addr[6];      /* 0x38 */
+       u_int8_t                an_tx_src_addr[6];      /* 0x3E */
+};
+
+#define AN_TXSTAT_EXCESS_RETRY 0x0002
+#define AN_TXSTAT_LIFE_EXCEEDED        0x0004
+#define AN_TXSTAT_AID_FAIL     0x0008
+#define AN_TXSTAT_MAC_DISABLED 0x0010
+#define AN_TXSTAT_ASSOC_LOST   0x0020
+
+#define AN_TXCTL_RSVD          0x0001
+#define AN_TXCTL_TXOK_INTR     0x0002
+#define AN_TXCTL_TXERR_INTR    0x0004
+#define AN_TXCTL_HEADER_TYPE   0x0008
+#define AN_TXCTL_PAYLOAD_TYPE  0x0010
+#define AN_TXCTL_NORELEASE     0x0020
+#define AN_TXCTL_NORETRIES     0x0040
+#define AN_TXCTL_CLEAR_AID     0x0080
+#define AN_TXCTL_STRICT_ORDER  0x0100
+#define AN_TXCTL_USE_RTS       0x0200
+
+#define AN_HEADERTYPE_8023     0x0000
+#define AN_HEADERTYPE_80211    0x0008
+
+#define AN_PAYLOADTYPE_ETHER   0x0000
+#define AN_PAYLOADTYPE_LLC     0x0010
+
+#define AN_TXCTL_80211 \
+       (AN_TXCTL_TXOK_INTR|AN_TXCTL_TXERR_INTR|AN_HEADERTYPE_80211|    \
+       AN_PAYLOADTYPE_LLC|AN_TXCTL_NORELEASE)
+
+#define AN_TXCTL_8023  \
+       (AN_TXCTL_TXOK_INTR|AN_TXCTL_TXERR_INTR|AN_HEADERTYPE_8023|     \
+       AN_PAYLOADTYPE_ETHER|AN_TXCTL_NORELEASE)
+
+#define AN_TXGAP_80211         0
+#define AN_TXGAP_8023          0
+
+struct an_802_3_hdr {
+       u_int16_t               an_8023_status;
+       u_int16_t               an_8023_payload_len;
+       u_int8_t                an_8023_dst_addr[6];
+       u_int8_t                an_8023_src_addr[6];
+       u_int16_t               an_8023_dat[3]; /* SNAP header */
+       u_int16_t               an_8023_type;
+};
+
+struct an_snap_hdr {
+       u_int16_t               an_snap_dat[3]; /* SNAP header */
+       u_int16_t               an_snap_type;
+};
+
+#define AN_TX_RING_CNT         4
+#define AN_INC(x, y)           (x) = (x + 1) % y
+
+struct an_tx_ring_data {
+       u_int16_t               an_tx_fids[AN_TX_RING_CNT];
+       u_int16_t               an_tx_ring[AN_TX_RING_CNT];
+       int                     an_tx_prod;
+       int                     an_tx_cons;
+};
+
+struct an_softc        {
+       struct device   sc_dev;
+       struct arpcom   arpcom;
+       void            *sc_ih;
+
+       bus_space_tag_t         an_btag;
+       bus_space_handle_t      an_bhandle;
+
+       struct an_ltv_genconfig an_config;
+       struct an_ltv_caps      an_caps;
+       struct an_ltv_ssidlist  an_ssidlist;
+       struct an_ltv_aplist    an_aplist;
+       int                     an_tx_rate;
+       int                     an_rxmode;
+       int                     an_gone;
+       int                     an_if_flags;
+       u_int8_t                an_txbuf[1536];
+       struct an_tx_ring_data  an_rdata;
+       struct an_ltv_stats     an_stats;
+       struct an_ltv_status    an_status;
+       u_int8_t                an_associated;
+#ifdef ANCACHE
+       int                     an_cache_iponly;
+       int                     an_cache_mcastonly;
+
+       int                     an_sigitems;
+       struct an_sigcache      an_sigcache[MAXANCACHE];
+       int                     an_nextitem;
+#endif
+       struct timeout          an_stat_ch;
+};
+
+void   an_release_resources    __P((struct device *));
+int    an_alloc_port           __P((struct device *, int, int));
+int    an_alloc_memory         __P((struct device *, int, int));
+int    an_alloc_irq            __P((struct device *, int, int));
+int    an_probe                __P((struct device *));
+void   an_shutdown             __P((void *));
+int    an_attach               __P((struct an_softc *));
+void   an_init                 __P((struct an_softc *));
+void    an_stop                        __P((struct an_softc *));
+int    an_intr                 __P((void *));
+
+#define AN_802_3_OFFSET                0x2E
+#define AN_802_11_OFFSET       0x44
+#define AN_802_11_OFFSET_RAW   0x3C
+
+#define AN_STAT_BADCRC         0x0001
+#define AN_STAT_UNDECRYPTABLE  0x0002
+#define AN_STAT_ERRSTAT                0x0003
+#define AN_STAT_MAC_PORT       0x0700
+#define AN_STAT_1042           0x2000  /* RFC1042 encoded */
+#define AN_STAT_TUNNEL         0x4000  /* Bridge-tunnel encoded */
+#define AN_STAT_WMP_MSG                0x6000  /* WaveLAN-II management protocol */
+#define AN_RXSTAT_MSG_TYPE     0xE000
+
+#define AN_ENC_TX_802_3                0x00
+#define AN_ENC_TX_802_11       0x11
+#define AN_ENC_TX_E_II         0x0E
+
+#define AN_ENC_TX_1042         0x00
+#define AN_ENC_TX_TUNNEL       0xF8
+
+#define AN_TXCNTL_MACPORT      0x00FF
+#define AN_TXCNTL_STRUCTTYPE   0xFF00
+
+/*
+ * SNAP (sub-network access protocol) constants for transmission
+ * of IP datagrams over IEEE 802 networks, taken from RFC1042.
+ * We need these for the LLC/SNAP header fields in the TX/RX frame
+ * structure.
+ */
+#define AN_SNAP_K1             0xaa    /* assigned global SAP for SNAP */
+#define AN_SNAP_K2             0x00
+#define AN_SNAP_CONTROL                0x03    /* unnumbered information format */
+#define AN_SNAP_WORD0          (AN_SNAP_K1 | (AN_SNAP_K1 << 8))
+#define AN_SNAP_WORD1          (AN_SNAP_K2 | (AN_SNAP_CONTROL << 8))
+#define AN_SNAPHDR_LEN         0x6
diff --git a/sys/dev/ic/anvar.h b/sys/dev/ic/anvar.h
new file mode 100644 (file)
index 0000000..b1eb2c3
--- /dev/null
@@ -0,0 +1,558 @@
+/*     $OpenBSD: anvar.h,v 1.1 2000/04/03 01:01:59 mickey Exp $        */
+
+/*
+ * Copyright (c) 1997, 1998, 1999
+ *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/an/if_aironet_ieee.h,v 1.1 2000/01/14 20:40:55 wpaul Exp $
+ */
+
+#ifndef _IF_AIRONET_IEEE_H
+#define _IF_AIRONET_IEEE_H
+
+/*
+ * This header defines a simple command interface to the FreeBSD
+ * Aironet driver (an) driver, which is used to set certain
+ * device-specific parameters which can't be easily managed through
+ * ifconfig(8). No, sysctl(2) is not the answer. I said a _simple_
+ * interface, didn't I.
+ */
+
+#ifndef SIOCSAIRONET
+#ifdef __FreeBSD__
+#define SIOCSAIRONET   SIOCSIFGENERIC
+#else   /* !__FreeBSD__ */
+#define SIOCSAIRONET   SIOCSIFASYNCMAP
+#endif
+#endif
+
+#ifndef SIOCGAIRONET
+#ifdef __FreeBSD__
+#define SIOCGAIRONET   SIOCGIFGENERIC
+#else   /* !__FreeBSD__ */
+#define SIOCGAIRONET   SIOCGIFASYNCMAP
+#endif
+#endif
+
+/*
+ * This is a make-predend RID value used only by the driver
+ * to allow the user to set the speed.
+ */
+#define AN_RID_TX_SPEED                0x1234
+
+/*
+ * Technically I don't think there's a limit to a record
+ * length. The largest record is the one that contains the CIS
+ * data, which is 240 words long, so 256 should be a safe
+ * value.
+ */
+#define AN_MAX_DATALEN 512
+
+struct an_req {
+       u_int16_t       an_len;
+       u_int16_t       an_type;
+       u_int16_t       an_val[AN_MAX_DATALEN];
+};
+
+/*
+ * Private LTV records (interpreted only by the driver). This is
+ * a minor kludge to allow reading the interface statistics from
+ * the driver.
+ */
+#define AN_RID_IFACE_STATS     0x0100
+#define AN_RID_MGMT_XMIT       0x0200
+#ifdef ANCACHE
+#define AN_RID_ZERO_CACHE      0x0300
+#define AN_RID_READ_CACHE      0x0400
+#endif
+
+struct an_80211_hdr {
+       u_int16_t               frame_ctl;
+       u_int16_t               dur_id;
+       u_int8_t                addr1[6];
+       u_int8_t                addr2[6];
+       u_int8_t                addr3[6];
+       u_int16_t               seq_ctl;
+       u_int8_t                addr4[6];
+};
+
+#define AN_FCTL_VERS           0x0002
+#define AN_FCTL_FTYPE          0x000C
+#define AN_FCTL_STYPE          0x00F0
+#define AN_FCTL_TODS           0x0100
+#define AN_FCTL_FROMDS         0x0200
+#define AN_FCTL_MOREFRAGS      0x0400
+#define AN_FCTL_RETRY          0x0800
+#define AN_FCTL_PM             0x1000
+#define AN_FCTL_MOREDATA       0x2000
+#define AN_FCTL_WEP            0x4000
+#define AN_FCTL_ORDER          0x8000
+
+#define AN_FTYPE_MGMT          0x0000
+#define AN_FTYPE_CTL           0x0004
+#define AN_FTYPE_DATA          0x0008
+
+#define AN_STYPE_MGMT_ASREQ    0x0000  /* association request */
+#define AN_STYPE_MGMT_ASRESP   0x0010  /* association response */
+#define AN_STYPE_MGMT_REASREQ  0x0020  /* reassociation request */
+#define AN_STYPE_MGMT_REASRESP 0x0030  /* reassociation response */
+#define AN_STYPE_MGMT_PROBEREQ 0x0040  /* probe request */
+#define AN_STYPE_MGMT_PROBERESP        0x0050  /* probe response */
+#define AN_STYPE_MGMT_BEACON   0x0080  /* beacon */
+#define AN_STYPE_MGMT_ATIM     0x0090  /* announcement traffic ind msg */
+#define AN_STYPE_MGMT_DISAS    0x00A0  /* disassociation */
+#define AN_STYPE_MGMT_AUTH     0x00B0  /* authentication */
+#define AN_STYPE_MGMT_DEAUTH   0x00C0  /* deauthentication */
+
+struct an_mgmt_hdr {
+       u_int16_t               frame_ctl;
+       u_int16_t               duration;
+       u_int8_t                dst_addr[6];
+       u_int8_t                src_addr[6];
+       u_int8_t                bssid[6];
+       u_int16_t               seq_ctl;
+};
+
+/* 
+ * Aironet IEEE signal strength cache
+ *
+ * driver keeps cache of last
+ * MAXANCACHE packets to arrive including signal strength info.
+ * daemons may read this via ioctl
+ *
+ * Each entry in the wi_sigcache has a unique macsrc.
+ */
+#ifdef ANCACHE
+#define MAXANCACHE      10
+
+struct an_sigcache {
+       char    macsrc[6];      /* unique MAC address for entry */
+       int     ipsrc;          /* ip address associated with packet */
+       int     signal;         /* signal strength of the packet */
+       int     noise;          /* noise value */
+       int     quality;        /* quality of the packet */
+};
+#endif
+
+#ifndef _KERNEL
+struct an_ltv_stats {
+       u_int16_t               an_fudge;
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* 0xXX */
+       u_int16_t               an_spacer;              /* 0x02 */
+       u_int32_t               an_rx_overruns;         /* 0x04 */
+       u_int32_t               an_rx_plcp_csum_errs;   /* 0x08 */
+       u_int32_t               an_rx_plcp_format_errs; /* 0x0C */
+       u_int32_t               an_rx_plcp_len_errs;    /* 0x10 */
+       u_int32_t               an_rx_mac_crc_errs;     /* 0x14 */
+       u_int32_t               an_rx_mac_crc_ok;       /* 0x18 */
+       u_int32_t               an_rx_wep_errs;         /* 0x1C */
+       u_int32_t               an_rx_wep_ok;           /* 0x20 */
+       u_int32_t               an_retry_long;          /* 0x24 */
+       u_int32_t               an_retry_short;         /* 0x28 */
+       u_int32_t               an_retry_max;           /* 0x2C */
+       u_int32_t               an_no_ack;              /* 0x30 */
+       u_int32_t               an_no_cts;              /* 0x34 */
+       u_int32_t               an_rx_ack_ok;           /* 0x38 */
+       u_int32_t               an_rx_cts_ok;           /* 0x3C */
+       u_int32_t               an_tx_ack_ok;           /* 0x40 */
+       u_int32_t               an_tx_rts_ok;           /* 0x44 */
+       u_int32_t               an_tx_cts_ok;           /* 0x48 */
+       u_int32_t               an_tx_lmac_mcasts;      /* 0x4C */
+       u_int32_t               an_tx_lmac_bcasts;      /* 0x50 */
+       u_int32_t               an_tx_lmac_ucast_frags; /* 0x54 */
+       u_int32_t               an_tx_lmac_ucasts;      /* 0x58 */
+       u_int32_t               an_tx_beacons;          /* 0x5C */
+       u_int32_t               an_rx_beacons;          /* 0x60 */
+       u_int32_t               an_tx_single_cols;      /* 0x64 */
+       u_int32_t               an_tx_multi_cols;       /* 0x68 */
+       u_int32_t               an_tx_defers_no;        /* 0x6C */
+       u_int32_t               an_tx_defers_prot;      /* 0x70 */
+       u_int32_t               an_tx_defers_energy;    /* 0x74 */
+       u_int32_t               an_rx_dups;             /* 0x78 */
+       u_int32_t               an_rx_partial;          /* 0x7C */
+       u_int32_t               an_tx_too_old;          /* 0x80 */
+       u_int32_t               an_rx_too_old;          /* 0x84 */
+       u_int32_t               an_lostsync_max_retries;/* 0x88 */
+       u_int32_t               an_lostsync_missed_beacons;/* 0x8C */
+       u_int32_t               an_lostsync_arl_exceeded;/*0x90 */
+       u_int32_t               an_lostsync_deauthed;   /* 0x94 */
+       u_int32_t               an_lostsync_disassociated;/*0x98 */
+       u_int32_t               an_lostsync_tsf_timing; /* 0x9C */
+       u_int32_t               an_tx_host_mcasts;      /* 0xA0 */
+       u_int32_t               an_tx_host_bcasts;      /* 0xA4 */
+       u_int32_t               an_tx_host_ucasts;      /* 0xA8 */
+       u_int32_t               an_tx_host_failed;      /* 0xAC */
+       u_int32_t               an_rx_host_mcasts;      /* 0xB0 */
+       u_int32_t               an_rx_host_bcasts;      /* 0xB4 */
+       u_int32_t               an_rx_host_ucasts;      /* 0xB8 */
+       u_int32_t               an_rx_host_discarded;   /* 0xBC */
+       u_int32_t               an_tx_hmac_mcasts;      /* 0xC0 */
+       u_int32_t               an_tx_hmac_bcasts;      /* 0xC4 */
+       u_int32_t               an_tx_hmac_ucasts;      /* 0xC8 */
+       u_int32_t               an_tx_hmac_failed;      /* 0xCC */
+       u_int32_t               an_rx_hmac_mcasts;      /* 0xD0 */
+       u_int32_t               an_rx_hmac_bcasts;      /* 0xD4 */
+       u_int32_t               an_rx_hmac_ucasts;      /* 0xD8 */
+       u_int32_t               an_rx_hmac_discarded;   /* 0xDC */
+       u_int32_t               an_tx_hmac_accepted;    /* 0xE0 */
+       u_int32_t               an_ssid_mismatches;     /* 0xE4 */
+       u_int32_t               an_ap_mismatches;       /* 0xE8 */
+       u_int32_t               an_rates_mismatches;    /* 0xEC */
+       u_int32_t               an_auth_rejects;        /* 0xF0 */
+       u_int32_t               an_auth_timeouts;       /* 0xF4 */
+       u_int32_t               an_assoc_rejects;       /* 0xF8 */
+       u_int32_t               an_assoc_timeouts;      /* 0xFC */
+       u_int32_t               an_reason_outside_table;/* 0x100 */
+       u_int32_t               an_reason1;             /* 0x104 */
+       u_int32_t               an_reason2;             /* 0x108 */
+       u_int32_t               an_reason3;             /* 0x10C */
+       u_int32_t               an_reason4;             /* 0x110 */
+       u_int32_t               an_reason5;             /* 0x114 */
+       u_int32_t               an_reason6;             /* 0x118 */
+       u_int32_t               an_reason7;             /* 0x11C */
+       u_int32_t               an_reason8;             /* 0x120 */
+       u_int32_t               an_reason9;             /* 0x124 */
+       u_int32_t               an_reason10;            /* 0x128 */
+       u_int32_t               an_reason11;            /* 0x12C */
+       u_int32_t               an_reason12;            /* 0x130 */
+       u_int32_t               an_reason13;            /* 0x134 */
+       u_int32_t               an_reason14;            /* 0x138 */
+       u_int32_t               an_reason15;            /* 0x13C */
+       u_int32_t               an_reason16;            /* 0x140 */
+       u_int32_t               an_reason17;            /* 0x144 */
+       u_int32_t               an_reason18;            /* 0x148 */
+       u_int32_t               an_reason19;            /* 0x14C */
+       u_int32_t               an_rx_mgmt_pkts;        /* 0x150 */
+       u_int32_t               an_tx_mgmt_pkts;        /* 0x154 */
+       u_int32_t               an_rx_refresh_pkts;     /* 0x158 */
+       u_int32_t               an_tx_refresh_pkts;     /* 0x15C */
+       u_int32_t               an_rx_poll_pkts;        /* 0x160 */
+       u_int32_t               an_tx_poll_pkts;        /* 0x164 */
+       u_int32_t               an_host_retries;        /* 0x168 */
+       u_int32_t               an_lostsync_hostreq;    /* 0x16C */
+       u_int32_t               an_host_tx_bytes;       /* 0x170 */
+       u_int32_t               an_host_rx_bytes;       /* 0x174 */
+       u_int32_t               an_uptime_usecs;        /* 0x178 */
+       u_int32_t               an_uptime_secs;         /* 0x17C */
+       u_int32_t               an_lostsync_better_ap;  /* 0x180 */
+       u_int32_t               an_rsvd[10];
+};
+
+struct an_ltv_genconfig {
+       /* General configuration. */
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* XXXX */
+       u_int16_t               an_opmode;              /* 0x02 */
+       u_int16_t               an_rxmode;              /* 0x04 */
+       u_int16_t               an_fragthresh;          /* 0x06 */
+       u_int16_t               an_rtsthresh;           /* 0x08 */
+       u_int8_t                an_macaddr[6];          /* 0x0A */
+       u_int8_t                an_rates[8];            /* 0x10 */
+       u_int16_t               an_shortretry_limit;    /* 0x18 */
+       u_int16_t               an_longretry_limit;     /* 0x1A */
+       u_int16_t               an_tx_msdu_lifetime;    /* 0x1C */
+       u_int16_t               an_rx_msdu_lifetime;    /* 0x1E */
+       u_int16_t               an_stationary;          /* 0x20 */
+       u_int16_t               an_ordering;            /* 0x22 */
+       u_int16_t               an_devtype;             /* 0x24 */
+       u_int16_t               an_rsvd0[5];            /* 0x26 */
+       /* Scanning associating. */
+       u_int16_t               an_scanmode;            /* 0x30 */
+       u_int16_t               an_probedelay;          /* 0x32 */
+       u_int16_t               an_probe_energy_timeout;/* 0x34 */
+       u_int16_t               an_probe_response_timeout;/*0x36 */
+       u_int16_t               an_beacon_listen_timeout;/*0x38 */
+       u_int16_t               an_ibss_join_net_timeout;/*0x3A */
+       u_int16_t               an_auth_timeout;        /* 0x3C */
+       u_int16_t               an_authtype;            /* 0x3E */
+       u_int16_t               an_assoc_timeout;       /* 0x40 */
+       u_int16_t               an_specified_ap_timeout;/* 0x42 */
+       u_int16_t               an_offline_scan_interval;/*0x44 */
+       u_int16_t               an_offline_scan_duration;/*0x46 */
+       u_int16_t               an_link_loss_delay;     /* 0x48 */
+       u_int16_t               an_max_beacon_lost_time;/* 0x4A */
+       u_int16_t               an_refresh_interval;    /* 0x4C */
+       u_int16_t               an_rsvd1;               /* 0x4E */
+       /* Power save operation */
+       u_int16_t               an_psave_mode;          /* 0x50 */
+       u_int16_t               an_sleep_for_dtims;     /* 0x52 */
+       u_int16_t               an_listen_interval;     /* 0x54 */
+       u_int16_t               an_fast_listen_interval;/* 0x56 */
+       u_int16_t               an_listen_decay;        /* 0x58 */
+       u_int16_t               an_fast_listen_decay;   /* 0x5A */
+       u_int16_t               an_rsvd2[2];            /* 0x5C */
+       /* Ad-hoc (or AP) operation. */
+       u_int16_t               an_beacon_period;       /* 0x60 */
+       u_int16_t               an_atim_duration;       /* 0x62 */
+       u_int16_t               an_rsvd3;               /* 0x64 */
+       u_int16_t               an_ds_channel;          /* 0x66 */
+       u_int16_t               an_rsvd4;               /* 0x68 */
+       u_int16_t               an_dtim_period;         /* 0x6A */
+       u_int16_t               an_rsvd5[2];            /* 0x6C */
+       /* Radio operation. */
+       u_int16_t               an_radiotype;           /* 0x70 */
+       u_int16_t               an_diversity;           /* 0x72 */
+       u_int16_t               an_tx_power;            /* 0x74 */
+       u_int16_t               an_rss_thresh;          /* 0x76 */
+       u_int16_t               an_rsvd6[4];            /* 0x78 */
+       /* Aironet extensions. */
+       u_int8_t                an_nodename[16];        /* 0x80 */
+       u_int16_t               an_arl_thresh;          /* 0x90 */
+       u_int16_t               an_arl_decay;           /* 0x92 */
+       u_int16_t               an_arl_delay;           /* 0x94 */
+       u_int8_t                an_rsvd7;               /* 0x96 */
+       u_int8_t                an_rsvd8;               /* 0x97 */
+       u_int8_t                an_magic_packet_action; /* 0x98 */
+       u_int8_t                an_magic_packet_ctl;    /* 0x99 */
+       u_int16_t               an_rsvd9;
+};
+
+#define AN_OPMODE_IBSS_ADHOC                   0x0000
+#define AN_OPMODE_INFRASTRUCTURE_STATION       0x0001
+#define AN_OPMODE_AP                           0x0002
+#define AN_OPMODE_AP_REPEATER                  0x0003
+#define AN_OPMODE_UNMODIFIED_PAYLOAD           0x0100
+#define AN_OPMODE_AIRONET_EXTENSIONS           0x0200
+#define AN_OPMODE_AP_EXTENSIONS                        0x0400
+
+#define AN_RXMODE_BC_MC_ADDR                   0x0000
+#define AN_RXMODE_BC_ADDR                      0x0001
+#define AN_RXMODE_ADDR                         0x0002
+#define AN_RXMODE_80211_MONITOR_CURBSS         0x0003
+#define AN_RXMODE_80211_MONITOR_ANYBSS         0x0004
+#define AN_RXMODE_LAN_MONITOR_CURBSS           0x0005
+#define AN_RXMODE_NO_8023_HEADER               0x0100
+
+#define AN_RATE_1MBPS                          0x0002
+#define AN_RATE_2MBPS                          0x0004
+#define AN_RATE_5_5MBPS                                0x000B
+#define AN_RATE_11MBPS                         0x0016
+
+#define AN_DEVTYPE_PC4500                      0x0065
+#define AN_DEVTYPE_PC4800                      0x006D
+
+#define AN_SCANMODE_ACTIVE                     0x0000
+#define AN_SCANMODE_PASSIVE                    0x0001
+#define AN_SCANMODE_AIRONET_ACTIVE             0x0002
+
+#define AN_AUTHTYPE_NONE                       0x0000
+#define AN_AUTHTYPE_OPEN                       0x0001
+#define AN_AUTHTYPE_SHAREDKEY                  0x0002
+#define AN_AUTHTYPE_EXCLUDE_UNENCRYPTED                0x0004
+
+#define AN_PSAVE_NONE                          0x0000
+#define AN_PSAVE_CAM                           0x0001
+#define AN_PSAVE_PSP                           0x0002
+#define AN_PSAVE_PSP_CAM                       0x0003
+
+#define AN_RADIOTYPE_80211_FH                  0x0001
+#define AN_RADIOTYPE_80211_DS                  0x0002
+#define AN_RADIOTYPE_LM2000_DS                 0x0004
+
+#define AN_DIVERSITY_FACTORY_DEFAULT           0x0000
+#define AN_DIVERSITY_ANTENNA_1_ONLY            0x0001
+#define AN_DIVERSITY_ANTENNA_2_ONLY            0x0002
+#define AN_DIVERSITY_ANTENNA_1_AND_2           0x0003
+
+#define AN_TXPOWER_FACTORY_DEFAULT             0x0000
+#define AN_TXPOWER_50MW                                50
+#define AN_TXPOWER_100MW                       100
+#define AN_TXPOWER_250MW                       250
+
+struct an_ltv_ssidlist {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_ssid1_len;
+       char                    an_ssid1[32];
+       u_int16_t               an_ssid2_len;
+       char                    an_ssid2[32];
+       u_int16_t               an_ssid3_len;
+       char                    an_ssid3[32];
+};
+
+struct an_ltv_aplist {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int8_t                an_ap1[8];
+       u_int8_t                an_ap2[8];
+       u_int8_t                an_ap3[8];
+       u_int8_t                an_ap4[8];
+};
+
+struct an_ltv_drvname {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int8_t                an_drvname[16];
+};
+
+struct an_rid_encap {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_ethertype_default;
+       u_int16_t               an_action_default;
+       u_int16_t               an_ethertype0;
+       u_int16_t               an_action0;
+       u_int16_t               an_ethertype1;
+       u_int16_t               an_action1;
+       u_int16_t               an_ethertype2;
+       u_int16_t               an_action2;
+       u_int16_t               an_ethertype3;
+       u_int16_t               an_action3;
+       u_int16_t               an_ethertype4;
+       u_int16_t               an_action4;
+       u_int16_t               an_ethertype5;
+       u_int16_t               an_action5;
+       u_int16_t               an_ethertype6;
+       u_int16_t               an_action6;
+};
+
+#define AN_ENCAP_ACTION_RX     0x0001
+#define AN_ENCAP_ACTION_TX     0x0002
+
+#define AN_RXENCAP_NONE                0x0000
+#define AN_RXENCAP_RFC1024     0x0001
+
+#define AN_TXENCAP_RFC1024     0x0000
+#define AN_TXENCAP_80211       0x0002
+
+struct an_ltv_caps {
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* XXXX */
+       u_int8_t                an_oui[3];              /* 0x02 */
+       u_int8_t                an_rsvd0;               /* 0x05 */
+       u_int16_t               an_prodnum;             /* 0x06 */
+       u_int8_t                an_manufname[32];       /* 0x08 */
+       u_int8_t                an_prodname[16];        /* 0x28 */
+       u_int8_t                an_prodvers[8];         /* 0x38 */
+       u_int8_t                an_oemaddr[6];          /* 0x40 */
+       u_int8_t                an_aironetaddr[6];      /* 0x46 */
+       u_int16_t               an_radiotype;           /* 0x4C */
+       u_int16_t               an_regdomain;           /* 0x4E */
+       u_int8_t                an_callid[6];           /* 0x50 */
+       u_int8_t                an_rates[8];            /* 0x56 */
+       u_int8_t                an_rx_diversity;        /* 0x5E */
+       u_int8_t                an_tx_diversity;        /* 0x5F */
+       u_int16_t               an_tx_powerlevels[8];   /* 0x60 */
+       u_int16_t               an_hwrev;               /* 0x70 */
+       u_int16_t               an_hwcaps;              /* 0x72 */
+       u_int16_t               an_temprange;           /* 0x74 */
+       u_int16_t               an_fwrev;               /* 0x76 */
+       u_int16_t               an_fwsubrev;            /* 0x78 */
+       u_int16_t               an_ifacerev;            /* 0x7A */
+       u_int16_t               an_softcaps;            /* 0x7C */
+       u_int16_t               an_bootblockrev;        /* 0x7E */
+};
+
+struct an_ltv_apinfo {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       u_int16_t               an_tim_addr;
+       u_int16_t               an_airo_addr;
+};
+
+struct an_ltv_radioinfo {
+       u_int16_t               an_len;
+       u_int16_t               an_type;
+       /* ??? */
+};
+
+struct an_ltv_status {
+       u_int16_t               an_len;                 /* 0x00 */
+       u_int16_t               an_type;                /* 0xXX */
+       u_int8_t                an_macaddr[6];          /* 0x02 */
+       u_int16_t               an_opmode;              /* 0x08 */
+       u_int16_t               an_errcode;             /* 0x0A */
+       u_int16_t               an_cur_signal_quality;  /* 0x0C */
+       u_int16_t               an_ssidlen;             /* 0x0E */
+       u_int8_t                an_ssid[32];            /* 0x10 */
+       u_int8_t                an_ap_name[16];         /* 0x30 */
+       u_int8_t                an_cur_bssid[6];        /* 0x40 */
+       u_int8_t                an_prev_bssid1[6];      /* 0x46 */
+       u_int8_t                an_prev_bssid2[6];      /* 0x4C */
+       u_int8_t                an_prev_bssid3[6];      /* 0x52 */
+       u_int16_t               an_beacon_period;       /* 0x58 */
+       u_int16_t               an_dtim_period;         /* 0x5A */
+       u_int16_t               an_atim_duration;       /* 0x5C */
+       u_int16_t               an_hop_period;          /* 0x5E */
+       u_int16_t               an_cur_channel;         /* 0x62 */
+       u_int16_t               an_channel_set;         /* 0x60 */
+       u_int16_t               an_hops_to_backbone;    /* 0x64 */
+       u_int16_t               an_ap_total_load;       /* 0x66 */
+       u_int16_t               an_our_generated_load;  /* 0x68 */
+       u_int16_t               an_accumulated_arl;     /* 0x6A */
+       u_int16_t               an_rsvd0;               /* 0x6C */
+};
+
+#define AN_STATUS_OPMODE_CONFIGURED            0x0001
+#define AN_STATUS_OPMODE_MAC_ENABLED           0x0002
+#define AN_STATUS_OPMODE_RX_ENABLED            0x0004
+#define AN_STATUS_OPMODE_IN_SYNC               0x0010
+#define AN_STATUS_OPMODE_ASSOCIATED            0x0020
+#define AN_STATUS_OPMODE_ERROR                 0x8000
+
+
+/*
+ * These are all the LTV record types that we can read or write
+ * from the Aironet. Not all of them are temendously useful, but I
+ * list as many as I know about here for completeness.
+ */
+
+/*
+ * Configuration (read/write)
+ */
+#define AN_RID_GENCONFIG       0xFF10  /* General configuration info */
+#define AN_RID_SSIDLIST                0xFF11  /* Valid SSID list */
+#define AN_RID_APLIST          0xFF12  /* Valid AP list */
+#define AN_RID_DRVNAME         0xFF13  /* ID name of this node for diag */
+#define AN_RID_ENCAPPROTO      0xFF14  /* Payload encapsulation type */
+#define AN_RID_ACTUALCFG       0xFF20  /* Current configuration settings */
+
+/*
+ * Reporting (read only)
+ */
+#define AN_RID_CAPABILITIES    0xFF00  /* PC 4500/4800 capabilities */
+#define AN_RID_AP_INFO         0xFF01  /* Access point info */
+#define AN_RID_RADIO_INFO      0xFF02  /* Radio info */
+#define AN_RID_STATUS          0xFF50  /* Current status info */
+
+/*
+ * Statistics
+ */
+#define AN_RID_16BITS_CUM      0xFF60  /* Cumulative 16-bit stats counters */
+#define AN_RID_16BITS_DELTA    0xFF61  /* 16-bit stats (since last clear) */
+#define AN_RID_16BITS_DELTACLR 0xFF62  /* 16-bit stats, clear on read */
+#define AN_RID_32BITS_CUM      0xFF68  /* Cumulative 32-bit stats counters */
+#define AN_RID_32BITS_DELTA    0xFF69  /* 32-bit stats (since last clear) */
+#define AN_RID_32BITS_DELTACLR 0xFF6A  /* 32-bit stats, clear on read */
+#endif
+
+
+#endif
index 98eb2a8..a852cbc 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.pcmcia,v 1.27 2000/03/29 20:23:21 mickey Exp $
+#      $OpenBSD: files.pcmcia,v 1.28 2000/04/03 01:02:00 mickey Exp $
 #      $NetBSD: files.pcmcia,v 1.9 1998/06/21 18:45:41 christos Exp $
 #
 # Config.new file and device description for machine-independent PCMCIA code.
@@ -82,3 +82,7 @@ file    dev/ic/am79c930.c                       awi
 device ray: ether, ifnet, ifmedia
 attach ray at pcmcia
 file   dev/pcmcia/if_ray.c                     ray
+
+# Aironet 4500/4800 802.11 DS WLAN
+attach an at pcmcia with an_pcmcia
+file   dev/pcmcia/if_an_pcmcia.c               an_pcmcia
diff --git a/sys/dev/pcmcia/if_an_pcmcia.c b/sys/dev/pcmcia/if_an_pcmcia.c
new file mode 100644 (file)
index 0000000..52f26a9
--- /dev/null
@@ -0,0 +1,198 @@
+/*     $OpenBSD: if_an_pcmcia.c,v 1.1 2000/04/03 01:02:00 mickey Exp $ */
+
+/*
+ * Copyright (c) 1999 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Michael Shalayeff.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/timeout.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+#include <dev/ic/anvar.h>
+#include <dev/ic/anreg.h>
+
+int  an_pcmcia_match         __P((struct device *, void *, void *));
+void an_pcmcia_attach        __P((struct device *, struct device *, void *));
+int  an_pcmcia_detach        __P((struct device *, int));
+int  an_pcmcia_activate      __P((struct device *, enum devact));
+
+struct an_pcmcia_softc {
+       struct an_softc sc_an;
+
+       struct pcmcia_io_handle sc_pcioh;
+       struct pcmcia_function *sc_pf;
+       int sc_io_window;
+};
+
+struct cfattach an_pcmcia_ca = {   
+       sizeof (struct an_softc), an_pcmcia_match, an_pcmcia_attach,
+       an_pcmcia_detach, an_pcmcia_activate
+};
+
+int
+an_pcmcia_match(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct pcmcia_attach_args *pa = aux;
+
+       if (pa->pf->function != PCMCIA_FUNCTION_NETWORK)
+               return 0;
+
+       switch (pa->manufacturer) {
+       case PCMCIA_VENDOR_AIRONET:
+               switch (pa->product) {
+               case PCMCIA_PRODUCT_AIRONET_PC4500:
+               case PCMCIA_PRODUCT_AIRONET_PC4800:
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+void
+an_pcmcia_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)self;
+       struct an_softc *sc = (struct an_softc *)self;
+       struct pcmcia_attach_args *pa = aux;
+       struct pcmcia_config_entry *cfe;
+
+       psc->sc_pf = pa->pf;
+       cfe = pa->pf->cfe_head.sqh_first;
+
+       pcmcia_function_init(pa->pf, cfe);
+       if (pcmcia_function_enable(pa->pf)) {
+               printf(": function enable failed\n");
+               return;
+       }
+
+       if (pcmcia_io_alloc(pa->pf, 0, AN_IOSIZ, AN_IOSIZ, &psc->sc_pcioh)) {
+               printf(": can't alloc i/o space\n");
+               pcmcia_function_disable(pa->pf);
+               return;
+       }
+
+       if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16, 0, AN_IOSIZ,
+           &psc->sc_pcioh, &psc->sc_io_window)) {
+               printf(": can't map i/o space\n");
+               pcmcia_io_free(pa->pf, &psc->sc_pcioh);
+               pcmcia_function_disable(pa->pf);
+               return;
+       }
+
+       sc->an_btag = psc->sc_pcioh.iot;
+       sc->an_bhandle = psc->sc_pcioh.ioh;
+
+       sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, an_intr, sc);
+       if (sc->sc_ih == NULL)
+               printf("no irq");
+
+       an_attach(sc);
+}
+
+int
+an_pcmcia_detach(dev, flags)
+       struct device *dev;
+       int flags;
+{
+       struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev;
+       struct an_softc *sc = (struct an_softc *)dev;
+       struct ifnet *ifp = &sc->arpcom.ac_if;
+
+       if (sc->an_gone) {
+               printf ("%s: already detached\n", sc->sc_dev.dv_xname);
+               return 0;
+       }
+
+       if (ifp->if_flags & IFF_RUNNING)
+               an_stop(sc);
+
+       pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
+       pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
+
+       ether_ifdetach(ifp);
+       if_detach(ifp);
+
+       sc->an_gone = 1;
+
+       return 0;
+}
+
+int
+an_pcmcia_activate(dev, act)
+       struct device *dev;
+       enum devact act;
+{
+       struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev;
+       struct an_softc *sc = (struct an_softc *)dev;
+       struct ifnet *ifp = &sc->arpcom.ac_if;
+       int s;
+
+       s = splnet();
+       switch (act) {
+       case DVACT_ACTIVATE:
+               pcmcia_function_enable(psc->sc_pf);
+               sc->sc_ih =
+                   pcmcia_intr_establish(psc->sc_pf, IPL_NET, an_intr, sc);
+               printf("\n");
+               an_init(sc);
+               break;
+
+       case DVACT_DEACTIVATE:
+               ifp->if_timer = 0;
+               if (ifp->if_flags & IFF_RUNNING)
+                       an_stop(sc);
+               pcmcia_function_disable(psc->sc_pf);
+               pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
+               break;
+       }
+
+       splx(s);
+       return (0);
+}