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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/an/if_an.c

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

    1 /*
    2  * Copyright (c) 1997, 1998, 1999
    3  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Bill Paul.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  *
   32  * $FreeBSD: releng/5.0/sys/dev/an/if_an.c 106937 2002-11-14 23:54:55Z sam $
   33  */
   34 
   35 /*
   36  * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
   37  *
   38  * Written by Bill Paul <wpaul@ctr.columbia.edu>
   39  * Electrical Engineering Department
   40  * Columbia University, New York City
   41  */
   42 
   43 /*
   44  * The Aironet 4500/4800 series cards come in PCMCIA, ISA and PCI form.
   45  * This driver supports all three device types (PCI devices are supported
   46  * through an extra PCI shim: /sys/dev/an/if_an_pci.c). ISA devices can be
   47  * supported either using hard-coded IO port/IRQ settings or via Plug
   48  * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates.
   49  * The 4800 devices support 1, 2, 5.5 and 11Mbps rates.
   50  *
   51  * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially
   52  * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA
   53  * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are
   54  * a couple of important differences though:
   55  *
   56  * - Lucent ISA card looks to the host like a PCMCIA controller with
   57  *   a PCMCIA WaveLAN card inserted. This means that even desktop
   58  *   machines need to be configured with PCMCIA support in order to
   59  *   use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand
   60  *   actually look like normal ISA and PCI devices to the host, so
   61  *   no PCMCIA controller support is needed
   62  *
   63  * The latter point results in a small gotcha. The Aironet PCMCIA
   64  * cards can be configured for one of two operating modes depending
   65  * on how the Vpp1 and Vpp2 programming voltages are set when the
   66  * card is activated. In order to put the card in proper PCMCIA
   67  * operation (where the CIS table is visible and the interface is
   68  * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be
   69  * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages,
   70  * which leaves the card in ISA/PCI mode, which prevents it from
   71  * being activated as an PCMCIA device.
   72  *
   73  * Note that some PCMCIA controller software packages for Windows NT
   74  * fail to set the voltages as well.
   75  *
   76  * The Aironet devices can operate in both station mode and access point
   77  * mode. Typically, when programmed for station mode, the card can be set
   78  * to automatically perform encapsulation/decapsulation of Ethernet II
   79  * and 802.3 frames within 802.11 frames so that the host doesn't have
   80  * to do it itself. This driver doesn't program the card that way: the
   81  * driver handles all of the encapsulation/decapsulation itself.
   82  */
   83 
   84 #include "opt_inet.h"
   85 
   86 #ifdef INET
   87 #define ANCACHE                 /* enable signal strength cache */
   88 #endif
   89 
   90 #include <sys/param.h>
   91 #include <sys/systm.h>
   92 #include <sys/sockio.h>
   93 #include <sys/mbuf.h>
   94 #include <sys/proc.h>
   95 #include <sys/kernel.h>
   96 #include <sys/socket.h>
   97 #ifdef ANCACHE
   98 #include <sys/syslog.h>
   99 #include <sys/sysctl.h>
  100 #endif
  101 
  102 #include <sys/module.h>
  103 #include <sys/sysctl.h>
  104 #include <sys/bus.h>
  105 #include <machine/bus.h>
  106 #include <sys/rman.h>
  107 #include <sys/lock.h>
  108 #include <sys/mutex.h>
  109 #include <machine/resource.h>
  110 
  111 #include <net/if.h>
  112 #include <net/if_arp.h>
  113 #include <net/ethernet.h>
  114 #include <net/if_dl.h>
  115 #include <net/if_types.h>
  116 #include <net/if_ieee80211.h>
  117 #include <net/if_media.h>
  118 
  119 #ifdef INET
  120 #include <netinet/in.h>
  121 #include <netinet/in_systm.h>
  122 #include <netinet/in_var.h>
  123 #include <netinet/ip.h>
  124 #endif
  125 
  126 #include <net/bpf.h>
  127 
  128 #include <machine/md_var.h>
  129 
  130 #include <dev/an/if_aironet_ieee.h>
  131 #include <dev/an/if_anreg.h>
  132 
  133 #if !defined(lint)
  134 static const char rcsid[] =
  135   "$FreeBSD: releng/5.0/sys/dev/an/if_an.c 106937 2002-11-14 23:54:55Z sam $";
  136 #endif
  137 
  138 /* These are global because we need them in sys/pci/if_an_p.c. */
  139 static void an_reset            (struct an_softc *);
  140 static int an_ioctl             (struct ifnet *, u_long, caddr_t);
  141 static void an_init             (void *);
  142 static int an_init_tx_ring      (struct an_softc *);
  143 static void an_start            (struct ifnet *);
  144 static void an_watchdog         (struct ifnet *);
  145 static void an_rxeof            (struct an_softc *);
  146 static void an_txeof            (struct an_softc *, int);
  147 
  148 static void an_promisc          (struct an_softc *, int);
  149 static int an_cmd               (struct an_softc *, int, int);
  150 static int an_read_record       (struct an_softc *, struct an_ltv_gen *);
  151 static int an_write_record      (struct an_softc *, struct an_ltv_gen *);
  152 static int an_read_data         (struct an_softc *, int, int, caddr_t, int);
  153 static int an_write_data        (struct an_softc *, int, int, caddr_t, int);
  154 static int an_seek              (struct an_softc *, int, int, int);
  155 static int an_alloc_nicmem      (struct an_softc *, int, int *);
  156 static void an_stats_update     (void *);
  157 static void an_setdef           (struct an_softc *, struct an_req *);
  158 #ifdef ANCACHE
  159 static void an_cache_store      (struct an_softc *, struct ether_header *,
  160                                         struct mbuf *, unsigned short);
  161 #endif
  162 
  163 /* function definitions for use with the Cisco's Linux configuration
  164    utilities
  165 */
  166 
  167 static int readrids(struct ifnet*, struct aironet_ioctl*);
  168 static int writerids(struct ifnet*, struct aironet_ioctl*);
  169 static int flashcard(struct ifnet*, struct aironet_ioctl*);
  170 
  171 static int cmdreset(struct ifnet *);
  172 static int setflashmode(struct ifnet *);
  173 static int flashgchar(struct ifnet *,int,int);
  174 static int flashpchar(struct ifnet *,int,int);
  175 static int flashputbuf(struct ifnet *);
  176 static int flashrestart(struct ifnet *);
  177 static int WaitBusy(struct ifnet *, int);
  178 static int unstickbusy(struct ifnet *);
  179 
  180 static void an_dump_record      (struct an_softc *,struct an_ltv_gen *,
  181                                     char *);
  182 
  183 static int an_media_change      (struct ifnet *);
  184 static void an_media_status     (struct ifnet *, struct ifmediareq *);
  185 
  186 static int      an_dump = 0;
  187 
  188 static char an_conf[256];
  189 
  190 /* sysctl vars */
  191 SYSCTL_NODE(_machdep, OID_AUTO, an, CTLFLAG_RD, 0, "dump RID");
  192 
  193 /* XXX violate ethernet/netgraph callback hooks */
  194 extern  void    (*ng_ether_attach_p)(struct ifnet *ifp);
  195 extern  void    (*ng_ether_detach_p)(struct ifnet *ifp);
  196 
  197 static int
  198 sysctl_an_dump(SYSCTL_HANDLER_ARGS)
  199 {
  200         int     error, r, last;
  201         char    *s = an_conf;
  202 
  203         last = an_dump;
  204         bzero(an_conf, sizeof(an_conf));
  205 
  206         switch (an_dump) {
  207         case 0:
  208                 strcat(an_conf, "off");
  209                 break;
  210         case 1:
  211                 strcat(an_conf, "type");
  212                 break;
  213         case 2:
  214                 strcat(an_conf, "dump");
  215                 break;
  216         default:
  217                 snprintf(an_conf, 5, "%x", an_dump);
  218                 break;
  219         }
  220 
  221         error = sysctl_handle_string(oidp, an_conf, sizeof(an_conf), req);
  222 
  223         if (strncmp(an_conf,"off", 4) == 0) {
  224                 an_dump = 0;
  225         }
  226         if (strncmp(an_conf,"dump", 4) == 0) {
  227                 an_dump = 1;
  228         }
  229         if (strncmp(an_conf,"type", 4) == 0) {
  230                 an_dump = 2;
  231         }
  232         if (*s == 'f') {
  233                 r = 0;
  234                 for (;;s++) {
  235                         if ((*s >= '') && (*s <= '9')) {
  236                                 r = r * 16 + (*s - '');
  237                         } else if ((*s >= 'a') && (*s <= 'f')) {
  238                                 r = r * 16 + (*s - 'a' + 10);
  239                         } else {
  240                                 break;
  241                         }
  242                 }
  243                 an_dump = r;
  244         }
  245         if (an_dump != last)
  246                 printf("Sysctl changed for Aironet driver\n");
  247 
  248         return error;
  249 }
  250 
  251 SYSCTL_PROC(_machdep, OID_AUTO, an_dump, CTLTYPE_STRING | CTLFLAG_RW,
  252             0, sizeof(an_conf), sysctl_an_dump, "A", "");
  253 
  254 /*
  255  * We probe for an Aironet 4500/4800 card by attempting to
  256  * read the default SSID list. On reset, the first entry in
  257  * the SSID list will contain the name "tsunami." If we don't
  258  * find this, then there's no card present.
  259  */
  260 int
  261 an_probe(dev)
  262         device_t                dev;
  263 {
  264         struct an_softc *sc = device_get_softc(dev);
  265         struct an_ltv_ssidlist  ssid;
  266         int     error;
  267 
  268         bzero((char *)&ssid, sizeof(ssid));
  269 
  270         error = an_alloc_port(dev, 0, AN_IOSIZ);
  271         if (error != 0)
  272                 return (0);
  273 
  274         /* can't do autoprobing */
  275         if (rman_get_start(sc->port_res) == -1)
  276                 return(0);
  277 
  278         /*
  279          * We need to fake up a softc structure long enough
  280          * to be able to issue commands and call some of the
  281          * other routines.
  282          */
  283         sc->an_bhandle = rman_get_bushandle(sc->port_res);
  284         sc->an_btag = rman_get_bustag(sc->port_res);
  285         sc->an_unit = device_get_unit(dev);
  286 
  287         ssid.an_len = sizeof(ssid);
  288         ssid.an_type = AN_RID_SSIDLIST;
  289 
  290         /* Make sure interrupts are disabled. */
  291         CSR_WRITE_2(sc, AN_INT_EN, 0);
  292         CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF);
  293 
  294         an_reset(sc);
  295 
  296         if (an_cmd(sc, AN_CMD_READCFG, 0))
  297                 return(0);
  298 
  299         if (an_read_record(sc, (struct an_ltv_gen *)&ssid))
  300                 return(0);
  301 
  302         /* See if the ssid matches what we expect ... but doesn't have to */
  303         if (strcmp(ssid.an_ssid1, AN_DEF_SSID))
  304                 return(0);
  305 
  306         return(AN_IOSIZ);
  307 }
  308 
  309 /*
  310  * Allocate a port resource with the given resource id.
  311  */
  312 int
  313 an_alloc_port(dev, rid, size)
  314         device_t dev;
  315         int rid;
  316         int size;
  317 {
  318         struct an_softc *sc = device_get_softc(dev);
  319         struct resource *res;
  320 
  321         res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
  322                                  0ul, ~0ul, size, RF_ACTIVE);
  323         if (res) {
  324                 sc->port_rid = rid;
  325                 sc->port_res = res;
  326                 return (0);
  327         } else {
  328                 return (ENOENT);
  329         }
  330 }
  331 
  332 /*
  333  * Allocate an irq resource with the given resource id.
  334  */
  335 int
  336 an_alloc_irq(dev, rid, flags)
  337         device_t dev;
  338         int rid;
  339         int flags;
  340 {
  341         struct an_softc *sc = device_get_softc(dev);
  342         struct resource *res;
  343 
  344         res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
  345                                  0ul, ~0ul, 1, (RF_ACTIVE | flags));
  346         if (res) {
  347                 sc->irq_rid = rid;
  348                 sc->irq_res = res;
  349                 return (0);
  350         } else {
  351                 return (ENOENT);
  352         }
  353 }
  354 
  355 /*
  356  * Release all resources
  357  */
  358 void
  359 an_release_resources(dev)
  360         device_t dev;
  361 {
  362         struct an_softc *sc = device_get_softc(dev);
  363 
  364         if (sc->port_res) {
  365                 bus_release_resource(dev, SYS_RES_IOPORT,
  366                                      sc->port_rid, sc->port_res);
  367                 sc->port_res = 0;
  368         }
  369         if (sc->irq_res) {
  370                 bus_release_resource(dev, SYS_RES_IRQ,
  371                                      sc->irq_rid, sc->irq_res);
  372                 sc->irq_res = 0;
  373         }
  374 }
  375 
  376 int
  377 an_attach(sc, unit, flags)
  378         struct an_softc *sc;
  379         int unit;
  380         int flags;
  381 {
  382         struct ifnet            *ifp = &sc->arpcom.ac_if;
  383 
  384         mtx_init(&sc->an_mtx, device_get_nameunit(sc->an_dev), MTX_NETWORK_LOCK,
  385             MTX_DEF | MTX_RECURSE);
  386         AN_LOCK(sc);
  387 
  388         sc->an_gone = 0;
  389         sc->an_associated = 0;
  390         sc->an_monitor = 0;
  391         sc->an_was_monitor = 0;
  392 
  393         /* Reset the NIC. */
  394         an_reset(sc);
  395 
  396         /* Load factory config */
  397         if (an_cmd(sc, AN_CMD_READCFG, 0)) {
  398                 printf("an%d: failed to load config data\n", sc->an_unit);
  399                 AN_UNLOCK(sc);
  400                 mtx_destroy(&sc->an_mtx);
  401                 return(EIO);
  402         }
  403 
  404         /* Read the current configuration */
  405         sc->an_config.an_type = AN_RID_GENCONFIG;
  406         sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
  407         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
  408                 printf("an%d: read record failed\n", sc->an_unit);
  409                 AN_UNLOCK(sc);
  410                 mtx_destroy(&sc->an_mtx);
  411                 return(EIO);
  412         }
  413 
  414         /* Read the card capabilities */
  415         sc->an_caps.an_type = AN_RID_CAPABILITIES;
  416         sc->an_caps.an_len = sizeof(struct an_ltv_caps);
  417         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) {
  418                 printf("an%d: read record failed\n", sc->an_unit);
  419                 AN_UNLOCK(sc);
  420                 mtx_destroy(&sc->an_mtx);
  421                 return(EIO);
  422         }
  423 
  424         /* Read ssid list */
  425         sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
  426         sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
  427         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
  428                 printf("an%d: read record failed\n", sc->an_unit);
  429                 AN_UNLOCK(sc);
  430                 mtx_destroy(&sc->an_mtx);
  431                 return(EIO);
  432         }
  433 
  434         /* Read AP list */
  435         sc->an_aplist.an_type = AN_RID_APLIST;
  436         sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
  437         if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
  438                 printf("an%d: read record failed\n", sc->an_unit);
  439                 AN_UNLOCK(sc);
  440                 mtx_destroy(&sc->an_mtx);
  441                 return(EIO);
  442         }
  443 
  444         bcopy((char *)&sc->an_caps.an_oemaddr,
  445            (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  446 
  447         printf("an%d: Ethernet address: %6D\n", sc->an_unit,
  448             sc->arpcom.ac_enaddr, ":");
  449 
  450         ifp->if_softc = sc;
  451         ifp->if_unit = sc->an_unit = unit;
  452         ifp->if_name = "an";
  453         ifp->if_mtu = ETHERMTU;
  454         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  455         ifp->if_ioctl = an_ioctl;
  456         ifp->if_output = ether_output;
  457         ifp->if_start = an_start;
  458         ifp->if_watchdog = an_watchdog;
  459         ifp->if_init = an_init;
  460         ifp->if_baudrate = 10000000;
  461         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  462 
  463         bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
  464         bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename,
  465             sizeof(AN_DEFAULT_NODENAME) - 1);
  466 
  467         bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1));
  468         bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1,
  469             sizeof(AN_DEFAULT_NETNAME) - 1);
  470         sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME);
  471 
  472         sc->an_config.an_opmode =
  473             AN_OPMODE_INFRASTRUCTURE_STATION;
  474 
  475         sc->an_tx_rate = 0;
  476         bzero((char *)&sc->an_stats, sizeof(sc->an_stats));
  477 
  478         ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status);
  479 #define ADD(m, c)       ifmedia_add(&sc->an_ifmedia, (m), (c), NULL)
  480         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
  481             IFM_IEEE80211_ADHOC, 0), 0);
  482         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
  483         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
  484             IFM_IEEE80211_ADHOC, 0), 0);
  485         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
  486         if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
  487                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
  488                     IFM_IEEE80211_ADHOC, 0), 0);
  489                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
  490         }
  491         if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
  492                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
  493                     IFM_IEEE80211_ADHOC, 0), 0);
  494                 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
  495         }
  496         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
  497             IFM_IEEE80211_ADHOC, 0), 0);
  498         ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
  499 #undef  ADD
  500         ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
  501             0, 0));
  502 
  503         /*
  504          * Call MI attach routine.
  505          */
  506         ether_ifattach(ifp, sc->arpcom.ac_enaddr);
  507         callout_handle_init(&sc->an_stat_ch);
  508         AN_UNLOCK(sc);
  509 
  510         return(0);
  511 }
  512 
  513 static void
  514 an_rxeof(sc)
  515         struct an_softc *sc;
  516 {
  517         struct ifnet   *ifp;
  518         struct ether_header *eh;
  519         struct ieee80211_frame *ih;
  520         struct an_rxframe rx_frame;
  521         struct an_rxframe_802_3 rx_frame_802_3;
  522         struct mbuf    *m;
  523         int             len, id, error = 0;
  524         int             ieee80211_header_len;
  525         u_char          *bpf_buf;
  526         u_short         fc1;
  527 
  528         ifp = &sc->arpcom.ac_if;
  529 
  530         id = CSR_READ_2(sc, AN_RX_FID);
  531 
  532         if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) {
  533                 /* read raw 802.11 packet */
  534                 bpf_buf = sc->buf_802_11;
  535 
  536                 /* read header */
  537                 if (an_read_data(sc, id, 0x0, (caddr_t)&rx_frame,
  538                                  sizeof(rx_frame))) {
  539                         ifp->if_ierrors++;
  540                         return;
  541                 }
  542 
  543                 /*
  544                  * skip beacon by default since this increases the
  545                  * system load a lot
  546                  */
  547 
  548                 if (!(sc->an_monitor & AN_MONITOR_INCLUDE_BEACON) &&
  549                     (rx_frame.an_frame_ctl & IEEE80211_FC0_SUBTYPE_BEACON)) {
  550                         return;
  551                 }
  552 
  553                 if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) {
  554                         len = rx_frame.an_rx_payload_len
  555                                 + sizeof(rx_frame);
  556                         /* Check for insane frame length */
  557                         if (len > sizeof(sc->buf_802_11)) {
  558                                 printf("an%d: oversized packet received (%d, %d)\n",
  559                                        sc->an_unit, len, MCLBYTES);
  560                                 ifp->if_ierrors++;
  561                                 return;
  562                         }
  563 
  564                         bcopy((char *)&rx_frame,
  565                               bpf_buf, sizeof(rx_frame));
  566 
  567                         error = an_read_data(sc, id, sizeof(rx_frame),
  568                                              (caddr_t)bpf_buf+sizeof(rx_frame),
  569                                              rx_frame.an_rx_payload_len);
  570                 } else {
  571                         fc1=rx_frame.an_frame_ctl >> 8;
  572                         ieee80211_header_len = sizeof(struct ieee80211_frame);
  573                         if ((fc1 & IEEE80211_FC1_DIR_TODS) &&
  574                             (fc1 & IEEE80211_FC1_DIR_FROMDS)) {
  575                                 ieee80211_header_len += ETHER_ADDR_LEN;
  576                         }
  577 
  578                         len = rx_frame.an_rx_payload_len
  579                                 + ieee80211_header_len;
  580                         /* Check for insane frame length */
  581                         if (len > sizeof(sc->buf_802_11)) {
  582                                 printf("an%d: oversized packet received (%d, %d)\n",
  583                                        sc->an_unit, len, MCLBYTES);
  584                                 ifp->if_ierrors++;
  585                                 return;
  586                         }
  587 
  588                         ih = (struct ieee80211_frame *)bpf_buf;
  589 
  590                         bcopy((char *)&rx_frame.an_frame_ctl,
  591                               (char *)ih, ieee80211_header_len);
  592 
  593                         error = an_read_data(sc, id, sizeof(rx_frame) +
  594                                              rx_frame.an_gaplen,
  595                                              (caddr_t)ih +ieee80211_header_len,
  596                                              rx_frame.an_rx_payload_len);
  597                 }
  598                 /* dump raw 802.11 packet to bpf and skip ip stack */
  599                 BPF_TAP(ifp, bpf_buf, len);
  600         } else {
  601                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  602                 if (m == NULL) {
  603                         ifp->if_ierrors++;
  604                         return;
  605                 }
  606                 MCLGET(m, M_DONTWAIT);
  607                 if (!(m->m_flags & M_EXT)) {
  608                         m_freem(m);
  609                         ifp->if_ierrors++;
  610                         return;
  611                 }
  612                 m->m_pkthdr.rcvif = ifp;
  613                 /* Read Ethernet encapsulated packet */
  614 
  615 #ifdef ANCACHE
  616                 /* Read NIC frame header */
  617                 if (an_read_data(sc, id, 0, (caddr_t) & rx_frame, sizeof(rx_frame))) {
  618                         ifp->if_ierrors++;
  619                         return;
  620                 }
  621 #endif
  622                 /* Read in the 802_3 frame header */
  623                 if (an_read_data(sc, id, 0x34, (caddr_t) & rx_frame_802_3,
  624                                  sizeof(rx_frame_802_3))) {
  625                         ifp->if_ierrors++;
  626                         return;
  627                 }
  628                 if (rx_frame_802_3.an_rx_802_3_status != 0) {
  629                         ifp->if_ierrors++;
  630                         return;
  631                 }
  632                 /* Check for insane frame length */
  633                 if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) {
  634                         ifp->if_ierrors++;
  635                         return;
  636                 }
  637                 m->m_pkthdr.len = m->m_len =
  638                         rx_frame_802_3.an_rx_802_3_payload_len + 12;
  639 
  640                 eh = mtod(m, struct ether_header *);
  641 
  642                 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr,
  643                       (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
  644                 bcopy((char *)&rx_frame_802_3.an_rx_src_addr,
  645                       (char *)&eh->ether_shost, ETHER_ADDR_LEN);
  646 
  647                 /* in mbuf header type is just before payload */
  648                 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),
  649                                      rx_frame_802_3.an_rx_802_3_payload_len);
  650 
  651                 if (error) {
  652                         m_freem(m);
  653                         ifp->if_ierrors++;
  654                         return;
  655                 }
  656                 ifp->if_ipackets++;
  657 
  658                 /* Receive packet. */
  659 #ifdef ANCACHE
  660                 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength);
  661 #endif
  662                 (*ifp->if_input)(ifp, m);
  663         }
  664 }
  665 
  666 static void
  667 an_txeof(sc, status)
  668         struct an_softc         *sc;
  669         int                     status;
  670 {
  671         struct ifnet            *ifp;
  672         int                     id, i;
  673 
  674         ifp = &sc->arpcom.ac_if;
  675 
  676         ifp->if_timer = 0;
  677         ifp->if_flags &= ~IFF_OACTIVE;
  678 
  679         id = CSR_READ_2(sc, AN_TX_CMP_FID);
  680 
  681         if (status & AN_EV_TX_EXC) {
  682                 ifp->if_oerrors++;
  683         } else
  684                 ifp->if_opackets++;
  685 
  686         for (i = 0; i < AN_TX_RING_CNT; i++) {
  687                 if (id == sc->an_rdata.an_tx_ring[i]) {
  688                         sc->an_rdata.an_tx_ring[i] = 0;
  689                         break;
  690                 }
  691         }
  692 
  693         AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
  694 
  695         return;
  696 }
  697 
  698 /*
  699  * We abuse the stats updater to check the current NIC status. This
  700  * is important because we don't want to allow transmissions until
  701  * the NIC has synchronized to the current cell (either as the master
  702  * in an ad-hoc group, or as a station connected to an access point).
  703  */
  704 static void
  705 an_stats_update(xsc)
  706         void                    *xsc;
  707 {
  708         struct an_softc         *sc;
  709         struct ifnet            *ifp;
  710 
  711         sc = xsc;
  712         AN_LOCK(sc);
  713         ifp = &sc->arpcom.ac_if;
  714 
  715         sc->an_status.an_type = AN_RID_STATUS;
  716         sc->an_status.an_len = sizeof(struct an_ltv_status);
  717         an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
  718 
  719         if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
  720                 sc->an_associated = 1;
  721         else
  722                 sc->an_associated = 0;
  723 
  724         /* Don't do this while we're transmitting */
  725         if (ifp->if_flags & IFF_OACTIVE) {
  726                 sc->an_stat_ch = timeout(an_stats_update, sc, hz);
  727                 AN_UNLOCK(sc);
  728                 return;
  729         }
  730 
  731         sc->an_stats.an_len = sizeof(struct an_ltv_stats);
  732         sc->an_stats.an_type = AN_RID_32BITS_CUM;
  733         an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
  734 
  735         sc->an_stat_ch = timeout(an_stats_update, sc, hz);
  736         AN_UNLOCK(sc);
  737 
  738         return;
  739 }
  740 
  741 void
  742 an_intr(xsc)
  743         void                    *xsc;
  744 {
  745         struct an_softc         *sc;
  746         struct ifnet            *ifp;
  747         u_int16_t               status;
  748 
  749         sc = (struct an_softc*)xsc;
  750 
  751         AN_LOCK(sc);
  752 
  753         if (sc->an_gone) {
  754                 AN_UNLOCK(sc);
  755                 return;
  756         }
  757 
  758         ifp = &sc->arpcom.ac_if;
  759 
  760         /* Disable interrupts. */
  761         CSR_WRITE_2(sc, AN_INT_EN, 0);
  762 
  763         status = CSR_READ_2(sc, AN_EVENT_STAT);
  764         CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS);
  765 
  766         if (status & AN_EV_AWAKE) {
  767                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE);
  768         }
  769 
  770         if (status & AN_EV_LINKSTAT) {
  771                 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED)
  772                         sc->an_associated = 1;
  773                 else
  774                         sc->an_associated = 0;
  775                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
  776         }
  777 
  778         if (status & AN_EV_RX) {
  779                 an_rxeof(sc);
  780                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
  781         }
  782 
  783         if (status & AN_EV_TX) {
  784                 an_txeof(sc, status);
  785                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX);
  786         }
  787 
  788         if (status & AN_EV_TX_EXC) {
  789                 an_txeof(sc, status);
  790                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC);
  791         }
  792 
  793         if (status & AN_EV_ALLOC)
  794                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
  795 
  796         /* Re-enable interrupts. */
  797         CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
  798 
  799         if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL))
  800                 an_start(ifp);
  801 
  802         AN_UNLOCK(sc);
  803 
  804         return;
  805 }
  806 
  807 static int
  808 an_cmd(sc, cmd, val)
  809         struct an_softc         *sc;
  810         int                     cmd;
  811         int                     val;
  812 {
  813         int                     i, s = 0;
  814 
  815         CSR_WRITE_2(sc, AN_PARAM0, val);
  816         CSR_WRITE_2(sc, AN_PARAM1, 0);
  817         CSR_WRITE_2(sc, AN_PARAM2, 0);
  818         CSR_WRITE_2(sc, AN_COMMAND, cmd);
  819 
  820         for (i = 0; i < AN_TIMEOUT; i++) {
  821                 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
  822                         break;
  823                 else {
  824                         if (CSR_READ_2(sc, AN_COMMAND) == cmd)
  825                                 CSR_WRITE_2(sc, AN_COMMAND, cmd);
  826                 }
  827         }
  828 
  829         for (i = 0; i < AN_TIMEOUT; i++) {
  830                 CSR_READ_2(sc, AN_RESP0);
  831                 CSR_READ_2(sc, AN_RESP1);
  832                 CSR_READ_2(sc, AN_RESP2);
  833                 s = CSR_READ_2(sc, AN_STATUS);
  834                 if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE))
  835                         break;
  836         }
  837 
  838         /* Ack the command */
  839         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
  840 
  841         if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)
  842                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
  843 
  844         if (i == AN_TIMEOUT)
  845                 return(ETIMEDOUT);
  846 
  847         return(0);
  848 }
  849 
  850 /*
  851  * This reset sequence may look a little strange, but this is the
  852  * most reliable method I've found to really kick the NIC in the
  853  * head and force it to reboot correctly.
  854  */
  855 static void
  856 an_reset(sc)
  857         struct an_softc         *sc;
  858 {
  859         if (sc->an_gone)
  860                 return;
  861 
  862         an_cmd(sc, AN_CMD_ENABLE, 0);
  863         an_cmd(sc, AN_CMD_FW_RESTART, 0);
  864         an_cmd(sc, AN_CMD_NOOP2, 0);
  865 
  866         if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT)
  867                 printf("an%d: reset failed\n", sc->an_unit);
  868 
  869         an_cmd(sc, AN_CMD_DISABLE, 0);
  870 
  871         return;
  872 }
  873 
  874 /*
  875  * Read an LTV record from the NIC.
  876  */
  877 static int
  878 an_read_record(sc, ltv)
  879         struct an_softc         *sc;
  880         struct an_ltv_gen       *ltv;
  881 {
  882         u_int16_t               *ptr;
  883         u_int8_t                *ptr2;
  884         int                     i, len;
  885 
  886         if (ltv->an_len < 4 || ltv->an_type == 0)
  887                 return(EINVAL);
  888 
  889         /* Tell the NIC to enter record read mode. */
  890         if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) {
  891                 printf("an%d: RID access failed\n", sc->an_unit);
  892                 return(EIO);
  893         }
  894 
  895         /* Seek to the record. */
  896         if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) {
  897                 printf("an%d: seek to record failed\n", sc->an_unit);
  898                 return(EIO);
  899         }
  900 
  901         /*
  902          * Read the length and record type and make sure they
  903          * match what we expect (this verifies that we have enough
  904          * room to hold all of the returned data).
  905          * Length includes type but not length.
  906          */
  907         len = CSR_READ_2(sc, AN_DATA1);
  908         if (len > (ltv->an_len - 2)) {
  909                 printf("an%d: record length mismatch -- expected %d, "
  910                     "got %d for Rid %x\n", sc->an_unit,
  911                     ltv->an_len - 2, len, ltv->an_type);
  912                 len = ltv->an_len - 2;
  913         } else {
  914                 ltv->an_len = len + 2;
  915         }
  916 
  917         /* Now read the data. */
  918         len -= 2;       /* skip the type */
  919         ptr = &ltv->an_val;
  920         for (i = len; i > 1; i -= 2)
  921                 *ptr++ = CSR_READ_2(sc, AN_DATA1);
  922         if (i) {
  923                 ptr2 = (u_int8_t *)ptr;
  924                 *ptr2 = CSR_READ_1(sc, AN_DATA1);
  925         }
  926         if (an_dump)
  927                 an_dump_record(sc, ltv, "Read");
  928 
  929         return(0);
  930 }
  931 
  932 /*
  933  * Same as read, except we inject data instead of reading it.
  934  */
  935 static int
  936 an_write_record(sc, ltv)
  937         struct an_softc         *sc;
  938         struct an_ltv_gen       *ltv;
  939 {
  940         u_int16_t               *ptr;
  941         u_int8_t                *ptr2;
  942         int                     i, len;
  943 
  944         if (an_dump)
  945                 an_dump_record(sc, ltv, "Write");
  946 
  947         if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
  948                 return(EIO);
  949 
  950         if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
  951                 return(EIO);
  952 
  953         /*
  954          * Length includes type but not length.
  955          */
  956         len = ltv->an_len - 2;
  957         CSR_WRITE_2(sc, AN_DATA1, len);
  958 
  959         len -= 2;       /* skip the type */
  960         ptr = &ltv->an_val;
  961         for (i = len; i > 1; i -= 2)
  962                 CSR_WRITE_2(sc, AN_DATA1, *ptr++);
  963         if (i) {
  964                 ptr2 = (u_int8_t *)ptr;
  965                 CSR_WRITE_1(sc, AN_DATA0, *ptr2);
  966         }
  967 
  968         if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
  969                 return(EIO);
  970 
  971         return(0);
  972 }
  973 
  974 static void
  975 an_dump_record(sc, ltv, string)
  976         struct an_softc         *sc;
  977         struct an_ltv_gen       *ltv;
  978         char                    *string;
  979 {
  980         u_int8_t                *ptr2;
  981         int                     len;
  982         int                     i;
  983         int                     count = 0;
  984         char                    buf[17], temp;
  985 
  986         len = ltv->an_len - 4;
  987         printf("an%d: RID %4x, Length %4d, Mode %s\n",
  988                 sc->an_unit, ltv->an_type, ltv->an_len - 4, string);
  989 
  990         if (an_dump == 1 || (an_dump == ltv->an_type)) {
  991                 printf("an%d:\t", sc->an_unit);
  992                 bzero(buf,sizeof(buf));
  993 
  994                 ptr2 = (u_int8_t *)&ltv->an_val;
  995                 for (i = len; i > 0; i--) {
  996                         printf("%02x ", *ptr2);
  997 
  998                         temp = *ptr2++;
  999                         if (temp >= ' ' && temp <= '~')
 1000                                 buf[count] = temp;
 1001                         else if (temp >= 'A' && temp <= 'Z')
 1002                                 buf[count] = temp;
 1003                         else
 1004                                 buf[count] = '.';
 1005                         if (++count == 16) {
 1006                                 count = 0;
 1007                                 printf("%s\n",buf);
 1008                                 printf("an%d:\t", sc->an_unit);
 1009                                 bzero(buf,sizeof(buf));
 1010                         }
 1011                 }
 1012                 for (; count != 16; count++) {
 1013                         printf("   ");
 1014                 }
 1015                 printf(" %s\n",buf);
 1016         }
 1017 }
 1018 
 1019 static int
 1020 an_seek(sc, id, off, chan)
 1021         struct an_softc         *sc;
 1022         int                     id, off, chan;
 1023 {
 1024         int                     i;
 1025         int                     selreg, offreg;
 1026 
 1027         switch (chan) {
 1028         case AN_BAP0:
 1029                 selreg = AN_SEL0;
 1030                 offreg = AN_OFF0;
 1031                 break;
 1032         case AN_BAP1:
 1033                 selreg = AN_SEL1;
 1034                 offreg = AN_OFF1;
 1035                 break;
 1036         default:
 1037                 printf("an%d: invalid data path: %x\n", sc->an_unit, chan);
 1038                 return(EIO);
 1039         }
 1040 
 1041         CSR_WRITE_2(sc, selreg, id);
 1042         CSR_WRITE_2(sc, offreg, off);
 1043 
 1044         for (i = 0; i < AN_TIMEOUT; i++) {
 1045                 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR)))
 1046                         break;
 1047         }
 1048 
 1049         if (i == AN_TIMEOUT)
 1050                 return(ETIMEDOUT);
 1051 
 1052         return(0);
 1053 }
 1054 
 1055 static int
 1056 an_read_data(sc, id, off, buf, len)
 1057         struct an_softc         *sc;
 1058         int                     id, off;
 1059         caddr_t                 buf;
 1060         int                     len;
 1061 {
 1062         int                     i;
 1063         u_int16_t               *ptr;
 1064         u_int8_t                *ptr2;
 1065 
 1066         if (off != -1) {
 1067                 if (an_seek(sc, id, off, AN_BAP1))
 1068                         return(EIO);
 1069         }
 1070 
 1071         ptr = (u_int16_t *)buf;
 1072         for (i = len; i > 1; i -= 2)
 1073                 *ptr++ = CSR_READ_2(sc, AN_DATA1);
 1074         if (i) {
 1075                 ptr2 = (u_int8_t *)ptr;
 1076                 *ptr2 = CSR_READ_1(sc, AN_DATA1);
 1077         }
 1078 
 1079         return(0);
 1080 }
 1081 
 1082 static int
 1083 an_write_data(sc, id, off, buf, len)
 1084         struct an_softc         *sc;
 1085         int                     id, off;
 1086         caddr_t                 buf;
 1087         int                     len;
 1088 {
 1089         int                     i;
 1090         u_int16_t               *ptr;
 1091         u_int8_t                *ptr2;
 1092 
 1093         if (off != -1) {
 1094                 if (an_seek(sc, id, off, AN_BAP0))
 1095                         return(EIO);
 1096         }
 1097 
 1098         ptr = (u_int16_t *)buf;
 1099         for (i = len; i > 1; i -= 2)
 1100                 CSR_WRITE_2(sc, AN_DATA0, *ptr++);
 1101         if (i) {
 1102                 ptr2 = (u_int8_t *)ptr;
 1103                 CSR_WRITE_1(sc, AN_DATA0, *ptr2);
 1104         }
 1105 
 1106         return(0);
 1107 }
 1108 
 1109 /*
 1110  * Allocate a region of memory inside the NIC and zero
 1111  * it out.
 1112  */
 1113 static int
 1114 an_alloc_nicmem(sc, len, id)
 1115         struct an_softc         *sc;
 1116         int                     len;
 1117         int                     *id;
 1118 {
 1119         int                     i;
 1120 
 1121         if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
 1122                 printf("an%d: failed to allocate %d bytes on NIC\n",
 1123                     sc->an_unit, len);
 1124                 return(ENOMEM);
 1125         }
 1126 
 1127         for (i = 0; i < AN_TIMEOUT; i++) {
 1128                 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
 1129                         break;
 1130         }
 1131 
 1132         if (i == AN_TIMEOUT)
 1133                 return(ETIMEDOUT);
 1134 
 1135         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
 1136         *id = CSR_READ_2(sc, AN_ALLOC_FID);
 1137 
 1138         if (an_seek(sc, *id, 0, AN_BAP0))
 1139                 return(EIO);
 1140 
 1141         for (i = 0; i < len / 2; i++)
 1142                 CSR_WRITE_2(sc, AN_DATA0, 0);
 1143 
 1144         return(0);
 1145 }
 1146 
 1147 static void
 1148 an_setdef(sc, areq)
 1149         struct an_softc         *sc;
 1150         struct an_req           *areq;
 1151 {
 1152         struct sockaddr_dl      *sdl;
 1153         struct ifaddr           *ifa;
 1154         struct ifnet            *ifp;
 1155         struct an_ltv_genconfig *cfg;
 1156         struct an_ltv_ssidlist  *ssid;
 1157         struct an_ltv_aplist    *ap;
 1158         struct an_ltv_gen       *sp;
 1159 
 1160         ifp = &sc->arpcom.ac_if;
 1161 
 1162         switch (areq->an_type) {
 1163         case AN_RID_GENCONFIG:
 1164                 cfg = (struct an_ltv_genconfig *)areq;
 1165 
 1166                 ifa = ifaddr_byindex(ifp->if_index);
 1167                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 1168                 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr,
 1169                     ETHER_ADDR_LEN);
 1170                 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN);
 1171 
 1172                 bcopy((char *)cfg, (char *)&sc->an_config,
 1173                         sizeof(struct an_ltv_genconfig));
 1174                 break;
 1175         case AN_RID_SSIDLIST:
 1176                 ssid = (struct an_ltv_ssidlist *)areq;
 1177                 bcopy((char *)ssid, (char *)&sc->an_ssidlist,
 1178                         sizeof(struct an_ltv_ssidlist));
 1179                 break;
 1180         case AN_RID_APLIST:
 1181                 ap = (struct an_ltv_aplist *)areq;
 1182                 bcopy((char *)ap, (char *)&sc->an_aplist,
 1183                         sizeof(struct an_ltv_aplist));
 1184                 break;
 1185         case AN_RID_TX_SPEED:
 1186                 sp = (struct an_ltv_gen *)areq;
 1187                 sc->an_tx_rate = sp->an_val;
 1188                 break;
 1189         case AN_RID_WEP_TEMP:
 1190         case AN_RID_WEP_PERM:
 1191         case AN_RID_LEAPUSERNAME:
 1192         case AN_RID_LEAPPASSWORD:
 1193                 /* Disable the MAC. */
 1194                 an_cmd(sc, AN_CMD_DISABLE, 0);
 1195 
 1196                 /* Write the key */
 1197                 an_write_record(sc, (struct an_ltv_gen *)areq);
 1198 
 1199                 /* Turn the MAC back on. */
 1200                 an_cmd(sc, AN_CMD_ENABLE, 0);
 1201 
 1202                 break;
 1203         case AN_RID_MONITOR_MODE:
 1204                 cfg = (struct an_ltv_genconfig *)areq;
 1205                 bpfdetach(ifp);
 1206                 if (ng_ether_detach_p != NULL)
 1207                         (*ng_ether_detach_p) (ifp);
 1208                 sc->an_monitor = cfg->an_len;
 1209 
 1210                 if (sc->an_monitor & AN_MONITOR) {
 1211                         if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) {
 1212                                 bpfattach(ifp, DLT_AIRONET_HEADER,
 1213                                         sizeof(struct ether_header));
 1214                         } else {
 1215                                 bpfattach(ifp, DLT_IEEE802_11,
 1216                                         sizeof(struct ether_header));
 1217                         }
 1218                 } else {
 1219                         bpfattach(ifp, DLT_EN10MB,
 1220                                   sizeof(struct ether_header));
 1221                         if (ng_ether_attach_p != NULL)
 1222                                 (*ng_ether_attach_p) (ifp);
 1223                 }
 1224                 break;
 1225         default:
 1226                 printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type);
 1227                 return;
 1228                 break;
 1229         }
 1230 
 1231 
 1232         /* Reinitialize the card. */
 1233         if (ifp->if_flags)
 1234                 an_init(sc);
 1235 
 1236         return;
 1237 }
 1238 
 1239 /*
 1240  * Derived from Linux driver to enable promiscious mode.
 1241  */
 1242 
 1243 static void
 1244 an_promisc(sc, promisc)
 1245         struct an_softc         *sc;
 1246         int                     promisc;
 1247 {
 1248         if (sc->an_was_monitor)
 1249                 an_reset(sc);
 1250         if (sc->an_monitor || sc->an_was_monitor)
 1251                 an_init(sc);
 1252 
 1253         sc->an_was_monitor = sc->an_monitor;
 1254         an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0);
 1255 
 1256         return;
 1257 }
 1258 
 1259 static int
 1260 an_ioctl(ifp, command, data)
 1261         struct ifnet            *ifp;
 1262         u_long                  command;
 1263         caddr_t                 data;
 1264 {
 1265         int                     error = 0;
 1266         int                     len;
 1267         int                     i;
 1268         struct an_softc         *sc;
 1269         struct ifreq            *ifr;
 1270         struct thread           *td = curthread;
 1271         struct ieee80211req     *ireq;
 1272         u_int8_t                tmpstr[IEEE80211_NWID_LEN*2];
 1273         u_int8_t                *tmpptr;
 1274         struct an_ltv_genconfig *config;
 1275         struct an_ltv_key       *key;
 1276         struct an_ltv_status    *status;
 1277         struct an_ltv_ssidlist  *ssids;
 1278         int                     mode;
 1279         struct aironet_ioctl    l_ioctl;
 1280 
 1281         sc = ifp->if_softc;
 1282         AN_LOCK(sc);
 1283         ifr = (struct ifreq *)data;
 1284         ireq = (struct ieee80211req *)data;
 1285 
 1286         config = (struct an_ltv_genconfig *)&sc->areq;
 1287         key = (struct an_ltv_key *)&sc->areq;
 1288         status = (struct an_ltv_status *)&sc->areq;
 1289         ssids = (struct an_ltv_ssidlist *)&sc->areq;
 1290 
 1291         if (sc->an_gone) {
 1292                 error = ENODEV;
 1293                 goto out;
 1294         }
 1295 
 1296         switch (command) {
 1297         case SIOCSIFFLAGS:
 1298                 if (ifp->if_flags & IFF_UP) {
 1299                         if (ifp->if_flags & IFF_RUNNING &&
 1300                             ifp->if_flags & IFF_PROMISC &&
 1301                             !(sc->an_if_flags & IFF_PROMISC)) {
 1302                                 an_promisc(sc, 1);
 1303                         } else if (ifp->if_flags & IFF_RUNNING &&
 1304                             !(ifp->if_flags & IFF_PROMISC) &&
 1305                             sc->an_if_flags & IFF_PROMISC) {
 1306                                 an_promisc(sc, 0);
 1307                         } else
 1308                                 an_init(sc);
 1309                 } else {
 1310                         if (ifp->if_flags & IFF_RUNNING)
 1311                                 an_stop(sc);
 1312                 }
 1313                 sc->an_if_flags = ifp->if_flags;
 1314                 error = 0;
 1315                 break;
 1316         case SIOCSIFMEDIA:
 1317         case SIOCGIFMEDIA:
 1318                 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command);
 1319                 break;
 1320         case SIOCADDMULTI:
 1321         case SIOCDELMULTI:
 1322                 /* The Aironet has no multicast filter. */
 1323                 error = 0;
 1324                 break;
 1325         case SIOCGAIRONET:
 1326                 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq));
 1327                 if (error != 0)
 1328                         break;
 1329 #ifdef ANCACHE
 1330                 if (sc->areq.an_type == AN_RID_ZERO_CACHE) {
 1331                         sc->an_sigitems = sc->an_nextitem = 0;
 1332                         break;
 1333                 } else if (sc->areq.an_type == AN_RID_READ_CACHE) {
 1334                         char *pt = (char *)&sc->areq.an_val;
 1335                         bcopy((char *)&sc->an_sigitems, (char *)pt,
 1336                             sizeof(int));
 1337                         pt += sizeof(int);
 1338                         sc->areq.an_len = sizeof(int) / 2;
 1339                         bcopy((char *)&sc->an_sigcache, (char *)pt,
 1340                             sizeof(struct an_sigcache) * sc->an_sigitems);
 1341                         sc->areq.an_len += ((sizeof(struct an_sigcache) *
 1342                             sc->an_sigitems) / 2) + 1;
 1343                 } else
 1344 #endif
 1345                 if (an_read_record(sc, (struct an_ltv_gen *)&sc->areq)) {
 1346                         error = EINVAL;
 1347                         break;
 1348                 }
 1349                 error = copyout(&sc->areq, ifr->ifr_data, sizeof(sc->areq));
 1350                 break;
 1351         case SIOCSAIRONET:
 1352                 if ((error = suser(td)))
 1353                         goto out;
 1354                 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq));
 1355                 if (error != 0)
 1356                         break;
 1357                 an_setdef(sc, &sc->areq);
 1358                 break;
 1359         case SIOCGPRIVATE_0:              /* used by Cisco client utility */
 1360                 if ((error = suser(td)))
 1361                         goto out;
 1362                 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
 1363                 mode = l_ioctl.command;
 1364 
 1365                 if (mode >= AIROGCAP && mode <= AIROGSTATSD32) {
 1366                         error = readrids(ifp, &l_ioctl);
 1367                 }else if (mode >= AIROPCAP && mode <= AIROPLEAPUSR) {
 1368                         error = writerids(ifp, &l_ioctl);
 1369                 }else if (mode >= AIROFLSHRST && mode <= AIRORESTART) {
 1370                         error = flashcard(ifp, &l_ioctl);
 1371                 }else{
 1372                         error =-1;
 1373                 }
 1374 
 1375                 /* copy out the updated command info */
 1376                 copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl));
 1377 
 1378                 break;
 1379         case SIOCGPRIVATE_1:              /* used by Cisco client utility */
 1380                 if ((error = suser(td)))
 1381                         goto out;
 1382                 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
 1383                 l_ioctl.command = 0;
 1384                 error = AIROMAGIC;
 1385                 copyout(&error, l_ioctl.data, sizeof(error));
 1386                 error = 0;
 1387                 break;
 1388         case SIOCG80211:
 1389                 sc->areq.an_len = sizeof(sc->areq);
 1390                 /* was that a good idea DJA we are doing a short-cut */
 1391                 switch (ireq->i_type) {
 1392                 case IEEE80211_IOC_SSID:
 1393                         if (ireq->i_val == -1) {
 1394                                 sc->areq.an_type = AN_RID_STATUS;
 1395                                 if (an_read_record(sc,
 1396                                     (struct an_ltv_gen *)&sc->areq)) {
 1397                                         error = EINVAL;
 1398                                         break;
 1399                                 }
 1400                                 len = status->an_ssidlen;
 1401                                 tmpptr = status->an_ssid;
 1402                         } else if (ireq->i_val >= 0) {
 1403                                 sc->areq.an_type = AN_RID_SSIDLIST;
 1404                                 if (an_read_record(sc,
 1405                                     (struct an_ltv_gen *)&sc->areq)) {
 1406                                         error = EINVAL;
 1407                                         break;
 1408                                 }
 1409                                 if (ireq->i_val == 0) {
 1410                                         len = ssids->an_ssid1_len;
 1411                                         tmpptr = ssids->an_ssid1;
 1412                                 } else if (ireq->i_val == 1) {
 1413                                         len = ssids->an_ssid2_len;
 1414                                         tmpptr = ssids->an_ssid2;
 1415                                 } else if (ireq->i_val == 2) {
 1416                                         len = ssids->an_ssid3_len;
 1417                                         tmpptr = ssids->an_ssid3;
 1418                                 } else {
 1419                                         error = EINVAL;
 1420                                         break;
 1421                                 }
 1422                         } else {
 1423                                 error = EINVAL;
 1424                                 break;
 1425                         }
 1426                         if (len > IEEE80211_NWID_LEN) {
 1427                                 error = EINVAL;
 1428                                 break;
 1429                         }
 1430                         ireq->i_len = len;
 1431                         bzero(tmpstr, IEEE80211_NWID_LEN);
 1432                         bcopy(tmpptr, tmpstr, len);
 1433                         error = copyout(tmpstr, ireq->i_data,
 1434                             IEEE80211_NWID_LEN);
 1435                         break;
 1436                 case IEEE80211_IOC_NUMSSIDS:
 1437                         ireq->i_val = 3;
 1438                         break;
 1439                 case IEEE80211_IOC_WEP:
 1440                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1441                         if (an_read_record(sc,
 1442                             (struct an_ltv_gen *)&sc->areq)) {
 1443                                 error = EINVAL;
 1444                                 break;
 1445                         }
 1446                         if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
 1447                                 if (config->an_authtype &
 1448                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED)
 1449                                         ireq->i_val = IEEE80211_WEP_MIXED;
 1450                                 else
 1451                                         ireq->i_val = IEEE80211_WEP_ON;
 1452                         } else {
 1453                                 ireq->i_val = IEEE80211_WEP_OFF;
 1454                         }
 1455                         break;
 1456                 case IEEE80211_IOC_WEPKEY:
 1457                         /*
 1458                          * XXX: I'm not entierly convinced this is
 1459                          * correct, but it's what is implemented in
 1460                          * ancontrol so it will have to do until we get
 1461                          * access to actual Cisco code.
 1462                          */
 1463                         if (ireq->i_val < 0 || ireq->i_val > 8) {
 1464                                 error = EINVAL;
 1465                                 break;
 1466                         }
 1467                         len = 0;
 1468                         if (ireq->i_val < 5) {
 1469                                 sc->areq.an_type = AN_RID_WEP_TEMP;
 1470                                 for (i = 0; i < 5; i++) {
 1471                                         if (an_read_record(sc,
 1472                                             (struct an_ltv_gen *)&sc->areq)) {
 1473                                                 error = EINVAL;
 1474                                                 break;
 1475                                         }
 1476                                         if (key->kindex == 0xffff)
 1477                                                 break;
 1478                                         if (key->kindex == ireq->i_val)
 1479                                                 len = key->klen;
 1480                                         /* Required to get next entry */
 1481                                         sc->areq.an_type = AN_RID_WEP_PERM;
 1482                                 }
 1483                                 if (error != 0)
 1484                                         break;
 1485                         }
 1486                         /* We aren't allowed to read the value of the
 1487                          * key from the card so we just output zeros
 1488                          * like we would if we could read the card, but
 1489                          * denied the user access.
 1490                          */
 1491                         bzero(tmpstr, len);
 1492                         ireq->i_len = len;
 1493                         error = copyout(tmpstr, ireq->i_data, len);
 1494                         break;
 1495                 case IEEE80211_IOC_NUMWEPKEYS:
 1496                         ireq->i_val = 9; /* include home key */
 1497                         break;
 1498                 case IEEE80211_IOC_WEPTXKEY:
 1499                         /*
 1500                          * For some strange reason, you have to read all
 1501                          * keys before you can read the txkey.
 1502                          */
 1503                         sc->areq.an_type = AN_RID_WEP_TEMP;
 1504                         for (i = 0; i < 5; i++) {
 1505                                 if (an_read_record(sc,
 1506                                     (struct an_ltv_gen *) &sc->areq)) {
 1507                                         error = EINVAL;
 1508                                         break;
 1509                                 }
 1510                                 if (key->kindex == 0xffff)
 1511                                         break;
 1512                                 /* Required to get next entry */
 1513                                 sc->areq.an_type = AN_RID_WEP_PERM;
 1514                         }
 1515                         if (error != 0)
 1516                                 break;
 1517 
 1518                         sc->areq.an_type = AN_RID_WEP_PERM;
 1519                         key->kindex = 0xffff;
 1520                         if (an_read_record(sc,
 1521                             (struct an_ltv_gen *)&sc->areq)) {
 1522                                 error = EINVAL;
 1523                                 break;
 1524                         }
 1525                         ireq->i_val = key->mac[0];
 1526                         /*
 1527                          * Check for home mode.  Map home mode into
 1528                          * 5th key since that is how it is stored on
 1529                          * the card
 1530                          */
 1531                         sc->areq.an_len  = sizeof(struct an_ltv_genconfig);
 1532                         sc->areq.an_type = AN_RID_GENCONFIG;
 1533                         if (an_read_record(sc,
 1534                             (struct an_ltv_gen *)&sc->areq)) {
 1535                                 error = EINVAL;
 1536                                 break;
 1537                         }
 1538                         if (config->an_home_product & AN_HOME_NETWORK)
 1539                                 ireq->i_val = 4;
 1540                         break;
 1541                 case IEEE80211_IOC_AUTHMODE:
 1542                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1543                         if (an_read_record(sc,
 1544                             (struct an_ltv_gen *)&sc->areq)) {
 1545                                 error = EINVAL;
 1546                                 break;
 1547                         }
 1548                         if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
 1549                             AN_AUTHTYPE_NONE) {
 1550                             ireq->i_val = IEEE80211_AUTH_NONE;
 1551                         } else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
 1552                             AN_AUTHTYPE_OPEN) {
 1553                             ireq->i_val = IEEE80211_AUTH_OPEN;
 1554                         } else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
 1555                             AN_AUTHTYPE_SHAREDKEY) {
 1556                             ireq->i_val = IEEE80211_AUTH_SHARED;
 1557                         } else
 1558                                 error = EINVAL;
 1559                         break;
 1560                 case IEEE80211_IOC_STATIONNAME:
 1561                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1562                         if (an_read_record(sc,
 1563                             (struct an_ltv_gen *)&sc->areq)) {
 1564                                 error = EINVAL;
 1565                                 break;
 1566                         }
 1567                         ireq->i_len = sizeof(config->an_nodename);
 1568                         tmpptr = config->an_nodename;
 1569                         bzero(tmpstr, IEEE80211_NWID_LEN);
 1570                         bcopy(tmpptr, tmpstr, ireq->i_len);
 1571                         error = copyout(tmpstr, ireq->i_data,
 1572                             IEEE80211_NWID_LEN);
 1573                         break;
 1574                 case IEEE80211_IOC_CHANNEL:
 1575                         sc->areq.an_type = AN_RID_STATUS;
 1576                         if (an_read_record(sc,
 1577                             (struct an_ltv_gen *)&sc->areq)) {
 1578                                 error = EINVAL;
 1579                                 break;
 1580                         }
 1581                         ireq->i_val = status->an_cur_channel;
 1582                         break;
 1583                 case IEEE80211_IOC_POWERSAVE:
 1584                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1585                         if (an_read_record(sc,
 1586                             (struct an_ltv_gen *)&sc->areq)) {
 1587                                 error = EINVAL;
 1588                                 break;
 1589                         }
 1590                         if (config->an_psave_mode == AN_PSAVE_NONE) {
 1591                                 ireq->i_val = IEEE80211_POWERSAVE_OFF;
 1592                         } else if (config->an_psave_mode == AN_PSAVE_CAM) {
 1593                                 ireq->i_val = IEEE80211_POWERSAVE_CAM;
 1594                         } else if (config->an_psave_mode == AN_PSAVE_PSP) {
 1595                                 ireq->i_val = IEEE80211_POWERSAVE_PSP;
 1596                         } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) {
 1597                                 ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM;
 1598                         } else
 1599                                 error = EINVAL;
 1600                         break;
 1601                 case IEEE80211_IOC_POWERSAVESLEEP:
 1602                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1603                         if (an_read_record(sc,
 1604                             (struct an_ltv_gen *)&sc->areq)) {
 1605                                 error = EINVAL;
 1606                                 break;
 1607                         }
 1608                         ireq->i_val = config->an_listen_interval;
 1609                         break;
 1610                 }
 1611                 break;
 1612         case SIOCS80211:
 1613                 if ((error = suser(td)))
 1614                         goto out;
 1615                 sc->areq.an_len = sizeof(sc->areq);
 1616                 /*
 1617                  * We need a config structure for everything but the WEP
 1618                  * key management and SSIDs so we get it now so avoid
 1619                  * duplicating this code every time.
 1620                  */
 1621                 if (ireq->i_type != IEEE80211_IOC_SSID &&
 1622                     ireq->i_type != IEEE80211_IOC_WEPKEY &&
 1623                     ireq->i_type != IEEE80211_IOC_WEPTXKEY) {
 1624                         sc->areq.an_type = AN_RID_GENCONFIG;
 1625                         if (an_read_record(sc,
 1626                             (struct an_ltv_gen *)&sc->areq)) {
 1627                                 error = EINVAL;
 1628                                 break;
 1629                         }
 1630                 }
 1631                 switch (ireq->i_type) {
 1632                 case IEEE80211_IOC_SSID:
 1633                         sc->areq.an_type = AN_RID_SSIDLIST;
 1634                         if (an_read_record(sc,
 1635                             (struct an_ltv_gen *)&sc->areq)) {
 1636                                 error = EINVAL;
 1637                                 break;
 1638                         }
 1639                         if (ireq->i_len > IEEE80211_NWID_LEN) {
 1640                                 error = EINVAL;
 1641                                 break;
 1642                         }
 1643                         switch (ireq->i_val) {
 1644                         case 0:
 1645                                 error = copyin(ireq->i_data,
 1646                                     ssids->an_ssid1, ireq->i_len);
 1647                                 ssids->an_ssid1_len = ireq->i_len;
 1648                                 break;
 1649                         case 1:
 1650                                 error = copyin(ireq->i_data,
 1651                                     ssids->an_ssid2, ireq->i_len);
 1652                                 ssids->an_ssid2_len = ireq->i_len;
 1653                                 break;
 1654                         case 2:
 1655                                 error = copyin(ireq->i_data,
 1656                                     ssids->an_ssid3, ireq->i_len);
 1657                                 ssids->an_ssid3_len = ireq->i_len;
 1658                                 break;
 1659                         default:
 1660                                 error = EINVAL;
 1661                                 break;
 1662                         }
 1663                         break;
 1664                 case IEEE80211_IOC_WEP:
 1665                         switch (ireq->i_val) {
 1666                         case IEEE80211_WEP_OFF:
 1667                                 config->an_authtype &=
 1668                                     ~(AN_AUTHTYPE_PRIVACY_IN_USE |
 1669                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED);
 1670                                 break;
 1671                         case IEEE80211_WEP_ON:
 1672                                 config->an_authtype |=
 1673                                     AN_AUTHTYPE_PRIVACY_IN_USE;
 1674                                 config->an_authtype &=
 1675                                     ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
 1676                                 break;
 1677                         case IEEE80211_WEP_MIXED:
 1678                                 config->an_authtype |=
 1679                                     AN_AUTHTYPE_PRIVACY_IN_USE |
 1680                                     AN_AUTHTYPE_ALLOW_UNENCRYPTED;
 1681                                 break;
 1682                         default:
 1683                                 error = EINVAL;
 1684                                 break;
 1685                         }
 1686                         break;
 1687                 case IEEE80211_IOC_WEPKEY:
 1688                         if (ireq->i_val < 0 || ireq->i_val > 7 ||
 1689                             ireq->i_len > 13) {
 1690                                 error = EINVAL;
 1691                                 break;
 1692                         }
 1693                         error = copyin(ireq->i_data, tmpstr, 13);
 1694                         if (error != 0)
 1695                                 break;
 1696                         bzero(&sc->areq, sizeof(struct an_ltv_key));
 1697                         sc->areq.an_len = sizeof(struct an_ltv_key);
 1698                         key->mac[0] = 1;        /* The others are 0. */
 1699                         key->kindex = ireq->i_val % 4;
 1700                         if (ireq->i_val < 4)
 1701                                 sc->areq.an_type = AN_RID_WEP_TEMP;
 1702                         else
 1703                                 sc->areq.an_type = AN_RID_WEP_PERM;
 1704                         key->klen = ireq->i_len;
 1705                         bcopy(tmpstr, key->key, key->klen);
 1706                         break;
 1707                 case IEEE80211_IOC_WEPTXKEY:
 1708                         /*
 1709                          * Map the 5th key into the home mode
 1710                          * since that is how it is stored on
 1711                          * the card
 1712                          */
 1713                         if (ireq->i_val < 0 || ireq->i_val > 4) {
 1714                                 error = EINVAL;
 1715                                 break;
 1716                         }
 1717                         sc->areq.an_len  = sizeof(struct an_ltv_genconfig);
 1718                         sc->areq.an_type = AN_RID_ACTUALCFG;
 1719                         if (an_read_record(sc,
 1720                             (struct an_ltv_gen *)&sc->areq)) {
 1721                                 error = EINVAL;
 1722                                 break;
 1723                         }
 1724                         if (ireq->i_val ==  4) {
 1725                                 config->an_home_product |= AN_HOME_NETWORK;
 1726                                 ireq->i_val = 0;
 1727                         } else {
 1728                                 config->an_home_product &= ~AN_HOME_NETWORK;
 1729                         }
 1730 
 1731                         sc->an_config.an_home_product
 1732                                 = config->an_home_product;
 1733                         an_write_record(sc, (struct an_ltv_gen *)&sc->areq);
 1734 
 1735                         bzero(&sc->areq, sizeof(struct an_ltv_key));
 1736                         sc->areq.an_len = sizeof(struct an_ltv_key);
 1737                         sc->areq.an_type = AN_RID_WEP_PERM;
 1738                         key->kindex = 0xffff;
 1739                         key->mac[0] = ireq->i_val;
 1740                         break;
 1741                 case IEEE80211_IOC_AUTHMODE:
 1742                         switch (ireq->i_val) {
 1743                         case IEEE80211_AUTH_NONE:
 1744                                 config->an_authtype = AN_AUTHTYPE_NONE |
 1745                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
 1746                                 break;
 1747                         case IEEE80211_AUTH_OPEN:
 1748                                 config->an_authtype = AN_AUTHTYPE_OPEN |
 1749                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
 1750                                 break;
 1751                         case IEEE80211_AUTH_SHARED:
 1752                                 config->an_authtype = AN_AUTHTYPE_SHAREDKEY |
 1753                                     (config->an_authtype & ~AN_AUTHTYPE_MASK);
 1754                                 break;
 1755                         default:
 1756                                 error = EINVAL;
 1757                         }
 1758                         break;
 1759                 case IEEE80211_IOC_STATIONNAME:
 1760                         if (ireq->i_len > 16) {
 1761                                 error = EINVAL;
 1762                                 break;
 1763                         }
 1764                         bzero(config->an_nodename, 16);
 1765                         error = copyin(ireq->i_data,
 1766                             config->an_nodename, ireq->i_len);
 1767                         break;
 1768                 case IEEE80211_IOC_CHANNEL:
 1769                         /*
 1770                          * The actual range is 1-14, but if you set it
 1771                          * to 0 you get the default so we let that work
 1772                          * too.
 1773                          */
 1774                         if (ireq->i_val < 0 || ireq->i_val >14) {
 1775                                 error = EINVAL;
 1776                                 break;
 1777                         }
 1778                         config->an_ds_channel = ireq->i_val;
 1779                         break;
 1780                 case IEEE80211_IOC_POWERSAVE:
 1781                         switch (ireq->i_val) {
 1782                         case IEEE80211_POWERSAVE_OFF:
 1783                                 config->an_psave_mode = AN_PSAVE_NONE;
 1784                                 break;
 1785                         case IEEE80211_POWERSAVE_CAM:
 1786                                 config->an_psave_mode = AN_PSAVE_CAM;
 1787                                 break;
 1788                         case IEEE80211_POWERSAVE_PSP:
 1789                                 config->an_psave_mode = AN_PSAVE_PSP;
 1790                                 break;
 1791                         case IEEE80211_POWERSAVE_PSP_CAM:
 1792                                 config->an_psave_mode = AN_PSAVE_PSP_CAM;
 1793                                 break;
 1794                         default:
 1795                                 error = EINVAL;
 1796                                 break;
 1797                         }
 1798                         break;
 1799                 case IEEE80211_IOC_POWERSAVESLEEP:
 1800                         config->an_listen_interval = ireq->i_val;
 1801                         break;
 1802                 }
 1803 
 1804                 if (!error)
 1805                         an_setdef(sc, &sc->areq);
 1806                 break;
 1807         default:
 1808                 error = ether_ioctl(ifp, command, data);
 1809                 break;
 1810         }
 1811 out:
 1812         AN_UNLOCK(sc);
 1813 
 1814         return(error != 0);
 1815 }
 1816 
 1817 static int
 1818 an_init_tx_ring(sc)
 1819         struct an_softc         *sc;
 1820 {
 1821         int                     i;
 1822         int                     id;
 1823 
 1824         if (sc->an_gone)
 1825                 return (0);
 1826 
 1827         for (i = 0; i < AN_TX_RING_CNT; i++) {
 1828                 if (an_alloc_nicmem(sc, 1518 +
 1829                     0x44, &id))
 1830                         return(ENOMEM);
 1831                 sc->an_rdata.an_tx_fids[i] = id;
 1832                 sc->an_rdata.an_tx_ring[i] = 0;
 1833         }
 1834 
 1835         sc->an_rdata.an_tx_prod = 0;
 1836         sc->an_rdata.an_tx_cons = 0;
 1837 
 1838         return(0);
 1839 }
 1840 
 1841 static void
 1842 an_init(xsc)
 1843         void                    *xsc;
 1844 {
 1845         struct an_softc         *sc = xsc;
 1846         struct ifnet            *ifp = &sc->arpcom.ac_if;
 1847 
 1848         AN_LOCK(sc);
 1849 
 1850         if (sc->an_gone) {
 1851                 AN_UNLOCK(sc);
 1852                 return;
 1853         }
 1854 
 1855         if (ifp->if_flags & IFF_RUNNING)
 1856                 an_stop(sc);
 1857 
 1858         sc->an_associated = 0;
 1859 
 1860         /* Allocate the TX buffers */
 1861         if (an_init_tx_ring(sc)) {
 1862                 an_reset(sc);
 1863                 if (an_init_tx_ring(sc)) {
 1864                         printf("an%d: tx buffer allocation "
 1865                             "failed\n", sc->an_unit);
 1866                         AN_UNLOCK(sc);
 1867                         return;
 1868                 }
 1869         }
 1870 
 1871         /* Set our MAC address. */
 1872         bcopy((char *)&sc->arpcom.ac_enaddr,
 1873             (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN);
 1874 
 1875         if (ifp->if_flags & IFF_BROADCAST)
 1876                 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR;
 1877         else
 1878                 sc->an_config.an_rxmode = AN_RXMODE_ADDR;
 1879 
 1880         if (ifp->if_flags & IFF_MULTICAST)
 1881                 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
 1882 
 1883         if (ifp->if_flags & IFF_PROMISC) {
 1884                 if (sc->an_monitor & AN_MONITOR) {
 1885                         if (sc->an_monitor & AN_MONITOR_ANY_BSS) {
 1886                                 sc->an_config.an_rxmode |=
 1887                                     AN_RXMODE_80211_MONITOR_ANYBSS |
 1888                                     AN_RXMODE_NO_8023_HEADER;
 1889                         } else {
 1890                                 sc->an_config.an_rxmode |=
 1891                                     AN_RXMODE_80211_MONITOR_CURBSS |
 1892                                     AN_RXMODE_NO_8023_HEADER;
 1893                         }
 1894                 }
 1895         }
 1896 
 1897         /* Set the ssid list */
 1898         sc->an_ssidlist.an_type = AN_RID_SSIDLIST;
 1899         sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist);
 1900         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) {
 1901                 printf("an%d: failed to set ssid list\n", sc->an_unit);
 1902                 AN_UNLOCK(sc);
 1903                 return;
 1904         }
 1905 
 1906         /* Set the AP list */
 1907         sc->an_aplist.an_type = AN_RID_APLIST;
 1908         sc->an_aplist.an_len = sizeof(struct an_ltv_aplist);
 1909         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) {
 1910                 printf("an%d: failed to set AP list\n", sc->an_unit);
 1911                 AN_UNLOCK(sc);
 1912                 return;
 1913         }
 1914 
 1915         /* Set the configuration in the NIC */
 1916         sc->an_config.an_len = sizeof(struct an_ltv_genconfig);
 1917         sc->an_config.an_type = AN_RID_GENCONFIG;
 1918         if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) {
 1919                 printf("an%d: failed to set configuration\n", sc->an_unit);
 1920                 AN_UNLOCK(sc);
 1921                 return;
 1922         }
 1923 
 1924         /* Enable the MAC */
 1925         if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
 1926                 printf("an%d: failed to enable MAC\n", sc->an_unit);
 1927                 AN_UNLOCK(sc);
 1928                 return;
 1929         }
 1930 
 1931         if (ifp->if_flags & IFF_PROMISC)
 1932                 an_cmd(sc, AN_CMD_SET_MODE, 0xffff);
 1933 
 1934         /* enable interrupts */
 1935         CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
 1936 
 1937         ifp->if_flags |= IFF_RUNNING;
 1938         ifp->if_flags &= ~IFF_OACTIVE;
 1939 
 1940         sc->an_stat_ch = timeout(an_stats_update, sc, hz);
 1941         AN_UNLOCK(sc);
 1942 
 1943         return;
 1944 }
 1945 
 1946 static void
 1947 an_start(ifp)
 1948         struct ifnet            *ifp;
 1949 {
 1950         struct an_softc         *sc;
 1951         struct mbuf             *m0 = NULL;
 1952         struct an_txframe_802_3 tx_frame_802_3;
 1953         struct ether_header     *eh;
 1954         int                     id;
 1955         int                     idx;
 1956         unsigned char           txcontrol;
 1957 
 1958         sc = ifp->if_softc;
 1959 
 1960         if (sc->an_gone)
 1961                 return;
 1962 
 1963         if (ifp->if_flags & IFF_OACTIVE)
 1964                 return;
 1965 
 1966         if (!sc->an_associated)
 1967                 return;
 1968 
 1969         /* We can't send in monitor mode so toss any attempts. */
 1970         if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) {
 1971                 for (;;) {
 1972                         IF_DEQUEUE(&ifp->if_snd, m0);
 1973                         if (m0 == NULL)
 1974                                 break;
 1975                         m_freem(m0);
 1976                 }
 1977                 return;
 1978         }
 1979 
 1980         idx = sc->an_rdata.an_tx_prod;
 1981         bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3));
 1982 
 1983         while (sc->an_rdata.an_tx_ring[idx] == 0) {
 1984                 IF_DEQUEUE(&ifp->if_snd, m0);
 1985                 if (m0 == NULL)
 1986                         break;
 1987 
 1988                 id = sc->an_rdata.an_tx_fids[idx];
 1989                 eh = mtod(m0, struct ether_header *);
 1990 
 1991                 bcopy((char *)&eh->ether_dhost,
 1992                     (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN);
 1993                 bcopy((char *)&eh->ether_shost,
 1994                     (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN);
 1995 
 1996                 tx_frame_802_3.an_tx_802_3_payload_len =
 1997                   m0->m_pkthdr.len - 12;  /* minus src/dest mac & type */
 1998 
 1999                 m_copydata(m0, sizeof(struct ether_header) - 2 ,
 2000                     tx_frame_802_3.an_tx_802_3_payload_len,
 2001                     (caddr_t)&sc->an_txbuf);
 2002 
 2003                 txcontrol = AN_TXCTL_8023;
 2004                 /* write the txcontrol only */
 2005                 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
 2006                               sizeof(txcontrol));
 2007 
 2008                 /* 802_3 header */
 2009                 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3,
 2010                               sizeof(struct an_txframe_802_3));
 2011 
 2012                 /* in mbuf header type is just before payload */
 2013                 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf,
 2014                             tx_frame_802_3.an_tx_802_3_payload_len);
 2015 
 2016                 /*
 2017                  * If there's a BPF listner, bounce a copy of
 2018                  * this frame to him.
 2019                  */
 2020                 BPF_MTAP(ifp, m0);
 2021 
 2022                 m_freem(m0);
 2023                 m0 = NULL;
 2024 
 2025                 sc->an_rdata.an_tx_ring[idx] = id;
 2026                 if (an_cmd(sc, AN_CMD_TX, id))
 2027                         printf("an%d: xmit failed\n", sc->an_unit);
 2028 
 2029                 AN_INC(idx, AN_TX_RING_CNT);
 2030         }
 2031 
 2032         if (m0 != NULL)
 2033                 ifp->if_flags |= IFF_OACTIVE;
 2034 
 2035         sc->an_rdata.an_tx_prod = idx;
 2036 
 2037         /*
 2038          * Set a timeout in case the chip goes out to lunch.
 2039          */
 2040         ifp->if_timer = 5;
 2041 
 2042         return;
 2043 }
 2044 
 2045 void
 2046 an_stop(sc)
 2047         struct an_softc         *sc;
 2048 {
 2049         struct ifnet            *ifp;
 2050         int                     i;
 2051 
 2052         AN_LOCK(sc);
 2053 
 2054         if (sc->an_gone) {
 2055                 AN_UNLOCK(sc);
 2056                 return;
 2057         }
 2058 
 2059         ifp = &sc->arpcom.ac_if;
 2060 
 2061         an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
 2062         CSR_WRITE_2(sc, AN_INT_EN, 0);
 2063         an_cmd(sc, AN_CMD_DISABLE, 0);
 2064 
 2065         for (i = 0; i < AN_TX_RING_CNT; i++)
 2066                 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
 2067 
 2068         untimeout(an_stats_update, sc, sc->an_stat_ch);
 2069 
 2070         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
 2071 
 2072         AN_UNLOCK(sc);
 2073 
 2074         return;
 2075 }
 2076 
 2077 static void
 2078 an_watchdog(ifp)
 2079         struct ifnet            *ifp;
 2080 {
 2081         struct an_softc         *sc;
 2082 
 2083         sc = ifp->if_softc;
 2084         AN_LOCK(sc);
 2085 
 2086         if (sc->an_gone) {
 2087                 AN_UNLOCK(sc);
 2088                 return;
 2089         }
 2090 
 2091         printf("an%d: device timeout\n", sc->an_unit);
 2092 
 2093         an_reset(sc);
 2094         an_init(sc);
 2095 
 2096         ifp->if_oerrors++;
 2097         AN_UNLOCK(sc);
 2098 
 2099         return;
 2100 }
 2101 
 2102 void
 2103 an_shutdown(dev)
 2104         device_t                dev;
 2105 {
 2106         struct an_softc         *sc;
 2107 
 2108         sc = device_get_softc(dev);
 2109         an_stop(sc);
 2110 
 2111         return;
 2112 }
 2113 
 2114 #ifdef ANCACHE
 2115 /* Aironet signal strength cache code.
 2116  * store signal/noise/quality on per MAC src basis in
 2117  * a small fixed cache.  The cache wraps if > MAX slots
 2118  * used.  The cache may be zeroed out to start over.
 2119  * Two simple filters exist to reduce computation:
 2120  * 1. ip only (literally 0x800, ETHERTYPE_IP) which may be used
 2121  * to ignore some packets.  It defaults to ip only.
 2122  * it could be used to focus on broadcast, non-IP 802.11 beacons.
 2123  * 2. multicast/broadcast only.  This may be used to
 2124  * ignore unicast packets and only cache signal strength
 2125  * for multicast/broadcast packets (beacons); e.g., Mobile-IP
 2126  * beacons and not unicast traffic.
 2127  *
 2128  * The cache stores (MAC src(index), IP src (major clue), signal,
 2129  *      quality, noise)
 2130  *
 2131  * No apologies for storing IP src here.  It's easy and saves much
 2132  * trouble elsewhere.  The cache is assumed to be INET dependent,
 2133  * although it need not be.
 2134  *
 2135  * Note: the Aironet only has a single byte of signal strength value
 2136  * in the rx frame header, and it's not scaled to anything sensible.
 2137  * This is kind of lame, but it's all we've got.
 2138  */
 2139 
 2140 #ifdef documentation
 2141 
 2142 int an_sigitems;                                /* number of cached entries */
 2143 struct an_sigcache an_sigcache[MAXANCACHE];  /*  array of cache entries */
 2144 int an_nextitem;                                /*  index/# of entries */
 2145 
 2146 
 2147 #endif
 2148 
 2149 /* control variables for cache filtering.  Basic idea is
 2150  * to reduce cost (e.g., to only Mobile-IP agent beacons
 2151  * which are broadcast or multicast).  Still you might
 2152  * want to measure signal strength anth unicast ping packets
 2153  * on a pt. to pt. ant. setup.
 2154  */
 2155 /* set true if you want to limit cache items to broadcast/mcast
 2156  * only packets (not unicast).  Useful for mobile-ip beacons which
 2157  * are broadcast/multicast at network layer.  Default is all packets
 2158  * so ping/unicast anll work say anth pt. to pt. antennae setup.
 2159  */
 2160 static int an_cache_mcastonly = 0;
 2161 SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW,
 2162         &an_cache_mcastonly, 0, "");
 2163 
 2164 /* set true if you want to limit cache items to IP packets only
 2165 */
 2166 static int an_cache_iponly = 1;
 2167 SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW,
 2168         &an_cache_iponly, 0, "");
 2169 
 2170 /*
 2171  * an_cache_store, per rx packet store signal
 2172  * strength in MAC (src) indexed cache.
 2173  */
 2174 static void
 2175 an_cache_store (sc, eh, m, rx_quality)
 2176         struct an_softc *sc;
 2177         struct ether_header *eh;
 2178         struct mbuf *m;
 2179         unsigned short rx_quality;
 2180 {
 2181         struct ip *ip = 0;
 2182         int i;
 2183         static int cache_slot = 0;      /* use this cache entry */
 2184         static int wrapindex = 0;       /* next "free" cache entry */
 2185         int type_ipv4 = 0;
 2186 
 2187         /* filters:
 2188          * 1. ip only
 2189          * 2. configurable filter to throw out unicast packets,
 2190          * keep multicast only.
 2191          */
 2192 
 2193         if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
 2194                 type_ipv4 = 1;
 2195         }
 2196 
 2197         /* filter for ip packets only
 2198         */
 2199         if ( an_cache_iponly && !type_ipv4) {
 2200                 return;
 2201         }
 2202 
 2203         /* filter for broadcast/multicast only
 2204          */
 2205         if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
 2206                 return;
 2207         }
 2208 
 2209 #ifdef SIGDEBUG
 2210         printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n",
 2211             rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
 2212 #endif
 2213 
 2214         /* find the ip header.  we want to store the ip_src
 2215          * address.
 2216          */
 2217         if (type_ipv4) {
 2218                 ip = mtod(m, struct ip *);
 2219         }
 2220 
 2221         /* do a linear search for a matching MAC address
 2222          * in the cache table
 2223          * . MAC address is 6 bytes,
 2224          * . var w_nextitem holds total number of entries already cached
 2225          */
 2226         for (i = 0; i < sc->an_nextitem; i++) {
 2227                 if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc,  6 )) {
 2228                         /* Match!,
 2229                          * so we already have this entry,
 2230                          * update the data
 2231                          */
 2232                         break;
 2233                 }
 2234         }
 2235 
 2236         /* did we find a matching mac address?
 2237          * if yes, then overwrite a previously existing cache entry
 2238          */
 2239         if (i < sc->an_nextitem )   {
 2240                 cache_slot = i;
 2241         }
 2242         /* else, have a new address entry,so
 2243          * add this new entry,
 2244          * if table full, then we need to replace LRU entry
 2245          */
 2246         else    {
 2247 
 2248                 /* check for space in cache table
 2249                  * note: an_nextitem also holds number of entries
 2250                  * added in the cache table
 2251                  */
 2252                 if ( sc->an_nextitem < MAXANCACHE ) {
 2253                         cache_slot = sc->an_nextitem;
 2254                         sc->an_nextitem++;
 2255                         sc->an_sigitems = sc->an_nextitem;
 2256                 }
 2257                 /* no space found, so simply wrap anth wrap index
 2258                  * and "zap" the next entry
 2259                  */
 2260                 else {
 2261                         if (wrapindex == MAXANCACHE) {
 2262                                 wrapindex = 0;
 2263                         }
 2264                         cache_slot = wrapindex++;
 2265                 }
 2266         }
 2267 
 2268         /* invariant: cache_slot now points at some slot
 2269          * in cache.
 2270          */
 2271         if (cache_slot < 0 || cache_slot >= MAXANCACHE) {
 2272                 log(LOG_ERR, "an_cache_store, bad index: %d of "
 2273                     "[0..%d], gross cache error\n",
 2274                     cache_slot, MAXANCACHE);
 2275                 return;
 2276         }
 2277 
 2278         /*  store items in cache
 2279          *  .ip source address
 2280          *  .mac src
 2281          *  .signal, etc.
 2282          */
 2283         if (type_ipv4) {
 2284                 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
 2285         }
 2286         bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc,  6);
 2287 
 2288         sc->an_sigcache[cache_slot].signal = rx_quality;
 2289 
 2290         return;
 2291 }
 2292 #endif
 2293 
 2294 static int
 2295 an_media_change(ifp)
 2296         struct ifnet            *ifp;
 2297 {
 2298         struct an_softc *sc = ifp->if_softc;
 2299         int otype = sc->an_config.an_opmode;
 2300         int orate = sc->an_tx_rate;
 2301 
 2302         if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
 2303                 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
 2304         else
 2305                 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION;
 2306 
 2307         switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) {
 2308         case IFM_IEEE80211_DS1:
 2309                 sc->an_tx_rate = AN_RATE_1MBPS;
 2310                 break;
 2311         case IFM_IEEE80211_DS2:
 2312                 sc->an_tx_rate = AN_RATE_2MBPS;
 2313                 break;
 2314         case IFM_IEEE80211_DS5:
 2315                 sc->an_tx_rate = AN_RATE_5_5MBPS;
 2316                 break;
 2317         case IFM_IEEE80211_DS11:
 2318                 sc->an_tx_rate = AN_RATE_11MBPS;
 2319                 break;
 2320         case IFM_AUTO:
 2321                 sc->an_tx_rate = 0;
 2322                 break;
 2323         }
 2324 
 2325         if (otype != sc->an_config.an_opmode ||
 2326             orate != sc->an_tx_rate)
 2327                 an_init(sc);
 2328 
 2329         return(0);
 2330 }
 2331 
 2332 static void
 2333 an_media_status(ifp, imr)
 2334         struct ifnet            *ifp;
 2335         struct ifmediareq       *imr;
 2336 {
 2337         struct an_ltv_status    status;
 2338         struct an_softc         *sc = ifp->if_softc;
 2339 
 2340         status.an_len = sizeof(status);
 2341         status.an_type = AN_RID_STATUS;
 2342         if (an_read_record(sc, (struct an_ltv_gen *)&status)) {
 2343                 /* If the status read fails, just lie. */
 2344                 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
 2345                 imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
 2346         }
 2347 
 2348         if (sc->an_tx_rate == 0) {
 2349                 imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
 2350                 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
 2351                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
 2352                 switch (status.an_current_tx_rate) {
 2353                 case AN_RATE_1MBPS:
 2354                         imr->ifm_active |= IFM_IEEE80211_DS1;
 2355                         break;
 2356                 case AN_RATE_2MBPS:
 2357                         imr->ifm_active |= IFM_IEEE80211_DS2;
 2358                         break;
 2359                 case AN_RATE_5_5MBPS:
 2360                         imr->ifm_active |= IFM_IEEE80211_DS5;
 2361                         break;
 2362                 case AN_RATE_11MBPS:
 2363                         imr->ifm_active |= IFM_IEEE80211_DS11;
 2364                         break;
 2365                 }
 2366         } else {
 2367                 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media;
 2368         }
 2369 
 2370         imr->ifm_status = IFM_AVALID;
 2371         if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED)
 2372                 imr->ifm_status |= IFM_ACTIVE;
 2373 }
 2374 
 2375 /********************** Cisco utility support routines *************/
 2376 
 2377 /*
 2378  * ReadRids & WriteRids derived from Cisco driver additions to Ben Reed's
 2379  * Linux driver
 2380  */
 2381 
 2382 static int
 2383 readrids(ifp, l_ioctl)
 2384         struct ifnet   *ifp;
 2385         struct aironet_ioctl *l_ioctl;
 2386 {
 2387         unsigned short  rid;
 2388         struct an_softc *sc;
 2389 
 2390         switch (l_ioctl->command) {
 2391         case AIROGCAP:
 2392                 rid = AN_RID_CAPABILITIES;
 2393                 break;
 2394         case AIROGCFG:
 2395                 rid = AN_RID_GENCONFIG;
 2396                 break;
 2397         case AIROGSLIST:
 2398                 rid = AN_RID_SSIDLIST;
 2399                 break;
 2400         case AIROGVLIST:
 2401                 rid = AN_RID_APLIST;
 2402                 break;
 2403         case AIROGDRVNAM:
 2404                 rid = AN_RID_DRVNAME;
 2405                 break;
 2406         case AIROGEHTENC:
 2407                 rid = AN_RID_ENCAPPROTO;
 2408                 break;
 2409         case AIROGWEPKTMP:
 2410                 rid = AN_RID_WEP_TEMP;
 2411                 break;
 2412         case AIROGWEPKNV:
 2413                 rid = AN_RID_WEP_PERM;
 2414                 break;
 2415         case AIROGSTAT:
 2416                 rid = AN_RID_STATUS;
 2417                 break;
 2418         case AIROGSTATSD32:
 2419                 rid = AN_RID_32BITS_DELTA;
 2420                 break;
 2421         case AIROGSTATSC32:
 2422                 rid = AN_RID_32BITS_CUM;
 2423                 break;
 2424         default:
 2425                 rid = 999;
 2426                 break;
 2427         }
 2428 
 2429         if (rid == 999) /* Is bad command */
 2430                 return -EINVAL;
 2431 
 2432         sc = ifp->if_softc;
 2433         sc->areq.an_len  = AN_MAX_DATALEN;
 2434         sc->areq.an_type = rid;
 2435 
 2436         an_read_record(sc, (struct an_ltv_gen *)&sc->areq);
 2437 
 2438         l_ioctl->len = sc->areq.an_len - 4;     /* just data */
 2439 
 2440         /* the data contains the length at first */
 2441         if (copyout(&(sc->areq.an_len), l_ioctl->data,
 2442                     sizeof(sc->areq.an_len))) {
 2443                 return -EFAULT;
 2444         }
 2445         /* Just copy the data back */
 2446         if (copyout(&(sc->areq.an_val), l_ioctl->data + 2,
 2447                     l_ioctl->len)) {
 2448                 return -EFAULT;
 2449         }
 2450         return 0;
 2451 }
 2452 
 2453 static int
 2454 writerids(ifp, l_ioctl)
 2455         struct ifnet   *ifp;
 2456         struct aironet_ioctl *l_ioctl;
 2457 {
 2458         struct an_softc *sc;
 2459         int             rid, command;
 2460 
 2461         sc = ifp->if_softc;
 2462         rid = 0;
 2463         command = l_ioctl->command;
 2464 
 2465         switch (command) {
 2466         case AIROPSIDS:
 2467                 rid = AN_RID_SSIDLIST;
 2468                 break;
 2469         case AIROPCAP:
 2470                 rid = AN_RID_CAPABILITIES;
 2471                 break;
 2472         case AIROPAPLIST:
 2473                 rid = AN_RID_APLIST;
 2474                 break;
 2475         case AIROPCFG:
 2476                 rid = AN_RID_GENCONFIG;
 2477                 break;
 2478         case AIROPMACON:
 2479                 an_cmd(sc, AN_CMD_ENABLE, 0);
 2480                 return 0;
 2481                 break;
 2482         case AIROPMACOFF:
 2483                 an_cmd(sc, AN_CMD_DISABLE, 0);
 2484                 return 0;
 2485                 break;
 2486         case AIROPSTCLR:
 2487                 /*
 2488                  * This command merely clears the counts does not actually
 2489                  * store any data only reads rid. But as it changes the cards
 2490                  * state, I put it in the writerid routines.
 2491                  */
 2492 
 2493                 rid = AN_RID_32BITS_DELTACLR;
 2494                 sc = ifp->if_softc;
 2495                 sc->areq.an_len = AN_MAX_DATALEN;
 2496                 sc->areq.an_type = rid;
 2497 
 2498                 an_read_record(sc, (struct an_ltv_gen *)&sc->areq);
 2499                 l_ioctl->len = sc->areq.an_len - 4;     /* just data */
 2500 
 2501                 /* the data contains the length at first */
 2502                 if (copyout(&(sc->areq.an_len), l_ioctl->data,
 2503                             sizeof(sc->areq.an_len))) {
 2504                         return -EFAULT;
 2505                 }
 2506                 /* Just copy the data */
 2507                 if (copyout(&(sc->areq.an_val), l_ioctl->data + 2,
 2508                             l_ioctl->len)) {
 2509                         return -EFAULT;
 2510                 }
 2511                 return 0;
 2512                 break;
 2513         case AIROPWEPKEY:
 2514                 rid = AN_RID_WEP_TEMP;
 2515                 break;
 2516         case AIROPWEPKEYNV:
 2517                 rid = AN_RID_WEP_PERM;
 2518                 break;
 2519         case AIROPLEAPUSR:
 2520                 rid = AN_RID_LEAPUSERNAME;
 2521                 break;
 2522         case AIROPLEAPPWD:
 2523                 rid = AN_RID_LEAPPASSWORD;
 2524                 break;
 2525         default:
 2526                 return -EOPNOTSUPP;
 2527         }
 2528 
 2529         if (rid) {
 2530                 if (l_ioctl->len > sizeof(sc->areq.an_val) + 4)
 2531                         return -EINVAL;
 2532                 sc->areq.an_len = l_ioctl->len + 4;     /* add type & length */
 2533                 sc->areq.an_type = rid;
 2534 
 2535                 /* Just copy the data back */
 2536                 copyin((l_ioctl->data) + 2, &sc->areq.an_val,
 2537                        l_ioctl->len);
 2538 
 2539                 an_cmd(sc, AN_CMD_DISABLE, 0);
 2540                 an_write_record(sc, (struct an_ltv_gen *)&sc->areq);
 2541                 an_cmd(sc, AN_CMD_ENABLE, 0);
 2542                 return 0;
 2543         }
 2544         return -EOPNOTSUPP;
 2545 }
 2546 
 2547 /*
 2548  * General Flash utilities derived from Cisco driver additions to Ben Reed's
 2549  * Linux driver
 2550  */
 2551 
 2552 #define FLASH_DELAY(x) tsleep(ifp, PZERO, "flash", ((x) / hz) + 1);
 2553 
 2554 static int
 2555 unstickbusy(ifp)
 2556         struct ifnet   *ifp;
 2557 {
 2558         struct an_softc *sc = ifp->if_softc;
 2559 
 2560         if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
 2561                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
 2562                 return 1;
 2563         }
 2564         return 0;
 2565 }
 2566 
 2567 /*
 2568  * Wait for busy completion from card wait for delay uSec's Return true for
 2569  * success meaning command reg is clear
 2570  */
 2571 
 2572 static int
 2573 WaitBusy(ifp, uSec)
 2574         struct ifnet   *ifp;
 2575         int             uSec;
 2576 {
 2577         int             statword = 0xffff;
 2578         int             delay = 0;
 2579         struct an_softc *sc = ifp->if_softc;
 2580 
 2581         while ((statword & AN_CMD_BUSY) && delay <= (1000 * 100)) {
 2582                 FLASH_DELAY(10);
 2583                 delay += 10;
 2584                 statword = CSR_READ_2(sc, AN_COMMAND);
 2585 
 2586                 if ((AN_CMD_BUSY & statword) && (delay % 200)) {
 2587                         unstickbusy(ifp);
 2588                 }
 2589         }
 2590 
 2591         return 0 == (AN_CMD_BUSY & statword);
 2592 }
 2593 
 2594 /*
 2595  * STEP 1) Disable MAC and do soft reset on card.
 2596  */
 2597 
 2598 static int
 2599 cmdreset(ifp)
 2600         struct ifnet   *ifp;
 2601 {
 2602         int             status;
 2603         struct an_softc *sc = ifp->if_softc;
 2604 
 2605         an_stop(sc);
 2606 
 2607         an_cmd(sc, AN_CMD_DISABLE, 0);
 2608 
 2609         if (!(status = WaitBusy(ifp, 600))) {
 2610                 printf("an%d: Waitbusy hang b4 RESET =%d\n",
 2611                        sc->an_unit, status);
 2612                 return -EBUSY;
 2613         }
 2614         CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_FW_RESTART);
 2615 
 2616         FLASH_DELAY(1000);      /* WAS 600 12/7/00 */
 2617 
 2618 
 2619         if (!(status = WaitBusy(ifp, 100))) {
 2620                 printf("an%d: Waitbusy hang AFTER RESET =%d\n",
 2621                        sc->an_unit, status);
 2622                 return -EBUSY;
 2623         }
 2624         return 0;
 2625 }
 2626 
 2627 /*
 2628  * STEP 2) Put the card in legendary flash mode
 2629  */
 2630 #define FLASH_COMMAND  0x7e7e
 2631 
 2632 static int
 2633 setflashmode(ifp)
 2634         struct ifnet   *ifp;
 2635 {
 2636         int             status;
 2637         struct an_softc *sc = ifp->if_softc;
 2638 
 2639         CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND);
 2640         CSR_WRITE_2(sc, AN_SW1, FLASH_COMMAND);
 2641         CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND);
 2642         CSR_WRITE_2(sc, AN_COMMAND, FLASH_COMMAND);
 2643 
 2644         /*
 2645          * mdelay(500); // 500ms delay
 2646          */
 2647 
 2648         FLASH_DELAY(500);
 2649 
 2650         if (!(status = WaitBusy(ifp, 600))) {
 2651                 printf("Waitbusy hang after setflash mode\n");
 2652                 return -EIO;
 2653         }
 2654         return 0;
 2655 }
 2656 
 2657 /*
 2658  * Get a character from the card matching matchbyte Step 3)
 2659  */
 2660 
 2661 static int
 2662 flashgchar(ifp, matchbyte, dwelltime)
 2663         struct ifnet   *ifp;
 2664         int             matchbyte;
 2665         int             dwelltime;
 2666 {
 2667         int             rchar;
 2668         unsigned char   rbyte = 0;
 2669         int             success = -1;
 2670         struct an_softc *sc = ifp->if_softc;
 2671 
 2672 
 2673         do {
 2674                 rchar = CSR_READ_2(sc, AN_SW1);
 2675 
 2676                 if (dwelltime && !(0x8000 & rchar)) {
 2677                         dwelltime -= 10;
 2678                         FLASH_DELAY(10);
 2679                         continue;
 2680                 }
 2681                 rbyte = 0xff & rchar;
 2682 
 2683                 if ((rbyte == matchbyte) && (0x8000 & rchar)) {
 2684                         CSR_WRITE_2(sc, AN_SW1, 0);
 2685                         success = 1;
 2686                         break;
 2687                 }
 2688                 if (rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
 2689                         break;
 2690                 CSR_WRITE_2(sc, AN_SW1, 0);
 2691 
 2692         } while (dwelltime > 0);
 2693         return success;
 2694 }
 2695 
 2696 /*
 2697  * Put character to SWS0 wait for dwelltime x 50us for  echo .
 2698  */
 2699 
 2700 static int
 2701 flashpchar(ifp, byte, dwelltime)
 2702         struct ifnet   *ifp;
 2703         int             byte;
 2704         int             dwelltime;
 2705 {
 2706         int             echo;
 2707         int             pollbusy, waittime;
 2708         struct an_softc *sc = ifp->if_softc;
 2709 
 2710         byte |= 0x8000;
 2711 
 2712         if (dwelltime == 0)
 2713                 dwelltime = 200;
 2714 
 2715         waittime = dwelltime;
 2716 
 2717         /*
 2718          * Wait for busy bit d15 to go false indicating buffer empty
 2719          */
 2720         do {
 2721                 pollbusy = CSR_READ_2(sc, AN_SW0);
 2722 
 2723                 if (pollbusy & 0x8000) {
 2724                         FLASH_DELAY(50);
 2725                         waittime -= 50;
 2726                         continue;
 2727                 } else
 2728                         break;
 2729         }
 2730         while (waittime >= 0);
 2731 
 2732         /* timeout for busy clear wait */
 2733 
 2734         if (waittime <= 0) {
 2735                 printf("an%d: flash putchar busywait timeout! \n",
 2736                        sc->an_unit);
 2737                 return -1;
 2738         }
 2739         /*
 2740          * Port is clear now write byte and wait for it to echo back
 2741          */
 2742         do {
 2743                 CSR_WRITE_2(sc, AN_SW0, byte);
 2744                 FLASH_DELAY(50);
 2745                 dwelltime -= 50;
 2746                 echo = CSR_READ_2(sc, AN_SW1);
 2747         } while (dwelltime >= 0 && echo != byte);
 2748 
 2749 
 2750         CSR_WRITE_2(sc, AN_SW1, 0);
 2751 
 2752         return echo == byte;
 2753 }
 2754 
 2755 /*
 2756  * Transfer 32k of firmware data from user buffer to our buffer and send to
 2757  * the card
 2758  */
 2759 
 2760 static char     flashbuffer[1024 * 38]; /* RAW Buffer for flash will be
 2761                                          * dynamic next */
 2762 
 2763 static int
 2764 flashputbuf(ifp)
 2765         struct ifnet   *ifp;
 2766 {
 2767         unsigned short *bufp;
 2768         int             nwords;
 2769         struct an_softc *sc = ifp->if_softc;
 2770 
 2771         /* Write stuff */
 2772 
 2773         bufp = (unsigned short *)flashbuffer;
 2774 
 2775         CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100);
 2776         CSR_WRITE_2(sc, AN_AUX_OFFSET, 0);
 2777 
 2778         for (nwords = 0; nwords != 16384; nwords++) {
 2779                 CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff);
 2780         }
 2781 
 2782         CSR_WRITE_2(sc, AN_SW0, 0x8000);
 2783 
 2784         return 0;
 2785 }
 2786 
 2787 /*
 2788  * After flashing restart the card.
 2789  */
 2790 
 2791 static int
 2792 flashrestart(ifp)
 2793         struct ifnet   *ifp;
 2794 {
 2795         int             status = 0;
 2796         struct an_softc *sc = ifp->if_softc;
 2797 
 2798         FLASH_DELAY(1024);              /* Added 12/7/00 */
 2799 
 2800         an_init(sc);
 2801 
 2802         FLASH_DELAY(1024);              /* Added 12/7/00 */
 2803         return status;
 2804 }
 2805 
 2806 /*
 2807  * Entry point for flash ioclt.
 2808  */
 2809 
 2810 static int
 2811 flashcard(ifp, l_ioctl)
 2812         struct ifnet   *ifp;
 2813         struct aironet_ioctl *l_ioctl;
 2814 {
 2815         int             z = 0, status;
 2816         struct an_softc *sc;
 2817 
 2818         sc = ifp->if_softc;
 2819         status = l_ioctl->command;
 2820 
 2821         switch (l_ioctl->command) {
 2822         case AIROFLSHRST:
 2823                 return cmdreset(ifp);
 2824                 break;
 2825         case AIROFLSHSTFL:
 2826                 return setflashmode(ifp);
 2827                 break;
 2828         case AIROFLSHGCHR:      /* Get char from aux */
 2829                 copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
 2830                 z = *(int *)&sc->areq;
 2831                 if ((status = flashgchar(ifp, z, 8000)) == 1)
 2832                         return 0;
 2833                 else
 2834                         return -1;
 2835                 break;
 2836         case AIROFLSHPCHR:      /* Send char to card. */
 2837                 copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
 2838                 z = *(int *)&sc->areq;
 2839                 if ((status = flashpchar(ifp, z, 8000)) == -1)
 2840                         return -EIO;
 2841                 else
 2842                         return 0;
 2843                 break;
 2844         case AIROFLPUTBUF:      /* Send 32k to card */
 2845                 if (l_ioctl->len > sizeof(flashbuffer)) {
 2846                         printf("an%d: Buffer to big, %x %zx\n", sc->an_unit,
 2847                                l_ioctl->len, sizeof(flashbuffer));
 2848                         return -EINVAL;
 2849                 }
 2850                 copyin(l_ioctl->data, &flashbuffer, l_ioctl->len);
 2851 
 2852                 if ((status = flashputbuf(ifp)) != 0)
 2853                         return -EIO;
 2854                 else
 2855                         return 0;
 2856                 break;
 2857         case AIRORESTART:
 2858                 if ((status = flashrestart(ifp)) != 0) {
 2859                         printf("an%d: FLASHRESTART returned %d\n",
 2860                                sc->an_unit, status);
 2861                         return -EIO;
 2862                 } else
 2863                         return 0;
 2864 
 2865                 break;
 2866         default:
 2867                 return -EINVAL;
 2868         }
 2869 
 2870         return -EINVAL;
 2871 }
 2872 

Cache object: 18b8482411b860c472811f512af434cd


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


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.