LCOV - code coverage report
Current view: top level - dev/ic - an.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 871 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: an.c,v 1.73 2018/02/19 08:59:52 mpi Exp $     */
       2             : /*      $NetBSD: an.c,v 1.34 2005/06/20 02:49:18 atatat Exp $   */
       3             : /*
       4             :  * Copyright (c) 1997, 1998, 1999
       5             :  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. All advertising materials mentioning features or use of this software
      16             :  *    must display the following acknowledgement:
      17             :  *      This product includes software developed by Bill Paul.
      18             :  * 4. Neither the name of the author nor the names of any co-contributors
      19             :  *    may be used to endorse or promote products derived from this software
      20             :  *    without specific prior written permission.
      21             :  *
      22             :  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
      23             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25             :  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
      26             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      27             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      28             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      30             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      31             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      32             :  * THE POSSIBILITY OF SUCH DAMAGE.
      33             :  *
      34             :  * $FreeBSD: src/sys/dev/an/if_an.c,v 1.12 2000/11/13 23:04:12 wpaul Exp $
      35             :  */
      36             : /*
      37             :  * Copyright (c) 2004, 2005 David Young.  All rights reserved.
      38             :  * Copyright (c) 2004, 2005 OJC Technologies.  All rights reserved.
      39             :  * Copyright (c) 2004, 2005 Dayton Data Center Services, LLC.  All
      40             :  *     rights reserved.
      41             :  *
      42             :  * Redistribution and use in source and binary forms, with or without
      43             :  * modification, are permitted provided that the following conditions
      44             :  * are met:
      45             :  * 1. Redistributions of source code must retain the above copyright
      46             :  *    notice, this list of conditions and the following disclaimer.
      47             :  * 2. Redistributions in binary form must reproduce the above copyright
      48             :  *    notice, this list of conditions and the following disclaimer in the
      49             :  *    documentation and/or other materials provided with the distribution.
      50             :  * 3. Neither the name of the author nor the names of any co-contributors
      51             :  *    may be used to endorse or promote products derived from this software
      52             :  *    without specific prior written permission.
      53             :  *
      54             :  * THIS SOFTWARE IS PROVIDED BY David Young AND CONTRIBUTORS ``AS IS'' AND
      55             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      56             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      57             :  * ARE DISCLAIMED.  IN NO EVENT SHALL David Young AND CONTRIBUTORS
      58             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      59             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      60             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      61             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      62             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      63             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      64             :  * THE POSSIBILITY OF SUCH DAMAGE.
      65             :  */
      66             : 
      67             : /*
      68             :  * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD.
      69             :  *
      70             :  * Written by Bill Paul <wpaul@ctr.columbia.edu>
      71             :  * Electrical Engineering Department
      72             :  * Columbia University, New York City
      73             :  */
      74             : 
      75             : /*
      76             :  * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego
      77             :  * IETF meeting.
      78             :  */
      79             : 
      80             : #include "bpfilter.h"
      81             : 
      82             : #include <sys/param.h>
      83             : #include <sys/systm.h>
      84             : #include <sys/sockio.h>
      85             : #include <sys/mbuf.h>
      86             : #include <sys/kernel.h>
      87             : #include <sys/ucred.h>
      88             : #include <sys/socket.h>
      89             : #include <sys/timeout.h>
      90             : #include <sys/device.h>
      91             : #include <sys/endian.h>
      92             : #include <sys/tree.h>
      93             : 
      94             : #include <machine/bus.h>
      95             : 
      96             : #include <net/if.h>
      97             : #include <net/if_llc.h>
      98             : #include <net/if_media.h>
      99             : 
     100             : #include <netinet/in.h>
     101             : #include <netinet/if_ether.h>
     102             : 
     103             : #include <net80211/ieee80211_radiotap.h>
     104             : #include <net80211/ieee80211_var.h>
     105             : 
     106             : #if NBPFILTER > 0
     107             : #include <net/bpf.h>
     108             : #endif
     109             : 
     110             : #include <dev/ic/anreg.h>
     111             : #include <dev/ic/anvar.h>
     112             : 
     113             : struct cfdriver an_cd = {
     114             :         NULL, "an", DV_IFNET
     115             : };
     116             : 
     117             : int     an_reset(struct an_softc *);
     118             : void    an_wait(struct an_softc *);
     119             : int     an_init(struct ifnet *);
     120             : void    an_stop(struct ifnet *, int);
     121             : void    an_start(struct ifnet *);
     122             : void    an_watchdog(struct ifnet *);
     123             : int     an_ioctl(struct ifnet *, u_long, caddr_t);
     124             : int     an_media_change(struct ifnet *);
     125             : void    an_media_status(struct ifnet *, struct ifmediareq *);
     126             : 
     127             : int     an_set_nwkey(struct an_softc *, struct ieee80211_nwkey *);
     128             : int     an_set_nwkey_wep(struct an_softc *, struct ieee80211_nwkey *);
     129             : int     an_get_nwkey(struct an_softc *, struct ieee80211_nwkey *);
     130             : int     an_write_wepkey(struct an_softc *, int, struct an_wepkey *,
     131             :                                 int);
     132             : 
     133             : void    an_rxeof(struct an_softc *);
     134             : void    an_txeof(struct an_softc *, u_int16_t);
     135             : void    an_linkstat_intr(struct an_softc *);
     136             : 
     137             : int     an_cmd(struct an_softc *, int, int);
     138             : int     an_seek_bap(struct an_softc *, int, int);
     139             : int     an_read_bap(struct an_softc *, int, int, void *, int, int);
     140             : int     an_write_bap(struct an_softc *, int, int, void *, int);
     141             : int     an_mwrite_bap(struct an_softc *, int, int, struct mbuf *, int);
     142             : int     an_read_rid(struct an_softc *, int, void *, int *);
     143             : int     an_write_rid(struct an_softc *, int, void *, int);
     144             : 
     145             : int     an_alloc_nicmem(struct an_softc *, int, int *);
     146             : 
     147             : int     an_newstate(struct ieee80211com *, enum ieee80211_state, int);
     148             : 
     149             : #ifdef AN_DEBUG
     150             : int an_debug = 0;
     151             : 
     152             : #define DPRINTF(X)      if (an_debug) printf X
     153             : #define DPRINTF2(X)     if (an_debug > 1) printf X
     154             : #else
     155             : #define DPRINTF(X)
     156             : #define DPRINTF2(X)
     157             : #endif
     158             : 
     159             : #if BYTE_ORDER == BIG_ENDIAN
     160             : static __inline void
     161             : an_swap16(u_int16_t *p, int cnt)
     162             : {
     163             :         for (; cnt--; p++)
     164             :                 *p = swap16(*p);
     165             : }
     166             : #define an_switch32(val)        (val >> 16 | (val & 0xFFFF) << 16)
     167             : #else
     168             : #define an_swap16(p, cnt)
     169             : #define an_switch32(val)        val
     170             : #endif
     171             : 
     172             : int
     173           0 : an_attach(struct an_softc *sc)
     174             : {
     175           0 :         struct ieee80211com *ic = &sc->sc_ic;
     176           0 :         struct ifnet *ifp = &ic->ic_if;
     177             :         int i;
     178             :         struct an_rid_wepkey *akey;
     179           0 :         int buflen, kid, rid;
     180             :         int chan, chan_min, chan_max;
     181             : 
     182           0 :         sc->sc_invalid = 0;
     183             : 
     184             :         /* disable interrupts */
     185           0 :         CSR_WRITE_2(sc, AN_INT_EN, 0);
     186           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff);
     187             : 
     188             : //      an_wait(sc);
     189           0 :         if (an_reset(sc) != 0) {
     190           0 :                 sc->sc_invalid = 1;
     191           0 :                 return 1;
     192             :         }
     193             : 
     194             :         /* Load factory config */
     195           0 :         if (an_cmd(sc, AN_CMD_READCFG, 0) != 0) {
     196           0 :                 printf("%s: failed to load config data\n",
     197           0 :                     sc->sc_dev.dv_xname);
     198           0 :                 return (EIO);
     199             :         }
     200             : 
     201             :         /* Read the current configuration */
     202           0 :         buflen = sizeof(sc->sc_config);
     203           0 :         if (an_read_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, &buflen) != 0) {
     204           0 :                 printf("%s: read config failed\n", sc->sc_dev.dv_xname);
     205           0 :                 return(EIO);
     206             :         }
     207             : 
     208             :         an_swap16((u_int16_t *)&sc->sc_config.an_macaddr, 3); 
     209             : 
     210             :         /* Read the card capabilities */
     211           0 :         buflen = sizeof(sc->sc_caps);
     212           0 :         if (an_read_rid(sc, AN_RID_CAPABILITIES, &sc->sc_caps, &buflen) != 0) {
     213           0 :                 printf("%s: read caps failed\n", sc->sc_dev.dv_xname);
     214           0 :                 return(EIO);
     215             :         }
     216             : 
     217             :         an_swap16((u_int16_t *)&sc->sc_caps.an_oemaddr, 3); 
     218             :         an_swap16((u_int16_t *)&sc->sc_caps.an_rates, 4);
     219             : 
     220             :         /* Read WEP settings from persistent memory */
     221           0 :         akey = &sc->sc_buf.sc_wepkey;
     222           0 :         buflen = sizeof(struct an_rid_wepkey);
     223             :         rid = AN_RID_WEP_VOLATILE;      /* first persistent key */
     224           0 :         while (an_read_rid(sc, rid, akey, &buflen) == 0) {
     225             :                 an_swap16((u_int16_t *)&akey->an_mac_addr, 3); 
     226             :                 an_swap16((u_int16_t *)&akey->an_key, 8); 
     227           0 :                 kid = akey->an_key_index;
     228             :                 DPRINTF(("an_attach: wep rid=0x%x len=%d(%d) index=0x%04x "
     229             :                     "mac[0]=%02x keylen=%d\n",
     230             :                     rid, buflen, sizeof(*akey), kid,
     231             :                     akey->an_mac_addr[0], akey->an_key_len));
     232           0 :                 if (kid == 0xffff) {
     233           0 :                         sc->sc_tx_perskey = akey->an_mac_addr[0];
     234           0 :                         sc->sc_tx_key = -1;
     235           0 :                         break;
     236             :                 }
     237           0 :                 if (kid >= IEEE80211_WEP_NKID)
     238             :                         break;
     239           0 :                 sc->sc_perskeylen[kid] = akey->an_key_len;
     240           0 :                 sc->sc_wepkeys[kid].an_wep_keylen = -1;
     241             :                 rid = AN_RID_WEP_PERSISTENT;    /* for next key */
     242           0 :                 buflen = sizeof(struct an_rid_wepkey);
     243             :         }
     244             : 
     245           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_caps.an_oemaddr);
     246           0 :         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
     247             : 
     248           0 :         printf("%s: Firmware %x.%02x.%02x, Radio: ", ifp->if_xname,
     249           0 :             sc->sc_caps.an_fwrev >> 8,
     250           0 :             sc->sc_caps.an_fwrev & 0xff,
     251           0 :             sc->sc_caps.an_fwsubrev);
     252             : 
     253           0 :         if (sc->sc_config.an_radiotype & AN_RADIOTYPE_80211_FH)
     254           0 :                 printf("802.11 FH");
     255           0 :         else if (sc->sc_config.an_radiotype & AN_RADIOTYPE_80211_DS)
     256           0 :                 printf("802.11 DS");
     257           0 :         else if (sc->sc_config.an_radiotype & AN_RADIOTYPE_LM2000_DS)
     258           0 :                 printf("LM2000 DS");
     259             :         else
     260           0 :                 printf("unknown (%x)", sc->sc_config.an_radiotype);
     261             : 
     262           0 :         printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
     263             :         
     264           0 :         ifp->if_softc = sc;
     265           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     266           0 :         ifp->if_ioctl = an_ioctl;
     267           0 :         ifp->if_start = an_start;
     268           0 :         ifp->if_watchdog = an_watchdog;
     269             : 
     270           0 :         ic->ic_phytype = IEEE80211_T_DS;
     271           0 :         ic->ic_opmode = IEEE80211_M_STA;
     272           0 :         ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_PMGT | IEEE80211_C_MONITOR;
     273             : #ifndef IEEE80211_STA_ONLY
     274           0 :         ic->ic_caps |= IEEE80211_C_IBSS;
     275             : #endif
     276           0 :         ic->ic_state = IEEE80211_S_INIT;
     277           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_caps.an_oemaddr);
     278             : 
     279           0 :         switch (sc->sc_caps.an_regdomain) {
     280             :         default:
     281             :         case AN_REGDOMAIN_USA:
     282             :         case AN_REGDOMAIN_CANADA:
     283           0 :                 chan_min = 1; chan_max = 11; break;
     284             :         case AN_REGDOMAIN_EUROPE:
     285             :         case AN_REGDOMAIN_AUSTRALIA:
     286           0 :                 chan_min = 1; chan_max = 13; break;
     287             :         case AN_REGDOMAIN_JAPAN:
     288           0 :                 chan_min = 14; chan_max = 14; break;
     289             :         case AN_REGDOMAIN_SPAIN:
     290           0 :                 chan_min = 10; chan_max = 11; break;
     291             :         case AN_REGDOMAIN_FRANCE:
     292           0 :                 chan_min = 10; chan_max = 13; break;
     293             :         case AN_REGDOMAIN_JAPANWIDE:
     294           0 :                 chan_min = 1; chan_max = 14; break;
     295             :         }
     296             : 
     297           0 :         for (chan = chan_min; chan <= chan_max; chan++) {
     298           0 :                 ic->ic_channels[chan].ic_freq =
     299           0 :                     ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
     300           0 :                 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
     301             :         }
     302           0 :         ic->ic_ibss_chan = &ic->ic_channels[chan_min];
     303             : 
     304             :         /* Find supported rate */
     305           0 :         for (i = 0; i < sizeof(sc->sc_caps.an_rates); i++) {
     306           0 :                 if (sc->sc_caps.an_rates[i] == 0)
     307             :                         continue;
     308           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
     309           0 :                     ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates++] =
     310             :                     sc->sc_caps.an_rates[i];
     311           0 :         }
     312             : 
     313             :         /*
     314             :          * Call MI attach routine.
     315             :          */
     316           0 :         if_attach(ifp);
     317           0 :         ieee80211_ifattach(ifp);
     318             : 
     319           0 :         sc->sc_newstate = ic->ic_newstate;
     320           0 :         ic->ic_newstate = an_newstate;
     321             : 
     322           0 :         ieee80211_media_init(ifp, an_media_change, an_media_status);
     323             : 
     324             : #if NBPFILTER > 0
     325           0 :         bzero(&sc->sc_rxtapu, sizeof(sc->sc_rxtapu));
     326           0 :         sc->sc_rxtap.ar_ihdr.it_len = sizeof(sc->sc_rxtapu);
     327           0 :         sc->sc_rxtap.ar_ihdr.it_present = AN_RX_RADIOTAP_PRESENT;
     328             : 
     329           0 :         bzero(&sc->sc_txtapu, sizeof(sc->sc_txtapu));
     330           0 :         sc->sc_txtap.at_ihdr.it_len = sizeof(sc->sc_txtapu);
     331           0 :         sc->sc_txtap.at_ihdr.it_present = AN_TX_RADIOTAP_PRESENT;
     332             : 
     333           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     334             :             sizeof(struct ieee80211_frame) + 64);
     335             : #endif
     336             : 
     337           0 :         sc->sc_attached = 1;
     338             : 
     339           0 :         return(0);
     340           0 : }
     341             : 
     342             : void
     343           0 : an_rxeof(struct an_softc *sc)
     344             : {
     345           0 :         struct ieee80211com *ic = &sc->sc_ic;
     346           0 :         struct ifnet *ifp = &ic->ic_if;
     347             :         struct ieee80211_frame *wh;
     348           0 :         struct ieee80211_rxinfo rxi;
     349             :         struct ieee80211_node *ni;
     350           0 :         struct an_rxframe frmhdr;
     351             :         struct mbuf *m;
     352             :         u_int16_t status;
     353             :         int fid, gaplen, len, off;
     354             :         uint8_t *gap;
     355             : 
     356           0 :         fid = CSR_READ_2(sc, AN_RX_FID);
     357             : 
     358             :         /* First read in the frame header */
     359           0 :         if (an_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr), sizeof(frmhdr)) != 0) {
     360           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     361           0 :                 ifp->if_ierrors++;
     362             :                 DPRINTF(("an_rxeof: read fid %x failed\n", fid));
     363           0 :                 return;
     364             :         }
     365             :         an_swap16((u_int16_t *)&frmhdr.an_whdr, sizeof(struct ieee80211_frame)/2);
     366             : 
     367           0 :         status = frmhdr.an_rx_status;
     368           0 :         if ((status & AN_STAT_ERRSTAT) != 0 &&
     369           0 :             ic->ic_opmode != IEEE80211_M_MONITOR) {
     370           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     371           0 :                 ifp->if_ierrors++;
     372             :                 DPRINTF(("an_rxeof: fid %x status %x\n", fid, status));
     373           0 :                 return;
     374             :         }
     375             : 
     376             :         /* the payload length field includes a 16-bit "mystery field" */
     377           0 :         len = frmhdr.an_rx_payload_len - sizeof(uint16_t);
     378             :         off = ALIGN(sizeof(struct ieee80211_frame));
     379             : 
     380           0 :         if (off + len > MCLBYTES) {
     381           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
     382           0 :                         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     383           0 :                         ifp->if_ierrors++;
     384             :                         DPRINTF(("an_rxeof: oversized packet %d\n", len));
     385           0 :                         return;
     386             :                 }
     387             :                 len = 0;
     388           0 :         }
     389             : 
     390           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
     391           0 :         if (m == NULL) {
     392           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     393           0 :                 ifp->if_ierrors++;
     394             :                 DPRINTF(("an_rxeof: MGET failed\n"));
     395           0 :                 return;
     396             :         }
     397           0 :         if (off + len + AN_GAPLEN_MAX > MHLEN) {
     398           0 :                 MCLGET(m, M_DONTWAIT);
     399           0 :                 if ((m->m_flags & M_EXT) == 0) {
     400           0 :                         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     401           0 :                         m_freem(m);
     402           0 :                         ifp->if_ierrors++;
     403             :                         DPRINTF(("an_rxeof: MCLGET failed\n"));
     404           0 :                         return;
     405             :                 }
     406             :         }
     407           0 :         m->m_data += off - sizeof(struct ieee80211_frame);
     408             : 
     409           0 :         if (ic->ic_opmode != IEEE80211_M_MONITOR) {
     410           0 :                 gaplen = frmhdr.an_gaplen;
     411           0 :                 if (gaplen > AN_GAPLEN_MAX) {
     412           0 :                         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     413           0 :                         m_freem(m);
     414           0 :                         ifp->if_ierrors++;
     415             :                         DPRINTF(("%s: gap too long\n", __func__));
     416           0 :                         return;
     417             :                 }
     418             :                 /*
     419             :                  * We don't need the 16-bit mystery field (payload length?),
     420             :                  * so read it into the region reserved for the 802.11 header.
     421             :                  *
     422             :                  * When Cisco Aironet 350 cards w/ firmware version 5 or
     423             :                  * greater operate with certain Cisco 350 APs,
     424             :                  * the "gap" is filled with the SNAP header.  Read
     425             :                  * it in after the 802.11 header.
     426             :                  */
     427           0 :                 gap = m->m_data + sizeof(struct ieee80211_frame) -
     428             :                     sizeof(uint16_t);
     429           0 :                 an_read_bap(sc, fid, -1, gap, gaplen + sizeof(u_int16_t),
     430             :                     gaplen + sizeof(u_int16_t));
     431           0 :         } else
     432             :                 gaplen = 0;
     433             : 
     434           0 :         an_read_bap(sc, fid, -1,
     435           0 :             m->m_data + sizeof(struct ieee80211_frame) + gaplen, len, len);
     436             :         an_swap16((u_int16_t *)(m->m_data + sizeof(struct ieee80211_frame) + gaplen), (len+1)/2);
     437           0 :         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + gaplen +
     438           0 :             len;
     439             : 
     440           0 :         memcpy(m->m_data, &frmhdr.an_whdr, sizeof(struct ieee80211_frame));
     441           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX);
     442             : 
     443             : #if NBPFILTER > 0
     444           0 :         if (sc->sc_drvbpf) {
     445           0 :                 struct mbuf mb;
     446           0 :                 struct an_rx_radiotap_header *tap = &sc->sc_rxtap;
     447             : 
     448           0 :                 tap->ar_rate = frmhdr.an_rx_rate;
     449           0 :                 tap->ar_antsignal = frmhdr.an_rx_signal_strength;
     450           0 :                 tap->ar_chan_freq = ic->ic_bss->ni_chan->ic_freq;
     451           0 :                 tap->ar_chan_flags = ic->ic_bss->ni_chan->ic_flags;
     452             : 
     453             : 
     454           0 :                 mb.m_data = (caddr_t)tap;
     455           0 :                 mb.m_len = sizeof(sc->sc_rxtapu);
     456           0 :                 mb.m_next = m;
     457           0 :                 mb.m_nextpkt = NULL;
     458           0 :                 mb.m_type = 0;
     459           0 :                 mb.m_flags = 0;
     460           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
     461           0 :         }
     462             : #endif /* NBPFILTER > 0 */
     463             : 
     464           0 :         wh = mtod(m, struct ieee80211_frame *);
     465           0 :         rxi.rxi_flags = 0;
     466           0 :         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
     467             :                 /*
     468             :                  * WEP is decrypted by hardware. Clear WEP bit
     469             :                  * header for ieee80211_input().
     470             :                  */
     471           0 :                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
     472             : 
     473           0 :                 rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
     474           0 :         }
     475             : 
     476           0 :         ni = ieee80211_find_rxnode(ic, wh);
     477           0 :         rxi.rxi_rssi = frmhdr.an_rx_signal_strength;
     478           0 :         rxi.rxi_tstamp = an_switch32(frmhdr.an_rx_time);
     479           0 :         ieee80211_input(ifp, m, ni, &rxi);
     480           0 :         ieee80211_release_node(ic, ni);
     481           0 : }
     482             : 
     483             : void
     484           0 : an_txeof(struct an_softc *sc, u_int16_t status)
     485             : {
     486           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     487             :         int cur, id;
     488             : 
     489           0 :         sc->sc_tx_timer = 0;
     490           0 :         ifq_clr_oactive(&ifp->if_snd);
     491             : 
     492           0 :         id = CSR_READ_2(sc, AN_TX_CMP_FID);
     493           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, status & (AN_EV_TX | AN_EV_TX_EXC));
     494             : 
     495           0 :         if (status & AN_EV_TX_EXC)
     496           0 :                 ifp->if_oerrors++;
     497             : 
     498           0 :         cur = sc->sc_txcur;
     499           0 :         if (sc->sc_txd[cur].d_fid == id) {
     500           0 :                 sc->sc_txd[cur].d_inuse = 0;
     501             :                 DPRINTF2(("an_txeof: sent %x/%d\n", id, cur));
     502           0 :                 AN_INC(cur, AN_TX_RING_CNT);
     503           0 :                 sc->sc_txcur = cur;
     504           0 :         } else {
     505           0 :                 for (cur = 0; cur < AN_TX_RING_CNT; cur++) {
     506           0 :                         if (id == sc->sc_txd[cur].d_fid) {
     507           0 :                                 sc->sc_txd[cur].d_inuse = 0;
     508           0 :                                 break;
     509             :                         }
     510             :                 }
     511           0 :                 if (ifp->if_flags & IFF_DEBUG)
     512           0 :                         printf("%s: tx mismatch: "
     513             :                             "expected %x(%d), actual %x(%d)\n",
     514           0 :                             sc->sc_dev.dv_xname,
     515           0 :                             sc->sc_txd[sc->sc_txcur].d_fid, sc->sc_txcur,
     516             :                             id, cur);
     517             :         }
     518           0 : }
     519             : 
     520             : int
     521           0 : an_intr(void *arg)
     522             : {
     523           0 :         struct an_softc *sc = arg;
     524           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     525             :         int i;
     526             :         u_int16_t status;
     527             : 
     528           0 :         if (!sc->sc_enabled || sc->sc_invalid ||
     529           0 :             (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
     530           0 :             (ifp->if_flags & IFF_RUNNING) == 0)
     531           0 :                 return 0;
     532             : 
     533           0 :         if ((ifp->if_flags & IFF_UP) == 0) {
     534           0 :                 CSR_WRITE_2(sc, AN_INT_EN, 0);
     535           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, ~0);
     536           0 :                 return 1;
     537             :         }
     538             : 
     539             :         /* maximum 10 loops per interrupt */
     540           0 :         for (i = 0; i < 10; i++) {
     541           0 :                 if (!sc->sc_enabled || sc->sc_invalid)
     542           0 :                         return 1;
     543           0 :                 if (CSR_READ_2(sc, AN_SW0) != AN_MAGIC) {
     544             :                         DPRINTF(("an_intr: magic number changed: %x\n",
     545             :                             CSR_READ_2(sc, AN_SW0)));
     546           0 :                         sc->sc_invalid = 1;
     547           0 :                         return 1;
     548             :                 }
     549           0 :                 status = CSR_READ_2(sc, AN_EVENT_STAT);
     550           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, status & ~(AN_INTRS));
     551           0 :                 if ((status & AN_INTRS) == 0)
     552             :                         break;
     553             : 
     554           0 :                 if (status & AN_EV_RX)
     555           0 :                         an_rxeof(sc);
     556             : 
     557           0 :                 if (status & (AN_EV_TX | AN_EV_TX_EXC))
     558           0 :                         an_txeof(sc, status);
     559             : 
     560           0 :                 if (status & AN_EV_LINKSTAT)
     561           0 :                         an_linkstat_intr(sc);
     562             : 
     563           0 :                 if (ifq_is_oactive(&ifp->if_snd) == 0 &&
     564           0 :                     sc->sc_ic.ic_state == IEEE80211_S_RUN &&
     565           0 :                     !IFQ_IS_EMPTY(&ifp->if_snd))
     566           0 :                         an_start(ifp);
     567             :         }
     568             : 
     569           0 :         return 1;
     570           0 : }
     571             : 
     572             : /* Must be called at proper protection level! */
     573             : int
     574           0 : an_cmd(struct an_softc *sc, int cmd, int val)
     575             : {
     576             :         int i, stat;
     577             : 
     578             :         /* make sure previous command completed */
     579           0 :         if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) {
     580           0 :                 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
     581           0 :                         printf("%s: command 0x%x busy\n", sc->sc_dev.dv_xname,
     582           0 :                             CSR_READ_2(sc, AN_COMMAND));
     583           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
     584           0 :         }
     585             : 
     586           0 :         CSR_WRITE_2(sc, AN_PARAM0, val);
     587           0 :         CSR_WRITE_2(sc, AN_PARAM1, 0);
     588           0 :         CSR_WRITE_2(sc, AN_PARAM2, 0);
     589           0 :         CSR_WRITE_2(sc, AN_COMMAND, cmd);
     590             : 
     591           0 :         if (cmd == AN_CMD_FW_RESTART) {
     592             :                 /* XXX: should sleep here */
     593           0 :                 DELAY(100*1000);
     594           0 :         }
     595             : 
     596           0 :         for (i = 0; i < AN_TIMEOUT; i++) {
     597           0 :                 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
     598             :                         break;
     599           0 :                 DELAY(10);
     600             :         }
     601             : 
     602           0 :         stat = CSR_READ_2(sc, AN_STATUS);
     603             : 
     604             :         /* clear stuck command busy if necessary */
     605           0 :         if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY)
     606           0 :                 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY);
     607             : 
     608             :         /* Ack the command */
     609           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
     610             : 
     611           0 :         if (i == AN_TIMEOUT) {
     612           0 :                 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
     613           0 :                         printf("%s: command 0x%x param 0x%x timeout\n",
     614           0 :                             sc->sc_dev.dv_xname, cmd, val);
     615           0 :                 return ETIMEDOUT;
     616             :         }
     617           0 :         if (stat & AN_STAT_CMD_RESULT) {
     618           0 :                 if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
     619           0 :                         printf("%s: command 0x%x param 0x%x status 0x%x "
     620             :                             "resp 0x%x 0x%x 0x%x\n",
     621           0 :                             sc->sc_dev.dv_xname, cmd, val, stat,
     622           0 :                             CSR_READ_2(sc, AN_RESP0), CSR_READ_2(sc, AN_RESP1),
     623           0 :                             CSR_READ_2(sc, AN_RESP2));
     624           0 :                 return EIO;
     625             :         }
     626             : 
     627           0 :         return 0;
     628           0 : }
     629             : 
     630             : int
     631           0 : an_reset(struct an_softc *sc)
     632             : {
     633             : 
     634             :         DPRINTF(("an_reset\n"));
     635             : 
     636           0 :         if (!sc->sc_enabled)
     637           0 :                 return ENXIO;
     638             : 
     639           0 :         an_cmd(sc, AN_CMD_ENABLE, 0);
     640           0 :         an_cmd(sc, AN_CMD_FW_RESTART, 0);
     641           0 :         an_cmd(sc, AN_CMD_NOOP2, 0);
     642             : 
     643           0 :         if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) {
     644           0 :                 printf("%s: reset failed\n", sc->sc_dev.dv_xname);
     645           0 :                 return ETIMEDOUT;
     646             :         }
     647             : 
     648           0 :         an_cmd(sc, AN_CMD_DISABLE, 0);
     649           0 :         return 0;
     650           0 : }
     651             : 
     652             : void
     653           0 : an_linkstat_intr(struct an_softc *sc)
     654             : {
     655           0 :         struct ieee80211com *ic = &sc->sc_ic;
     656             :         u_int16_t status;
     657             : 
     658           0 :         status = CSR_READ_2(sc, AN_LINKSTAT);
     659           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT);
     660             :         DPRINTF(("an_linkstat_intr: status 0x%x\n", status));
     661             : 
     662           0 :         if (status == AN_LINKSTAT_ASSOCIATED) {
     663           0 :                 if (ic->ic_state != IEEE80211_S_RUN
     664             : #ifndef IEEE80211_STA_ONLY
     665           0 :                     || ic->ic_opmode == IEEE80211_M_IBSS
     666             : #endif
     667             :                     )
     668           0 :                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
     669             :         } else {
     670           0 :                 if (ic->ic_opmode == IEEE80211_M_STA)
     671           0 :                         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
     672             :         }
     673           0 : }
     674             : 
     675             : /*
     676             :  * Wait for firmware come up after power enabled.
     677             :  */
     678             : void
     679           0 : an_wait(struct an_softc *sc)
     680             : {
     681             :         int i;
     682             : 
     683           0 :         CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2);
     684           0 :         for (i = 0; i < 3*hz; i++) {
     685           0 :                 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD)
     686             :                         break;
     687           0 :                 (void)tsleep(sc, PWAIT, "anatch", 1);
     688             :         }
     689           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD);
     690           0 : }
     691             : 
     692             : int
     693           0 : an_read_bap(struct an_softc *sc, int id, int off, void *buf, int len, int blen)
     694             : {
     695             :         int error, cnt, cnt2;
     696             : 
     697           0 :         if (len == 0 || blen == 0)
     698           0 :                 return 0;
     699           0 :         if (off == -1)
     700           0 :                 off = sc->sc_bap_off;
     701           0 :         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
     702           0 :                 if ((error = an_seek_bap(sc, id, off)) != 0)
     703           0 :                         return EIO;
     704             :         }
     705             : 
     706           0 :         cnt = (blen + 1) / 2;
     707           0 :         CSR_READ_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt);
     708           0 :         for (cnt2 = (len + 1) / 2; cnt < cnt2; cnt++)
     709           0 :                 (void) CSR_READ_2(sc, AN_DATA0);
     710           0 :         sc->sc_bap_off += cnt * 2;
     711             : 
     712           0 :         return 0;
     713           0 : }
     714             : 
     715             : int
     716           0 : an_write_bap(struct an_softc *sc, int id, int off, void *buf, int buflen)
     717             : {
     718             :         int error, cnt;
     719             : 
     720           0 :         if (buflen == 0)
     721           0 :                 return 0;
     722           0 :         if (off == -1)
     723           0 :                 off = sc->sc_bap_off;
     724           0 :         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
     725           0 :                 if ((error = an_seek_bap(sc, id, off)) != 0)
     726           0 :                         return EIO;
     727             :         }
     728             : 
     729           0 :         cnt = (buflen + 1) / 2;
     730           0 :         CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt);
     731           0 :         sc->sc_bap_off += cnt * 2;
     732           0 :         return 0;
     733           0 : }
     734             : 
     735             : int
     736           0 : an_seek_bap(struct an_softc *sc, int id, int off)
     737             : {
     738             :         int i, status;
     739             : 
     740           0 :         CSR_WRITE_2(sc, AN_SEL0, id);
     741           0 :         CSR_WRITE_2(sc, AN_OFF0, off);
     742             : 
     743           0 :         for (i = 0; ; i++) {
     744           0 :                 status = CSR_READ_2(sc, AN_OFF0);
     745           0 :                 if ((status & AN_OFF_BUSY) == 0)
     746             :                         break;
     747           0 :                 if (i == AN_TIMEOUT) {
     748           0 :                         printf("%s: timeout in an_seek_bap to 0x%x/0x%x\n",
     749           0 :                             sc->sc_dev.dv_xname, id, off);
     750           0 :                         sc->sc_bap_off = AN_OFF_ERR; /* invalidate */
     751           0 :                         return ETIMEDOUT;
     752             :                 }
     753           0 :                 DELAY(10);
     754             :         }
     755           0 :         if (status & AN_OFF_ERR) {
     756           0 :                 printf("%s: failed in an_seek_bap to 0x%x/0x%x\n",
     757           0 :                     sc->sc_dev.dv_xname, id, off);
     758           0 :                 sc->sc_bap_off = AN_OFF_ERR; /* invalidate */
     759           0 :                 return EIO;
     760             :         }
     761           0 :         sc->sc_bap_id = id;
     762           0 :         sc->sc_bap_off = off;
     763           0 :         return 0;
     764           0 : }
     765             : 
     766             : int
     767           0 : an_mwrite_bap(struct an_softc *sc, int id, int off, struct mbuf *m, int totlen)
     768             : {
     769             :         int error, len, cnt;
     770             : 
     771           0 :         if (off == -1)
     772           0 :                 off = sc->sc_bap_off;
     773           0 :         if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
     774           0 :                 if ((error = an_seek_bap(sc, id, off)) != 0)
     775           0 :                         return EIO;
     776             :         }
     777             : 
     778           0 :         for (len = 0; m != NULL; m = m->m_next) {
     779           0 :                 if (m->m_len == 0)
     780             :                         continue;
     781           0 :                 len = min(m->m_len, totlen);
     782             : 
     783           0 :                 if ((mtod(m, u_long) & 0x1) || (len & 0x1)) {
     784           0 :                         m_copydata(m, 0, totlen, (caddr_t)&sc->sc_buf.sc_txbuf);
     785           0 :                         cnt = (totlen + 1) / 2;
     786             :                         an_swap16((u_int16_t *)&sc->sc_buf.sc_txbuf, cnt); 
     787           0 :                         CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0,
     788             :                             sc->sc_buf.sc_val, cnt);
     789           0 :                         off += cnt * 2;
     790           0 :                         break;
     791             :                 }
     792           0 :                 cnt = len / 2;
     793             :                 an_swap16((u_int16_t *)mtod(m, u_int16_t *), cnt); 
     794           0 :                 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, mtod(m, u_int16_t *),
     795             :                     cnt);
     796           0 :                 off += len;
     797           0 :                 totlen -= len;
     798           0 :         }
     799           0 :         sc->sc_bap_off = off;
     800           0 :         return 0;
     801           0 : }
     802             : 
     803             : int
     804           0 : an_alloc_nicmem(struct an_softc *sc, int len, int *idp)
     805             : {
     806             :         int i;
     807             : 
     808           0 :         if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) {
     809           0 :                 printf("%s: failed to allocate %d bytes on NIC\n",
     810           0 :                     sc->sc_dev.dv_xname, len);
     811           0 :                 return(ENOMEM);
     812             :         }
     813             : 
     814           0 :         for (i = 0; i < AN_TIMEOUT; i++) {
     815           0 :                 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC)
     816             :                         break;
     817           0 :                 if (i == AN_TIMEOUT) {
     818           0 :                         printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
     819           0 :                         return ETIMEDOUT;
     820             :                 }
     821           0 :                 DELAY(10);
     822             :         }
     823             : 
     824           0 :         *idp = CSR_READ_2(sc, AN_ALLOC_FID);
     825           0 :         CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC);
     826           0 :         return 0;
     827           0 : }
     828             : 
     829             : int
     830           0 : an_read_rid(struct an_softc *sc, int rid, void *buf, int *buflenp)
     831             : {
     832             :         int error;
     833           0 :         u_int16_t len;
     834             : 
     835             :         /* Tell the NIC to enter record read mode. */
     836           0 :         error = an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_READ, rid);
     837           0 :         if (error)
     838           0 :                 return error;
     839             : 
     840             :         /* length in byte, including length itself */
     841           0 :         error = an_read_bap(sc, rid, 0, &len, sizeof(len), sizeof(len));
     842           0 :         if (error)
     843           0 :                 return error;
     844             : 
     845           0 :         len -= 2;
     846           0 :         return an_read_bap(sc, rid, sizeof(len), buf, len, *buflenp);
     847           0 : }
     848             : 
     849             : int
     850           0 : an_write_rid(struct an_softc *sc, int rid, void *buf, int buflen)
     851             : {
     852             :         int error;
     853           0 :         u_int16_t len;
     854             : 
     855             :         /* length in byte, including length itself */
     856           0 :         len = buflen + 2;
     857             : 
     858           0 :         error = an_write_bap(sc, rid, 0, &len, sizeof(len));
     859           0 :         if (error)
     860           0 :                 return error;
     861           0 :         error = an_write_bap(sc, rid, sizeof(len), buf, buflen);
     862           0 :         if (error)
     863           0 :                 return error;
     864             : 
     865           0 :         return an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_WRITE, rid);
     866           0 : }
     867             : 
     868             : int
     869           0 : an_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
     870             : {
     871           0 :         struct an_softc *sc = ifp->if_softc;
     872             :         int s, error = 0;
     873             : 
     874           0 :         if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
     875           0 :                 return ENXIO;
     876             : 
     877           0 :         s = splnet();
     878             : 
     879           0 :         switch(command) {
     880             :         case SIOCSIFADDR:
     881           0 :                 ifp->if_flags |= IFF_UP;
     882           0 :                 error = an_init(ifp);
     883           0 :                 break;
     884             :         case SIOCSIFFLAGS:
     885           0 :                 if (ifp->if_flags & IFF_UP) {
     886           0 :                         if (sc->sc_enabled) {
     887             :                                 /*
     888             :                                  * To avoid rescanning another access point,
     889             :                                  * do not call an_init() here.  Instead, only
     890             :                                  * reflect promisc mode settings.
     891             :                                  */
     892           0 :                                 error = an_cmd(sc, AN_CMD_SET_MODE,
     893           0 :                                     (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0);
     894           0 :                         } else
     895           0 :                                 error = an_init(ifp);
     896           0 :                 } else if (sc->sc_enabled)
     897           0 :                         an_stop(ifp, 1);
     898             :                 break;
     899             :         case SIOCADDMULTI:
     900             :         case SIOCDELMULTI:
     901             :                 /* The Aironet has no multicast filter. */
     902             :                 error = 0;
     903           0 :                 break;
     904             :         case SIOCS80211NWKEY:
     905           0 :                 error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data);
     906           0 :                         break;
     907             :         case SIOCG80211NWKEY:
     908           0 :                 error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data);
     909           0 :                 break;
     910             :         default:
     911           0 :                 error = ieee80211_ioctl(ifp, command, data);
     912           0 :                 break;
     913             :         }
     914           0 :         if (error == ENETRESET) {
     915           0 :                 if (sc->sc_enabled)
     916           0 :                         error = an_init(ifp);
     917             :                 else
     918             :                         error = 0;
     919             :         }
     920           0 :         splx(s);
     921           0 :         return(error);
     922           0 : }
     923             : 
     924             : int
     925           0 : an_init(struct ifnet *ifp)
     926             : {
     927           0 :         struct an_softc *sc = ifp->if_softc;
     928           0 :         struct ieee80211com *ic = &sc->sc_ic;
     929           0 :         int i, error, fid;
     930             : 
     931             :         DPRINTF(("an_init: enabled %d\n", sc->sc_enabled));
     932           0 :         if (!sc->sc_enabled) {
     933           0 :                 if (sc->sc_enable)
     934           0 :                         (*sc->sc_enable)(sc);
     935           0 :                 an_wait(sc);
     936           0 :                 sc->sc_enabled = 1;
     937           0 :         } else {
     938           0 :                 an_stop(ifp, 0);
     939           0 :                 if ((error = an_reset(sc)) != 0) {
     940           0 :                         printf("%s: failed to reset\n", ifp->if_xname);
     941           0 :                         an_stop(ifp, 1);
     942           0 :                         return error;
     943             :                 }
     944             :         }
     945           0 :         CSR_WRITE_2(sc, AN_SW0, AN_MAGIC);
     946             : 
     947             :         /* Allocate the TX buffers */
     948           0 :         for (i = 0; i < AN_TX_RING_CNT; i++) {
     949           0 :                 if ((error = an_alloc_nicmem(sc, AN_TX_MAX_LEN, &fid)) != 0) {
     950           0 :                         printf("%s: failed to allocate nic memory\n",
     951           0 :                             ifp->if_xname);
     952           0 :                         an_stop(ifp, 1);
     953           0 :                         return error;
     954             :                 }
     955             :                 DPRINTF2(("an_init: txbuf %d allocated %x\n", i, fid));
     956           0 :                 sc->sc_txd[i].d_fid = fid;
     957           0 :                 sc->sc_txd[i].d_inuse = 0;
     958             :         }
     959           0 :         sc->sc_txcur = sc->sc_txnext = 0;
     960             : 
     961           0 :         IEEE80211_ADDR_COPY(sc->sc_config.an_macaddr, ic->ic_myaddr);
     962             :         an_swap16((u_int16_t *)&sc->sc_config.an_macaddr, 3); 
     963           0 :         sc->sc_config.an_scanmode = AN_SCANMODE_ACTIVE;
     964           0 :         sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN;        /*XXX*/
     965           0 :         if (ic->ic_flags & IEEE80211_F_WEPON) {
     966           0 :                 sc->sc_config.an_authtype |=
     967             :                     AN_AUTHTYPE_PRIVACY_IN_USE;
     968           0 :         }
     969           0 :         sc->sc_config.an_listen_interval = ic->ic_lintval;
     970           0 :         sc->sc_config.an_beacon_period = ic->ic_lintval;
     971           0 :         if (ic->ic_flags & IEEE80211_F_PMGTON)
     972           0 :                 sc->sc_config.an_psave_mode = AN_PSAVE_PSP;
     973             :         else
     974           0 :                 sc->sc_config.an_psave_mode = AN_PSAVE_CAM;
     975           0 :         sc->sc_config.an_ds_channel =
     976           0 :             ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
     977             : 
     978           0 :         switch (ic->ic_opmode) {
     979             :         case IEEE80211_M_STA:
     980           0 :                 sc->sc_config.an_opmode =
     981             :                     AN_OPMODE_INFRASTRUCTURE_STATION;
     982           0 :                 sc->sc_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
     983           0 :                 break;
     984             : #ifndef IEEE80211_STA_ONLY
     985             :         case IEEE80211_M_IBSS:
     986           0 :                 sc->sc_config.an_opmode = AN_OPMODE_IBSS_ADHOC;
     987           0 :                 sc->sc_config.an_rxmode = AN_RXMODE_BC_MC_ADDR;
     988           0 :                 break;
     989             : #endif
     990             :         case IEEE80211_M_MONITOR:
     991           0 :                 sc->sc_config.an_opmode =
     992             :                     AN_OPMODE_INFRASTRUCTURE_STATION;
     993           0 :                 sc->sc_config.an_rxmode =
     994             :                     AN_RXMODE_80211_MONITOR_ANYBSS;
     995           0 :                 sc->sc_config.an_authtype = AN_AUTHTYPE_NONE;
     996           0 :                 if (ic->ic_flags & IEEE80211_F_WEPON)
     997           0 :                         sc->sc_config.an_authtype |=
     998             :                             AN_AUTHTYPE_PRIVACY_IN_USE |
     999             :                             AN_AUTHTYPE_ALLOW_UNENCRYPTED;
    1000             :                 break;
    1001             :         default:
    1002           0 :                 printf("%s: bad opmode %d\n", ifp->if_xname, ic->ic_opmode);
    1003           0 :                 an_stop(ifp, 1);
    1004           0 :                 return EIO;
    1005             :         }
    1006           0 :         sc->sc_config.an_rxmode |= AN_RXMODE_NO_8023_HEADER;
    1007             : 
    1008             :         /* Set the ssid list */
    1009           0 :         memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_ssidlist));
    1010           0 :         sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid_len =
    1011           0 :             ic->ic_des_esslen;
    1012           0 :         if (ic->ic_des_esslen)
    1013           0 :                 memcpy(sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid,
    1014             :                     ic->ic_des_essid, ic->ic_des_esslen);
    1015             :         an_swap16((u_int16_t *)&sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid, 16); 
    1016           0 :         if ((error = an_write_rid(sc, AN_RID_SSIDLIST, &sc->sc_buf,
    1017             :             sizeof(sc->sc_buf.sc_ssidlist)))) {
    1018           0 :                 printf("%s: failed to write ssid list\n", ifp->if_xname);
    1019           0 :                 an_stop(ifp, 1);
    1020           0 :                 return error;
    1021             :         }
    1022             : 
    1023             :         /* Set the AP list */
    1024           0 :         memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_aplist));
    1025           0 :         (void)an_write_rid(sc, AN_RID_APLIST, &sc->sc_buf,
    1026             :             sizeof(sc->sc_buf.sc_aplist));
    1027             : 
    1028             :         /* Set the encapsulation */
    1029           0 :         for (i = 0; i < AN_ENCAP_NENTS; i++) {
    1030           0 :                 sc->sc_buf.sc_encap.an_entry[i].an_ethertype = 0;
    1031           0 :                 sc->sc_buf.sc_encap.an_entry[i].an_action =
    1032             :                     AN_RXENCAP_RFC1024 | AN_TXENCAP_RFC1024;
    1033             :         }
    1034           0 :         (void)an_write_rid(sc, AN_RID_ENCAP, &sc->sc_buf,
    1035             :             sizeof(sc->sc_buf.sc_encap));
    1036             : 
    1037             :         /* Set the WEP Keys */
    1038           0 :         if (ic->ic_flags & IEEE80211_F_WEPON)
    1039           0 :                 an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->sc_wepkeys,
    1040           0 :                     sc->sc_tx_key);
    1041             : 
    1042             :         /* Set the configuration */
    1043           0 :         if ((error = an_write_rid(sc, AN_RID_GENCONFIG, &sc->sc_config,
    1044             :             sizeof(sc->sc_config)))) {
    1045           0 :                 printf("%s: failed to write config\n", ifp->if_xname);
    1046           0 :                 an_stop(ifp, 1);
    1047           0 :                 return error;
    1048             :         }
    1049             : 
    1050             :         /* Enable the MAC */
    1051           0 :         if (an_cmd(sc, AN_CMD_ENABLE, 0)) {
    1052           0 :                 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname);
    1053           0 :                 an_stop(ifp, 1);
    1054           0 :                 return ENXIO;
    1055             :         }
    1056           0 :         if (ifp->if_flags & IFF_PROMISC)
    1057           0 :                 an_cmd(sc, AN_CMD_SET_MODE, 0xffff);
    1058             : 
    1059           0 :         ifp->if_flags |= IFF_RUNNING;
    1060           0 :         ifq_clr_oactive(&ifp->if_snd);
    1061           0 :         ic->ic_state = IEEE80211_S_INIT;
    1062           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    1063           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    1064             : 
    1065             :         /* enable interrupts */
    1066           0 :         CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS);
    1067           0 :         return 0;
    1068           0 : }
    1069             : 
    1070             : void
    1071           0 : an_start(struct ifnet *ifp)
    1072             : {
    1073           0 :         struct an_softc *sc = (struct an_softc *)ifp->if_softc;
    1074           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1075           0 :         struct ieee80211_node *ni;
    1076             :         struct ieee80211_frame *wh;
    1077           0 :         struct an_txframe frmhdr;
    1078             :         struct mbuf *m;
    1079             :         u_int16_t len;
    1080             :         int cur, fid;
    1081             : 
    1082           0 :         if (!sc->sc_enabled || sc->sc_invalid) {
    1083             :                 DPRINTF(("an_start: noop: enabled %d invalid %d\n",
    1084             :                     sc->sc_enabled, sc->sc_invalid));
    1085           0 :                 return;
    1086             :         }
    1087             : 
    1088           0 :         memset(&frmhdr, 0, sizeof(frmhdr));
    1089           0 :         cur = sc->sc_txnext;
    1090           0 :         for (;;) {
    1091           0 :                 if (ic->ic_state != IEEE80211_S_RUN) {
    1092             :                         DPRINTF(("an_start: not running %d\n", ic->ic_state));
    1093             :                         break;
    1094             :                 }
    1095           0 :                 m = ifq_deq_begin(&ifp->if_snd);
    1096           0 :                 if (m == NULL) {
    1097             :                         DPRINTF2(("an_start: no pending mbuf\n"));
    1098             :                         break;
    1099             :                 }
    1100           0 :                 if (sc->sc_txd[cur].d_inuse) {
    1101           0 :                         ifq_deq_rollback(&ifp->if_snd, m);
    1102             :                         DPRINTF2(("an_start: %x/%d busy\n",
    1103             :                             sc->sc_txd[cur].d_fid, cur));
    1104           0 :                         ifq_set_oactive(&ifp->if_snd);
    1105           0 :                         break;
    1106             :                 }
    1107           0 :                 ifq_deq_commit(&ifp->if_snd, m);
    1108             : #if NBPFILTER > 0
    1109           0 :                 if (ifp->if_bpf)
    1110           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    1111             : #endif
    1112           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) {
    1113           0 :                         ifp->if_oerrors++;
    1114           0 :                         continue;
    1115             :                 }
    1116           0 :                 if (ni != NULL)
    1117           0 :                         ieee80211_release_node(ic, ni);
    1118             : #if NBPFILTER > 0
    1119           0 :                 if (ic->ic_rawbpf)
    1120           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    1121             : #endif
    1122             : 
    1123           0 :                 wh = mtod(m, struct ieee80211_frame *);
    1124           0 :                 if (ic->ic_flags & IEEE80211_F_WEPON)
    1125           0 :                         wh->i_fc[1] |= IEEE80211_FC1_WEP;
    1126           0 :                 m_copydata(m, 0, sizeof(struct ieee80211_frame),
    1127           0 :                     (caddr_t)&frmhdr.an_whdr);
    1128             :                 an_swap16((u_int16_t *)&frmhdr.an_whdr, sizeof(struct ieee80211_frame)/2);
    1129             : 
    1130             :                 /* insert payload length in front of llc/snap */
    1131           0 :                 len = htons(m->m_pkthdr.len - sizeof(struct ieee80211_frame));
    1132           0 :                 m_adj(m, sizeof(struct ieee80211_frame) - sizeof(len));
    1133           0 :                 if (mtod(m, u_long) & 0x01)
    1134           0 :                         memcpy(mtod(m, caddr_t), &len, sizeof(len));
    1135             :                 else
    1136           0 :                         *mtod(m, u_int16_t *) = len;
    1137             : 
    1138             :                 /*
    1139             :                  * XXX Aironet firmware apparently convert the packet
    1140             :                  * with longer than 1500 bytes in length into LLC/SNAP.
    1141             :                  * If we have 1500 bytes in ethernet payload, it is
    1142             :                  * 1508 bytes including LLC/SNAP and will be inserted
    1143             :                  * additional LLC/SNAP header with 1501-1508 in its
    1144             :                  * ethertype !!
    1145             :                  * So we skip LLC/SNAP header and force firmware to
    1146             :                  * convert it to LLC/SNAP again.
    1147             :                  */
    1148           0 :                 m_adj(m, sizeof(struct llc));
    1149             : 
    1150           0 :                 frmhdr.an_tx_ctl = AN_TXCTL_80211;
    1151           0 :                 frmhdr.an_tx_payload_len = m->m_pkthdr.len;
    1152           0 :                 frmhdr.an_gaplen = AN_TXGAP_802_11;
    1153             : 
    1154           0 :                 if (ic->ic_fixed_rate != -1)
    1155           0 :                         frmhdr.an_tx_rate =
    1156           0 :                             ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
    1157           0 :                             ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
    1158             :                 else
    1159           0 :                         frmhdr.an_tx_rate = 0;
    1160             : 
    1161           0 :                 if (sizeof(frmhdr) + AN_TXGAP_802_11 + sizeof(len) +
    1162           0 :                     m->m_pkthdr.len > AN_TX_MAX_LEN) {
    1163           0 :                         ifp->if_oerrors++;
    1164           0 :                         m_freem(m);
    1165           0 :                         continue;
    1166             :                 }
    1167             : 
    1168             : #if NBPFILTER > 0
    1169           0 :                 if (sc->sc_drvbpf) {
    1170             :                         struct mbuf mb;
    1171           0 :                         struct an_tx_radiotap_header *tap = &sc->sc_txtap;
    1172             : 
    1173           0 :                         tap->at_rate = 
    1174           0 :                             ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate];
    1175           0 :                         tap->at_chan_freq =
    1176           0 :                             ic->ic_bss->ni_chan->ic_freq;
    1177           0 :                         tap->at_chan_flags =
    1178           0 :                             ic->ic_bss->ni_chan->ic_flags;
    1179             : 
    1180             :                         mb.m_data = (caddr_t)tap;
    1181             :                         mb.m_len = sizeof(sc->sc_txtapu);
    1182             :                         mb.m_next = m;
    1183             :                         mb.m_nextpkt = NULL;
    1184             :                         mb.m_type = 0;
    1185             :                         mb.m_flags = 0;
    1186           0 :                         bpf_mtap(sc->sc_drvbpf, m, BPF_DIRECTION_OUT);
    1187           0 :                 }
    1188             : #endif
    1189             : 
    1190           0 :                 fid = sc->sc_txd[cur].d_fid;
    1191           0 :                 if (an_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
    1192           0 :                         ifp->if_oerrors++;
    1193           0 :                         m_freem(m);
    1194           0 :                         continue;
    1195             :                 }
    1196             :                 /* dummy write to avoid seek. */
    1197           0 :                 an_write_bap(sc, fid, -1, &frmhdr, AN_TXGAP_802_11);
    1198           0 :                 an_mwrite_bap(sc, fid, -1, m, m->m_pkthdr.len);
    1199           0 :                 m_freem(m);
    1200             : 
    1201             :                 DPRINTF2(("an_start: send %d byte via %x/%d\n",
    1202             :                     ntohs(len) + sizeof(struct ieee80211_frame),
    1203             :                     fid, cur));
    1204           0 :                 sc->sc_txd[cur].d_inuse = 1;
    1205           0 :                 if (an_cmd(sc, AN_CMD_TX, fid)) {
    1206           0 :                         printf("%s: xmit failed\n", ifp->if_xname);
    1207           0 :                         sc->sc_txd[cur].d_inuse = 0;
    1208           0 :                         continue;
    1209             :                 }
    1210           0 :                 sc->sc_tx_timer = 5;
    1211           0 :                 ifp->if_timer = 1;
    1212           0 :                 AN_INC(cur, AN_TX_RING_CNT);
    1213           0 :                 sc->sc_txnext = cur;
    1214             :         }
    1215           0 : }
    1216             : 
    1217             : void
    1218           0 : an_stop(struct ifnet *ifp, int disable)
    1219             : {
    1220           0 :         struct an_softc *sc = ifp->if_softc;
    1221             :         int i, s;
    1222             : 
    1223           0 :         if (!sc->sc_enabled)
    1224           0 :                 return;
    1225             : 
    1226             :         DPRINTF(("an_stop: disable %d\n", disable));
    1227             : 
    1228           0 :         s = splnet();
    1229           0 :         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
    1230           0 :         if (!sc->sc_invalid) {
    1231           0 :                 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0);
    1232           0 :                 CSR_WRITE_2(sc, AN_INT_EN, 0);
    1233           0 :                 an_cmd(sc, AN_CMD_DISABLE, 0);
    1234             : 
    1235           0 :                 for (i = 0; i < AN_TX_RING_CNT; i++)
    1236           0 :                         an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->sc_txd[i].d_fid);
    1237             :         }
    1238             : 
    1239           0 :         sc->sc_tx_timer = 0;
    1240           0 :         ifp->if_timer = 0;
    1241           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1242           0 :         ifq_clr_oactive(&ifp->if_snd);
    1243             : 
    1244           0 :         if (disable) {
    1245           0 :                 if (sc->sc_disable)
    1246           0 :                         (*sc->sc_disable)(sc);
    1247           0 :                 sc->sc_enabled = 0;
    1248           0 :         }
    1249           0 :         splx(s);
    1250           0 : }
    1251             : 
    1252             : void
    1253           0 : an_watchdog(struct ifnet *ifp)
    1254             : {
    1255           0 :         struct an_softc *sc = ifp->if_softc;
    1256             : 
    1257           0 :         if (!sc->sc_enabled)
    1258           0 :                 return;
    1259             : 
    1260           0 :         if (sc->sc_tx_timer) {
    1261           0 :                 if (--sc->sc_tx_timer == 0) {
    1262           0 :                         printf("%s: device timeout\n", ifp->if_xname);
    1263           0 :                         ifp->if_oerrors++;
    1264           0 :                         an_init(ifp);
    1265           0 :                         return;
    1266             :                 }
    1267           0 :                 ifp->if_timer = 1;
    1268           0 :         }
    1269           0 :         ieee80211_watchdog(ifp);
    1270           0 : }
    1271             : 
    1272             : /* TBD factor with ieee80211_media_change */
    1273             : int
    1274           0 : an_media_change(struct ifnet *ifp)
    1275             : {
    1276           0 :         struct an_softc *sc = ifp->if_softc;
    1277           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1278             :         struct ifmedia_entry *ime;
    1279             :         enum ieee80211_opmode newmode;
    1280             :         int i, rate, error = 0;
    1281             : 
    1282           0 :         ime = ic->ic_media.ifm_cur;
    1283           0 :         if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
    1284             :                 i = -1;
    1285           0 :         } else {
    1286             :                 struct ieee80211_rateset *rs =
    1287           0 :                     &ic->ic_sup_rates[IEEE80211_MODE_11B];
    1288           0 :                 rate = ieee80211_media2rate(ime->ifm_media);
    1289           0 :                 if (rate == 0)
    1290           0 :                         return EINVAL;
    1291           0 :                 for (i = 0; i < rs->rs_nrates; i++) {
    1292           0 :                         if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
    1293             :                                 break;
    1294             :                 }
    1295           0 :                 if (i == rs->rs_nrates)
    1296           0 :                         return EINVAL;
    1297           0 :         }
    1298           0 :         if (ic->ic_fixed_rate != i) {
    1299           0 :                 ic->ic_fixed_rate = i;
    1300             :                 error = ENETRESET;
    1301           0 :         }
    1302             : 
    1303             : #ifndef IEEE80211_STA_ONLY
    1304           0 :         if (ime->ifm_media & IFM_IEEE80211_ADHOC)
    1305           0 :                 newmode = IEEE80211_M_IBSS;
    1306           0 :         else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
    1307           0 :                 newmode = IEEE80211_M_HOSTAP;
    1308             :         else
    1309             : #endif
    1310           0 :         if (ime->ifm_media & IFM_IEEE80211_MONITOR)
    1311           0 :                 newmode = IEEE80211_M_MONITOR;
    1312             :         else
    1313             :                 newmode = IEEE80211_M_STA;
    1314           0 :         if (ic->ic_opmode != newmode) {
    1315           0 :                 ic->ic_opmode = newmode;
    1316             :                 error = ENETRESET;
    1317           0 :         }
    1318           0 :         if (error == ENETRESET) {
    1319           0 :                 if (sc->sc_enabled)
    1320           0 :                         error = an_init(ifp);
    1321             :                 else
    1322             :                         error = 0;
    1323             :         }
    1324           0 :         ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media);
    1325             : 
    1326           0 :         return error;
    1327           0 : }
    1328             : 
    1329             : void
    1330           0 : an_media_status(struct ifnet *ifp, struct ifmediareq *imr)
    1331             : {
    1332           0 :         struct an_softc *sc = ifp->if_softc;
    1333           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1334           0 :         int rate, buflen;
    1335             : 
    1336           0 :         if (sc->sc_enabled == 0) {
    1337           0 :                 imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
    1338           0 :                 imr->ifm_status = 0;
    1339           0 :                 return;
    1340             :         }
    1341             : 
    1342           0 :         imr->ifm_status = IFM_AVALID;
    1343           0 :         imr->ifm_active = IFM_IEEE80211;
    1344           0 :         if (ic->ic_state == IEEE80211_S_RUN)
    1345           0 :                 imr->ifm_status |= IFM_ACTIVE;
    1346           0 :         buflen = sizeof(sc->sc_buf);
    1347           0 :         if (ic->ic_fixed_rate != -1)
    1348           0 :                 rate = ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[
    1349           0 :                     ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
    1350           0 :         else if (an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen) != 0)
    1351           0 :                 rate = 0;
    1352             :         else
    1353           0 :                 rate = sc->sc_buf.sc_status.an_current_tx_rate;
    1354           0 :         imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
    1355           0 :         switch (ic->ic_opmode) {
    1356             :         case IEEE80211_M_STA:
    1357             :                 break;
    1358             : #ifndef IEEE80211_STA_ONLY
    1359             :         case IEEE80211_M_IBSS:
    1360           0 :                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
    1361           0 :                 break;
    1362             :         case IEEE80211_M_HOSTAP:
    1363           0 :                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
    1364           0 :                 break;
    1365             : #endif
    1366             :         case IEEE80211_M_MONITOR:
    1367           0 :                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
    1368           0 :                 break;
    1369             :         default:
    1370             :                 break;
    1371             :         }
    1372           0 : }
    1373             : 
    1374             : int
    1375           0 : an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
    1376             : {
    1377             :         int error;
    1378           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1379             :         u_int16_t prevauth;
    1380             : 
    1381             :         error = 0;
    1382           0 :         prevauth = sc->sc_config.an_authtype;
    1383             : 
    1384           0 :         switch (nwkey->i_wepon) {
    1385             :         case IEEE80211_NWKEY_OPEN:
    1386           0 :                 sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN;
    1387           0 :                 ic->ic_flags &= ~IEEE80211_F_WEPON;
    1388           0 :                 break;
    1389             : 
    1390             :         case IEEE80211_NWKEY_WEP:
    1391             :         case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST:
    1392           0 :                 error = an_set_nwkey_wep(sc, nwkey);
    1393           0 :                 if (error == 0 || error == ENETRESET) {
    1394           0 :                         sc->sc_config.an_authtype =
    1395             :                             AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE;
    1396           0 :                         ic->ic_flags |= IEEE80211_F_WEPON;
    1397           0 :                 }
    1398             :                 break;
    1399             : 
    1400             :         default:
    1401             :                 error = EINVAL;
    1402           0 :                 break;
    1403             :         }
    1404           0 :         if (error == 0 && prevauth != sc->sc_config.an_authtype)
    1405           0 :                 error = ENETRESET;
    1406           0 :         return error;
    1407             : }
    1408             : 
    1409             : int
    1410           0 : an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
    1411             : {
    1412             :         int i, txkey, anysetkey, needreset, error;
    1413           0 :         struct an_wepkey keys[IEEE80211_WEP_NKID];
    1414             : 
    1415             :         error = 0;
    1416           0 :         memset(keys, 0, sizeof(keys));
    1417             :         anysetkey = needreset = 0;
    1418             : 
    1419             :         /* load argument and sanity check */
    1420           0 :         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1421           0 :                 keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen;
    1422           0 :                 if (keys[i].an_wep_keylen < 0)
    1423             :                         continue;
    1424           0 :                 if (keys[i].an_wep_keylen != 0 &&
    1425           0 :                     keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN)
    1426           0 :                         return EINVAL;
    1427           0 :                 if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key))
    1428           0 :                         return EINVAL;
    1429           0 :                 if ((error = copyin(nwkey->i_key[i].i_keydat,
    1430           0 :                     keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0)
    1431           0 :                         return error;
    1432           0 :                 anysetkey++;
    1433           0 :         }
    1434           0 :         txkey = nwkey->i_defkid - 1;
    1435           0 :         if (txkey >= 0) {
    1436           0 :                 if (txkey >= IEEE80211_WEP_NKID)
    1437           0 :                         return EINVAL;
    1438             :                 /* default key must have a valid value */
    1439           0 :                 if (keys[txkey].an_wep_keylen == 0 ||
    1440           0 :                     (keys[txkey].an_wep_keylen < 0 &&
    1441           0 :                     sc->sc_perskeylen[txkey] == 0))
    1442           0 :                         return EINVAL;
    1443           0 :                 anysetkey++;
    1444           0 :         }
    1445             :         DPRINTF(("an_set_nwkey_wep: %s: %sold(%d:%d,%d,%d,%d) "
    1446             :             "pers(%d:%d,%d,%d,%d) new(%d:%d,%d,%d,%d)\n",
    1447             :             sc->sc_dev.dv_xname,
    1448             :             ((nwkey->i_wepon & IEEE80211_NWKEY_PERSIST) ? "persist: " : ""),
    1449             :             sc->sc_tx_key,
    1450             :             sc->sc_wepkeys[0].an_wep_keylen, sc->sc_wepkeys[1].an_wep_keylen,
    1451             :             sc->sc_wepkeys[2].an_wep_keylen, sc->sc_wepkeys[3].an_wep_keylen,
    1452             :             sc->sc_tx_perskey,
    1453             :             sc->sc_perskeylen[0], sc->sc_perskeylen[1],
    1454             :             sc->sc_perskeylen[2], sc->sc_perskeylen[3],
    1455             :             txkey,
    1456             :             keys[0].an_wep_keylen, keys[1].an_wep_keylen,
    1457             :             keys[2].an_wep_keylen, keys[3].an_wep_keylen));
    1458           0 :         if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) {
    1459             :                 /* set temporary keys */
    1460           0 :                 sc->sc_tx_key = txkey;
    1461           0 :                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1462           0 :                         if (keys[i].an_wep_keylen < 0)
    1463             :                                 continue;
    1464           0 :                         memcpy(&sc->sc_wepkeys[i], &keys[i], sizeof(keys[i]));
    1465           0 :                 }
    1466             :         } else {
    1467             :                 /* set persist keys */
    1468           0 :                 if (anysetkey) {
    1469             :                         /* prepare to write nvram */
    1470           0 :                         if (!sc->sc_enabled) {
    1471           0 :                                 if (sc->sc_enable)
    1472           0 :                                         (*sc->sc_enable)(sc);
    1473           0 :                                 an_wait(sc);
    1474           0 :                                 sc->sc_enabled = 1;
    1475           0 :                                 error = an_write_wepkey(sc,
    1476             :                                     AN_RID_WEP_PERSISTENT, keys, txkey);
    1477           0 :                                 if (sc->sc_disable)
    1478           0 :                                         (*sc->sc_disable)(sc);
    1479           0 :                                 sc->sc_enabled = 0;
    1480           0 :                         } else {
    1481           0 :                                 an_cmd(sc, AN_CMD_DISABLE, 0);
    1482           0 :                                 error = an_write_wepkey(sc,
    1483             :                                     AN_RID_WEP_PERSISTENT, keys, txkey);
    1484           0 :                                 an_cmd(sc, AN_CMD_ENABLE, 0);
    1485             :                         }
    1486           0 :                         if (error)
    1487           0 :                                 return error;
    1488             :                 }
    1489           0 :                 if (txkey >= 0)
    1490           0 :                         sc->sc_tx_perskey = txkey;
    1491           0 :                 if (sc->sc_tx_key >= 0) {
    1492           0 :                         sc->sc_tx_key = -1;
    1493             :                         needreset++;
    1494           0 :                 }
    1495           0 :                 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1496           0 :                         if (sc->sc_wepkeys[i].an_wep_keylen >= 0) {
    1497           0 :                                 memset(&sc->sc_wepkeys[i].an_wep_key, 0,
    1498             :                                     sizeof(sc->sc_wepkeys[i].an_wep_key));
    1499           0 :                                 sc->sc_wepkeys[i].an_wep_keylen = -1;
    1500           0 :                                 needreset++;
    1501           0 :                         }
    1502           0 :                         if (keys[i].an_wep_keylen >= 0)
    1503           0 :                                 sc->sc_perskeylen[i] = keys[i].an_wep_keylen;
    1504             :                 }
    1505             :         }
    1506           0 :         if (needreset) {
    1507             :                 /* firmware restart to reload persistent key */
    1508           0 :                 an_reset(sc);
    1509           0 :         }
    1510           0 :         if (anysetkey || needreset)
    1511           0 :                 error = ENETRESET;
    1512           0 :         return error;
    1513           0 : }
    1514             : 
    1515             : int
    1516           0 : an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey)
    1517             : {
    1518             :         int i, error;
    1519             : 
    1520             :         error = 0;
    1521           0 :         if (sc->sc_config.an_authtype & AN_AUTHTYPE_LEAP)
    1522           0 :                 nwkey->i_wepon = IEEE80211_NWKEY_EAP;
    1523           0 :         else if (sc->sc_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE)
    1524           0 :                 nwkey->i_wepon = IEEE80211_NWKEY_WEP;
    1525             :         else
    1526           0 :                 nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
    1527           0 :         if (sc->sc_tx_key == -1)
    1528           0 :                 nwkey->i_defkid = sc->sc_tx_perskey + 1;
    1529             :         else
    1530           0 :                 nwkey->i_defkid = sc->sc_tx_key + 1;
    1531           0 :         if (nwkey->i_key[0].i_keydat == NULL)
    1532           0 :                 return 0;
    1533           0 :         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1534           0 :                 if (nwkey->i_key[i].i_keydat == NULL)
    1535             :                         continue;
    1536             :                 /* do not show any keys to non-root user */
    1537           0 :                 if ((error = suser(curproc)) != 0)
    1538             :                         break;
    1539           0 :                 nwkey->i_key[i].i_keylen = sc->sc_wepkeys[i].an_wep_keylen;
    1540           0 :                 if (nwkey->i_key[i].i_keylen < 0) {
    1541           0 :                         if (sc->sc_perskeylen[i] == 0)
    1542           0 :                                 nwkey->i_key[i].i_keylen = 0;
    1543             :                         continue;
    1544             :                 }
    1545           0 :                 if ((error = copyout(sc->sc_wepkeys[i].an_wep_key,
    1546           0 :                     nwkey->i_key[i].i_keydat,
    1547           0 :                     sc->sc_wepkeys[i].an_wep_keylen)) != 0)
    1548             :                         break;
    1549             :         }
    1550           0 :         return error;
    1551           0 : }
    1552             : 
    1553             : int
    1554           0 : an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid)
    1555             : {
    1556             :         int i, error;
    1557             :         struct an_rid_wepkey *akey;
    1558             : 
    1559             :         error = 0;
    1560           0 :         akey = &sc->sc_buf.sc_wepkey;
    1561           0 :         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1562           0 :                 memset(akey, 0, sizeof(struct an_rid_wepkey));
    1563           0 :                 if (keys[i].an_wep_keylen < 0 ||
    1564           0 :                     keys[i].an_wep_keylen > sizeof(akey->an_key))
    1565             :                         continue;
    1566           0 :                 akey->an_key_len = keys[i].an_wep_keylen;
    1567           0 :                 akey->an_key_index = i;
    1568           0 :                 akey->an_mac_addr[0] = 1;    /* default mac */
    1569             :                 an_swap16((u_int16_t *)&akey->an_mac_addr, 3); 
    1570           0 :                 memcpy(akey->an_key, keys[i].an_wep_key, keys[i].an_wep_keylen);
    1571             :                 an_swap16((u_int16_t *)&akey->an_key, 8); 
    1572           0 :                 if ((error = an_write_rid(sc, type, akey, sizeof(*akey))) != 0)
    1573           0 :                         return error;
    1574             :         }
    1575           0 :         if (kid >= 0) {
    1576           0 :                 memset(akey, 0, sizeof(struct an_rid_wepkey));
    1577           0 :                 akey->an_key_index = 0xffff;
    1578           0 :                 akey->an_mac_addr[0] = kid;
    1579             :                 an_swap16((u_int16_t *)&akey->an_mac_addr, 3); 
    1580           0 :                 akey->an_key_len = 0;
    1581           0 :                 memset(akey->an_key, 0, sizeof(akey->an_key));
    1582           0 :                 error = an_write_rid(sc, type, akey, sizeof(*akey));
    1583           0 :         }
    1584           0 :         return error;
    1585           0 : }
    1586             : 
    1587             : int
    1588           0 : an_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
    1589             : {
    1590           0 :         struct an_softc *sc = ic->ic_softc;
    1591           0 :         struct ieee80211_node *ni = ic->ic_bss;
    1592             :         enum ieee80211_state ostate;
    1593           0 :         int buflen;
    1594             : 
    1595           0 :         ostate = ic->ic_state;
    1596             :         DPRINTF(("an_newstate: %s -> %s\n", ieee80211_state_name[ostate],
    1597             :             ieee80211_state_name[nstate]));
    1598             : 
    1599           0 :         switch (nstate) {
    1600             :         case IEEE80211_S_INIT:
    1601           0 :                 ic->ic_flags &= ~IEEE80211_F_IBSSON;
    1602           0 :                 return (*sc->sc_newstate)(ic, nstate, arg);
    1603             : 
    1604             :         case IEEE80211_S_RUN:
    1605           0 :                 buflen = sizeof(sc->sc_buf);
    1606           0 :                 an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen);
    1607             :                 an_swap16((u_int16_t *)&sc->sc_buf.sc_status.an_cur_bssid, 3); 
    1608             :                 an_swap16((u_int16_t *)&sc->sc_buf.sc_status.an_ssid, 16); 
    1609           0 :                 IEEE80211_ADDR_COPY(ni->ni_bssid,
    1610             :                     sc->sc_buf.sc_status.an_cur_bssid);
    1611           0 :                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
    1612           0 :                 ni->ni_chan = &ic->ic_channels[
    1613           0 :                     sc->sc_buf.sc_status.an_cur_channel];
    1614           0 :                 ni->ni_esslen = sc->sc_buf.sc_status.an_ssidlen;
    1615           0 :                 if (ni->ni_esslen > IEEE80211_NWID_LEN)
    1616           0 :                         ni->ni_esslen = IEEE80211_NWID_LEN;  /*XXX*/
    1617           0 :                 memcpy(ni->ni_essid, sc->sc_buf.sc_status.an_ssid,
    1618             :                     ni->ni_esslen);
    1619           0 :                 ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];      /*XXX*/
    1620           0 :                 if (ic->ic_if.if_flags & IFF_DEBUG) {
    1621           0 :                         printf("%s: ", sc->sc_dev.dv_xname);
    1622           0 :                         if (ic->ic_opmode == IEEE80211_M_STA)
    1623           0 :                                 printf("associated ");
    1624             :                         else
    1625           0 :                                 printf("synchronized ");
    1626           0 :                         printf("with %s ssid ", ether_sprintf(ni->ni_bssid));
    1627           0 :                         ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
    1628           0 :                         printf(" channel %u start %uMb\n",
    1629           0 :                             sc->sc_buf.sc_status.an_cur_channel,
    1630           0 :                             sc->sc_buf.sc_status.an_current_tx_rate/2);
    1631           0 :                 }
    1632             :                 break;
    1633             : 
    1634             :         default:
    1635             :                 break;
    1636             :         }
    1637           0 :         ic->ic_state = nstate;
    1638             :         /* skip standard ieee80211 handling */
    1639           0 :         return 0;
    1640           0 : }
    1641             : 
    1642             : int
    1643           0 : an_detach(struct an_softc *sc)
    1644             : {
    1645           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    1646             :         int s;
    1647             : 
    1648           0 :         if (!sc->sc_attached)
    1649           0 :                 return 0;
    1650             : 
    1651           0 :         s = splnet();
    1652           0 :         sc->sc_invalid = 1;
    1653           0 :         an_stop(ifp, 1);
    1654           0 :         ifmedia_delete_instance(&sc->sc_ic.ic_media, IFM_INST_ANY);
    1655           0 :         ieee80211_ifdetach(ifp);
    1656           0 :         if_detach(ifp);
    1657           0 :         splx(s);
    1658           0 :         return 0;
    1659           0 : }
    1660             : 

Generated by: LCOV version 1.13