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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/awi.c

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

    1 /*      $NetBSD: awi.c,v 1.62 2004/01/16 14:13:15 onoe Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Bill Sommerfeld
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 /*
   39  * Driver for AMD 802.11 firmware.
   40  * Uses am79c930 chip driver to talk to firmware running on the am79c930.
   41  *
   42  * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
   43  */
   44 
   45 /*
   46  * todo:
   47  *      - flush tx queue on resynch.
   48  *      - clear oactive on "down".
   49  *      - rewrite copy-into-mbuf code
   50  *      - mgmt state machine gets stuck retransmitting assoc requests.
   51  *      - multicast filter.
   52  *      - fix device reset so it's more likely to work
   53  *      - show status goo through ifmedia.
   54  *
   55  * more todo:
   56  *      - deal with more 802.11 frames.
   57  *              - send reassoc request
   58  *              - deal with reassoc response
   59  *              - send/deal with disassociation
   60  *      - deal with "full" access points (no room for me).
   61  *      - power save mode
   62  *
   63  * later:
   64  *      - SSID preferences
   65  *      - need ioctls for poking at the MIBs
   66  *      - implement ad-hoc mode (including bss creation).
   67  *      - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
   68  *              (focus on inf. mode since that will be needed for ietf)
   69  *      - deal with DH vs. FH versions of the card
   70  *      - deal with faster cards (2mb/s)
   71  *      - ?WEP goo (mmm, rc4) (it looks not particularly useful).
   72  *      - ifmedia revision.
   73  *      - common 802.11 mibish things.
   74  *      - common 802.11 media layer.
   75  */
   76 
   77 /*
   78  * Driver for AMD 802.11 PCnetMobile firmware.
   79  * Uses am79c930 chip driver to talk to firmware running on the am79c930.
   80  *
   81  * The initial version of the driver was written by
   82  * Bill Sommerfeld <sommerfeld@NetBSD.org>.
   83  * Then the driver module completely rewritten to support cards with DS phy
   84  * and to support adhoc mode by Atsushi Onoe <onoe@NetBSD.org>
   85  */
   86 
   87 #include <sys/cdefs.h>
   88 #ifdef __NetBSD__
   89 __KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.62 2004/01/16 14:13:15 onoe Exp $");
   90 #endif
   91 #ifdef __FreeBSD__
   92 __FBSDID("$FreeBSD: src/sys/dev/awi/awi.c,v 1.30 2004/01/15 13:30:06 onoe Exp $");
   93 #endif
   94 
   95 #include "opt_inet.h"
   96 #ifdef __NetBSD__
   97 #include "bpfilter.h"
   98 #endif
   99 #ifdef __FreeBSD__
  100 #define NBPFILTER       1
  101 #endif
  102 
  103 #include <sys/param.h>
  104 #include <sys/systm.h>
  105 #include <sys/kernel.h>
  106 #include <sys/mbuf.h>
  107 #include <sys/malloc.h>
  108 #include <sys/proc.h>
  109 #include <sys/socket.h>
  110 #include <sys/sockio.h>
  111 #include <sys/errno.h>
  112 #include <sys/endian.h>
  113 #ifdef __FreeBSD__
  114 #include <sys/bus.h>
  115 #endif
  116 #ifdef __NetBSD__
  117 #include <sys/device.h>
  118 #endif
  119 
  120 #include <net/if.h>
  121 #include <net/if_dl.h>
  122 #ifdef __NetBSD__
  123 #include <net/if_ether.h>
  124 #endif
  125 #ifdef __FreeBSD__
  126 #include <net/ethernet.h>
  127 #include <net/if_arp.h>
  128 #endif
  129 #include <net/if_media.h>
  130 #include <net/if_llc.h>
  131 
  132 #include <net80211/ieee80211_var.h>
  133 #ifdef __NetBSD__
  134 #include <net80211/ieee80211_compat.h>
  135 #endif
  136 
  137 #if NBPFILTER > 0
  138 #include <net/bpf.h>
  139 #endif
  140 
  141 #include <machine/cpu.h>
  142 #include <machine/bus.h>
  143 
  144 #ifdef __NetBSD__
  145 #include <dev/ic/am79c930reg.h>
  146 #include <dev/ic/am79c930var.h>
  147 #include <dev/ic/awireg.h>
  148 #include <dev/ic/awivar.h>
  149 #endif
  150 #ifdef __FreeBSD__
  151 #include <dev/awi/am79c930reg.h>
  152 #include <dev/awi/am79c930var.h>
  153 #include <dev/awi/awireg.h>
  154 #include <dev/awi/awivar.h>
  155 #endif
  156 
  157 #ifdef __FreeBSD__
  158 static void awi_init0(void *);
  159 #endif
  160 static int  awi_init(struct ifnet *);
  161 static void awi_stop(struct ifnet *, int);
  162 static void awi_start(struct ifnet *);
  163 static void awi_watchdog(struct ifnet *);
  164 static int  awi_ioctl(struct ifnet *, u_long, caddr_t);
  165 static int  awi_media_change(struct ifnet *);
  166 static void awi_media_status(struct ifnet *, struct ifmediareq *);
  167 static int  awi_mode_init(struct awi_softc *);
  168 static void awi_rx_int(struct awi_softc *);
  169 static void awi_tx_int(struct awi_softc *);
  170 static struct mbuf *awi_devget(struct awi_softc *, u_int32_t, u_int16_t);
  171 static int  awi_hw_init(struct awi_softc *);
  172 static int  awi_init_mibs(struct awi_softc *);
  173 static int  awi_mib(struct awi_softc *, u_int8_t, u_int8_t, int);
  174 static int  awi_cmd(struct awi_softc *, u_int8_t, int);
  175 static int  awi_cmd_wait(struct awi_softc *);
  176 static void awi_cmd_done(struct awi_softc *);
  177 static int  awi_next_txd(struct awi_softc *, int, u_int32_t *, u_int32_t *);
  178 static int  awi_lock(struct awi_softc *);
  179 static void awi_unlock(struct awi_softc *);
  180 static int  awi_intr_lock(struct awi_softc *);
  181 static void awi_intr_unlock(struct awi_softc *);
  182 static int  awi_newstate(struct ieee80211com *, enum ieee80211_state, int);
  183 static void awi_recv_mgmt(struct ieee80211com *, struct mbuf *,
  184     struct ieee80211_node *, int, int, u_int32_t);
  185 static int  awi_send_mgmt(struct ieee80211com *, struct ieee80211_node *, int,
  186     int);
  187 static struct mbuf *awi_ether_encap(struct awi_softc *, struct mbuf *);
  188 static struct mbuf *awi_ether_modcap(struct awi_softc *, struct mbuf *);
  189 
  190 /* unaligned little endian access */     
  191 #define LE_READ_2(p)                                                    \
  192         ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8))
  193 #define LE_READ_4(p)                                                    \
  194         ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8) |  \
  195          (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))
  196 #define LE_WRITE_2(p, v)                                                \
  197         ((((u_int8_t *)(p))[0] = (((u_int32_t)(v)      ) & 0xff)),      \
  198          (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >>  8) & 0xff)))
  199 #define LE_WRITE_4(p, v)                                                \
  200         ((((u_int8_t *)(p))[0] = (((u_int32_t)(v)      ) & 0xff)),      \
  201          (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >>  8) & 0xff)),      \
  202          (((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)),      \
  203          (((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff)))
  204 
  205 struct awi_chanset awi_chanset[] = {
  206     /* PHY type        domain            min max def */
  207     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_JP,  6, 17,  6 },
  208     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_ES,  0, 26,  1 },
  209     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_FR,  0, 32,  1 },
  210     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_US,  0, 77,  1 },
  211     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_CA,  0, 77,  1 },
  212     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_EU,  0, 77,  1 },
  213     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_JP, 14, 14, 14 },
  214     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_ES, 10, 11, 10 },
  215     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_FR, 10, 13, 10 },
  216     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_US,  1, 11,  3 },
  217     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_CA,  1, 11,  3 },
  218     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_EU,  1, 13,  3 },
  219     { 0, 0 }
  220 };
  221 
  222 #ifdef __FreeBSD__
  223 devclass_t awi_devclass;
  224 
  225 #if __FreeBSD_version < 500043
  226 static char *ether_sprintf(u_int8_t *);
  227 
  228 static char *
  229 ether_sprintf(u_int8_t *enaddr)
  230 {
  231         static char strbuf[18];
  232 
  233         sprintf(strbuf, "%6D", enaddr, ":");
  234         return strbuf;
  235 }
  236 #endif
  237 
  238 #define IFQ_PURGE(ifq)          IF_DRAIN(ifq)
  239 #define IF_POLL(ifq, m)         ((m) = (ifq)->ifq_head)
  240 #define IFQ_POLL(ifq, m)        IF_POLL((ifq), (m))
  241 #define IFQ_DEQUEUE(ifq, m)     IF_DEQUEUE((ifq), (m))
  242 
  243 #endif
  244 
  245 #ifdef AWI_DEBUG
  246 int awi_debug = 0;
  247 
  248 #define DPRINTF(X)      if (awi_debug) printf X
  249 #define DPRINTF2(X)     if (awi_debug > 1) printf X
  250 #else
  251 #define DPRINTF(X)
  252 #define DPRINTF2(X)
  253 #endif
  254 
  255 int
  256 awi_attach(struct awi_softc *sc)
  257 {
  258         struct ieee80211com *ic = &sc->sc_ic;
  259         struct ifnet *ifp = &ic->ic_if;
  260         int s, i, error, nrate;
  261         int mword;
  262         enum ieee80211_phymode mode;
  263 
  264         s = splnet();
  265         sc->sc_busy = 1;
  266         sc->sc_attached = 0;
  267         sc->sc_substate = AWI_ST_NONE;
  268         if ((error = awi_hw_init(sc)) != 0) {
  269                 sc->sc_invalid = 1;
  270                 splx(s);
  271                 return error;
  272         }
  273         error = awi_init_mibs(sc);
  274         if (error != 0) {
  275                 sc->sc_invalid = 1;
  276                 splx(s);
  277                 return error;
  278         }
  279         ifp->if_softc = sc;
  280         ifp->if_flags =
  281 #ifdef IFF_NOTRAILERS
  282             IFF_NOTRAILERS |
  283 #endif
  284             IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
  285         ifp->if_ioctl = awi_ioctl;
  286         ifp->if_start = awi_start;
  287         ifp->if_watchdog = awi_watchdog;
  288 #ifdef __NetBSD__
  289         ifp->if_init = awi_init;
  290         ifp->if_stop = awi_stop;
  291         IFQ_SET_READY(&ifp->if_snd);
  292         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
  293 #endif
  294 #ifdef __FreeBSD__
  295         ifp->if_init = awi_init0;
  296         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  297         if_initname(ifp, device_get_name(sc->sc_dev),
  298             device_get_unit(sc->sc_dev));
  299 #endif
  300 
  301         ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP;
  302         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
  303                 ic->ic_phytype = IEEE80211_T_FH;
  304                 mode = IEEE80211_MODE_FH;
  305         } else {
  306                 ic->ic_phytype = IEEE80211_T_DS;
  307                 ic->ic_caps |= IEEE80211_C_AHDEMO;
  308                 mode = IEEE80211_MODE_11B;
  309         }
  310         ic->ic_opmode = IEEE80211_M_STA;
  311         nrate = sc->sc_mib_phy.aSuprt_Data_Rates[1];
  312         memcpy(ic->ic_sup_rates[mode].rs_rates,
  313             sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate);
  314         ic->ic_sup_rates[mode].rs_nrates = nrate;
  315         IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address);
  316 
  317         printf("%s: IEEE802.11 %s (firmware %s)\n", ifp->if_xname,
  318             (ic->ic_phytype == IEEE80211_T_FH) ? "FH" : "DS", sc->sc_banner);
  319         printf("%s: 802.11 address: %s\n", ifp->if_xname,
  320             ether_sprintf(ic->ic_myaddr));
  321 
  322 #ifdef __NetBSD__
  323         if_attach(ifp);
  324 #endif
  325         ieee80211_ifattach(ifp);
  326 
  327         sc->sc_newstate = ic->ic_newstate;
  328         ic->ic_newstate = awi_newstate;
  329 
  330         sc->sc_recv_mgmt = ic->ic_recv_mgmt;
  331         ic->ic_recv_mgmt = awi_recv_mgmt;
  332 
  333         sc->sc_send_mgmt = ic->ic_send_mgmt;
  334         ic->ic_send_mgmt = awi_send_mgmt;
  335 
  336         ieee80211_media_init(ifp, awi_media_change, awi_media_status);
  337 
  338         /* Melco compatibility mode. */
  339 #define ADD(s, o)       ifmedia_add(&ic->ic_media, \
  340         IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
  341         ADD(IFM_AUTO, IFM_FLAG0);
  342 
  343         for (i = 0; i < nrate; i++) {
  344                 mword = ieee80211_rate2media(ic,
  345                     ic->ic_sup_rates[mode].rs_rates[i], mode);
  346                 if (mword == 0)
  347                         continue;
  348                 ADD(mword, IFM_FLAG0);
  349         }
  350 #undef  ADD
  351 
  352 #ifdef __NetBSD__
  353         if ((sc->sc_sdhook = shutdownhook_establish(awi_shutdown, sc)) == NULL)
  354                 printf("%s: WARNING: unable to establish shutdown hook\n",
  355                     ifp->if_xname);
  356         if ((sc->sc_powerhook = powerhook_establish(awi_power, sc)) == NULL)
  357                 printf("%s: WARNING: unable to establish power hook\n",
  358                     ifp->if_xname);
  359 #endif
  360         sc->sc_attached = 1;
  361         splx(s);
  362 
  363         /* ready to accept ioctl */
  364         awi_unlock(sc);
  365 
  366         return 0;
  367 }
  368 
  369 int
  370 awi_detach(struct awi_softc *sc)
  371 {
  372         struct ifnet *ifp = &sc->sc_ic.ic_if;
  373         int s;
  374 
  375         if (!sc->sc_attached)
  376                 return 0;
  377 
  378         s = splnet();
  379         sc->sc_invalid = 1;
  380         awi_stop(ifp, 1);
  381 
  382         while (sc->sc_sleep_cnt > 0) {
  383                 wakeup(sc);
  384                 (void)tsleep(sc, PWAIT, "awidet", 1);
  385         }
  386         sc->sc_attached = 0;
  387         ieee80211_ifdetach(ifp);
  388 #ifdef __NetBSD__
  389         if_detach(ifp);
  390         shutdownhook_disestablish(sc->sc_sdhook);
  391         powerhook_disestablish(sc->sc_powerhook);
  392 #endif
  393         splx(s);
  394         return 0;
  395 }
  396 
  397 #ifdef __NetBSD__
  398 int
  399 awi_activate(struct device *self, enum devact act)
  400 {
  401         struct awi_softc *sc = (struct awi_softc *)self;
  402         struct ifnet *ifp = &sc->sc_ic.ic_if;
  403         int s, error = 0;
  404 
  405         s = splnet();
  406         switch (act) {
  407         case DVACT_ACTIVATE:
  408                 error = EOPNOTSUPP;
  409                 break;
  410         case DVACT_DEACTIVATE:
  411                 sc->sc_invalid = 1;
  412                 if_deactivate(ifp);
  413                 break;
  414         }
  415         splx(s);
  416         return error;
  417 }
  418 
  419 void
  420 awi_power(int why, void *arg)
  421 {
  422         struct awi_softc *sc = arg;
  423         struct ifnet *ifp = &sc->sc_ic.ic_if;
  424         int s;
  425         int ocansleep;
  426 
  427         DPRINTF(("awi_power: %d\n", why));
  428         s = splnet();
  429         ocansleep = sc->sc_cansleep;
  430         sc->sc_cansleep = 0;
  431         switch (why) {
  432         case PWR_SUSPEND:
  433         case PWR_STANDBY:
  434                 awi_stop(ifp, 1);
  435                 break;
  436         case PWR_RESUME:
  437                 if (ifp->if_flags & IFF_UP) {
  438                         awi_init(ifp);
  439                         (void)awi_intr(sc);     /* make sure */
  440                 }
  441                 break;
  442         case PWR_SOFTSUSPEND:
  443         case PWR_SOFTSTANDBY:
  444         case PWR_SOFTRESUME:
  445                 break;
  446         }
  447         sc->sc_cansleep = ocansleep;
  448         splx(s);
  449 }
  450 #endif /* __NetBSD__ */
  451 
  452 void
  453 awi_shutdown(void *arg)
  454 {
  455         struct awi_softc *sc = arg;
  456         struct ifnet *ifp = &sc->sc_ic.ic_if;
  457 
  458         if (sc->sc_attached)
  459                 awi_stop(ifp, 1);
  460 }
  461 
  462 int
  463 awi_intr(void *arg)
  464 {
  465         struct awi_softc *sc = arg;
  466         u_int16_t status;
  467         int handled = 0, ocansleep;
  468 #ifdef AWI_DEBUG
  469         static const char *intname[] = {
  470             "CMD", "RX", "TX", "SCAN_CMPLT",
  471             "CFP_START", "DTIM", "CFP_ENDING", "GROGGY",
  472             "TXDATA", "TXBCAST", "TXPS", "TXCF",
  473             "TXMGT", "#13", "RXDATA", "RXMGT"
  474         };
  475 #endif
  476 
  477         if (!sc->sc_enabled || !sc->sc_enab_intr || sc->sc_invalid) {
  478                 DPRINTF(("awi_intr: stray interrupt: "
  479                     "enabled %d enab_intr %d invalid %d\n",
  480                     sc->sc_enabled, sc->sc_enab_intr, sc->sc_invalid));
  481                 return 0;
  482         }
  483 
  484         am79c930_gcr_setbits(&sc->sc_chip,
  485             AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT);
  486         awi_write_1(sc, AWI_DIS_PWRDN, 1);
  487         ocansleep = sc->sc_cansleep;
  488         sc->sc_cansleep = 0;
  489 
  490         for (;;) {
  491                 if (awi_intr_lock(sc) != 0)
  492                         break;
  493                 status = awi_read_1(sc, AWI_INTSTAT);
  494                 awi_write_1(sc, AWI_INTSTAT, 0);
  495                 awi_write_1(sc, AWI_INTSTAT, 0);
  496                 status |= awi_read_1(sc, AWI_INTSTAT2) << 8;
  497                 awi_write_1(sc, AWI_INTSTAT2, 0);
  498                 DELAY(10);
  499                 awi_intr_unlock(sc);
  500                 if (!sc->sc_cmd_inprog)
  501                         status &= ~AWI_INT_CMD; /* make sure */
  502                 if (status == 0)
  503                         break;
  504 #ifdef AWI_DEBUG
  505                 if (awi_debug > 1) {
  506                         int i;
  507 
  508                         printf("awi_intr: status 0x%04x", status);
  509                         for (i = 0; i < sizeof(intname)/sizeof(intname[0]);
  510                             i++) {
  511                                 if (status & (1 << i))
  512                                         printf(" %s", intname[i]);
  513                         }
  514                         printf("\n");
  515                 }
  516 #endif
  517                 handled = 1;
  518                 if (status & AWI_INT_RX)
  519                         awi_rx_int(sc);
  520                 if (status & AWI_INT_TX)
  521                         awi_tx_int(sc);
  522                 if (status & AWI_INT_CMD)
  523                         awi_cmd_done(sc);
  524                 if (status & AWI_INT_SCAN_CMPLT) {
  525                         if (sc->sc_ic.ic_state == IEEE80211_S_SCAN &&
  526                             sc->sc_substate == AWI_ST_NONE)
  527                                 ieee80211_next_scan(&sc->sc_ic.ic_if);
  528                 }
  529         }
  530         sc->sc_cansleep = ocansleep;
  531         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
  532         awi_write_1(sc, AWI_DIS_PWRDN, 0);
  533         return handled;
  534 }
  535 
  536 #ifdef __FreeBSD__
  537 static void
  538 awi_init0(void *arg)
  539 {
  540         struct awi_softc *sc = arg;
  541 
  542         (void)awi_init(&sc->sc_ic.ic_if);
  543 }
  544 #endif
  545 
  546 static int
  547 awi_init(struct ifnet *ifp)
  548 {
  549         struct awi_softc *sc = ifp->if_softc;
  550         struct ieee80211com *ic = &sc->sc_ic;
  551         struct ieee80211_node *ni = ic->ic_bss;
  552         struct ieee80211_rateset *rs;
  553         int error, rate, i;
  554 
  555         DPRINTF(("awi_init: enabled=%d\n", sc->sc_enabled));
  556         if (sc->sc_enabled) {
  557                 awi_stop(ifp, 0);
  558         } else {
  559                 if (sc->sc_enable)
  560                         (*sc->sc_enable)(sc);
  561                 sc->sc_enabled = 1;
  562                 if ((error = awi_hw_init(sc)) != 0) {
  563                         if (sc->sc_disable)
  564                                 (*sc->sc_disable)(sc);
  565                         sc->sc_enabled = 0;
  566                         return error;
  567                 }
  568         }
  569         ic->ic_state = IEEE80211_S_INIT;
  570 
  571         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  572         switch (ic->ic_opmode) {
  573         case IEEE80211_M_STA:
  574                 sc->sc_mib_local.Network_Mode = 1;
  575                 sc->sc_mib_local.Acting_as_AP = 0;
  576                 break;
  577         case IEEE80211_M_IBSS:
  578                 ic->ic_flags |= IEEE80211_F_IBSSON;
  579                 /* FALLTHRU */
  580         case IEEE80211_M_AHDEMO:
  581                 sc->sc_mib_local.Network_Mode = 0;
  582                 sc->sc_mib_local.Acting_as_AP = 0;
  583                 break;
  584         case IEEE80211_M_HOSTAP:
  585                 sc->sc_mib_local.Network_Mode = 1;
  586                 sc->sc_mib_local.Acting_as_AP = 1;
  587                 break;
  588         case IEEE80211_M_MONITOR:
  589                 return ENODEV;
  590         }
  591 #if 0
  592         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
  593 #endif
  594         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
  595         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
  596         sc->sc_mib_mac.aDesired_ESS_ID[1] = ic->ic_des_esslen;
  597         memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], ic->ic_des_essid,
  598             ic->ic_des_esslen);
  599 
  600         /* configure basic rate */
  601         if (ic->ic_phytype == IEEE80211_T_FH)
  602                 rs = &ic->ic_sup_rates[IEEE80211_MODE_FH];
  603         else
  604                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
  605         if (ic->ic_fixed_rate != -1) {
  606                 rate = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
  607         } else {
  608                 rate = 0;
  609                 for (i = 0; i < rs->rs_nrates; i++) {
  610                         if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
  611                             rate < (rs->rs_rates[i] & IEEE80211_RATE_VAL))
  612                                 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
  613                 }
  614         }
  615         rate *= 5;
  616         LE_WRITE_2(&sc->sc_mib_mac.aStation_Basic_Rate, rate);
  617 
  618         if ((error = awi_mode_init(sc)) != 0) {
  619                 DPRINTF(("awi_init: awi_mode_init failed %d\n", error));
  620                 awi_stop(ifp, 1);
  621                 return error;
  622         }
  623 
  624         /* start transmitter */
  625         sc->sc_txdone = sc->sc_txnext = sc->sc_txbase;
  626         awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0);
  627         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0);
  628         awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0);
  629         awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0);
  630         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0);
  631         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0);
  632         awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0);
  633         awi_write_4(sc, AWI_CA_TX_DATA, sc->sc_txbase);
  634         awi_write_4(sc, AWI_CA_TX_MGT, 0);
  635         awi_write_4(sc, AWI_CA_TX_BCAST, 0);
  636         awi_write_4(sc, AWI_CA_TX_PS, 0);
  637         awi_write_4(sc, AWI_CA_TX_CF, 0);
  638         if ((error = awi_cmd(sc, AWI_CMD_INIT_TX, AWI_WAIT)) != 0) {
  639                 DPRINTF(("awi_init: failed to start transmitter: %d\n", error));
  640                 awi_stop(ifp, 1);
  641                 return error;
  642         }
  643 
  644         /* start receiver */
  645         if ((error = awi_cmd(sc, AWI_CMD_INIT_RX, AWI_WAIT)) != 0) {
  646                 DPRINTF(("awi_init: failed to start receiver: %d\n", error));
  647                 awi_stop(ifp, 1);
  648                 return error;
  649         }
  650         sc->sc_rxdoff = awi_read_4(sc, AWI_CA_IRX_DATA_DESC);
  651         sc->sc_rxmoff = awi_read_4(sc, AWI_CA_IRX_PS_DESC);
  652 
  653         ifp->if_flags |= IFF_RUNNING;
  654         ifp->if_flags &= ~IFF_OACTIVE;
  655         ic->ic_state = IEEE80211_S_INIT;
  656 
  657         if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
  658             ic->ic_opmode == IEEE80211_M_HOSTAP) {
  659                 ni->ni_chan = ic->ic_ibss_chan;
  660                 ni->ni_intval = ic->ic_lintval;
  661                 ni->ni_rssi = 0;
  662                 ni->ni_rstamp = 0;
  663                 memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
  664                 ni->ni_rates =
  665                     ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
  666                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
  667                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  668                         IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
  669                         ni->ni_esslen = ic->ic_des_esslen;
  670                         memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
  671                         ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
  672                         if (ic->ic_phytype == IEEE80211_T_FH) {
  673                                 ni->ni_fhdwell = 200;   /* XXX */
  674                                 ni->ni_fhindex = 1;
  675                         }
  676                 } else {
  677                         ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
  678                         memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
  679                         ni->ni_esslen = 0;
  680                 }
  681                 if (ic->ic_flags & IEEE80211_F_WEPON)
  682                         ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
  683                 if (ic->ic_opmode != IEEE80211_M_AHDEMO)
  684                         ic->ic_flags |= IEEE80211_F_SIBSS;
  685                 ic->ic_state = IEEE80211_S_SCAN;        /*XXX*/
  686                 sc->sc_substate = AWI_ST_NONE;
  687                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  688         } else {
  689                 /* XXX check sc->sc_cur_chan */
  690                 ni->ni_chan = &ic->ic_channels[sc->sc_cur_chan];
  691                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  692         }
  693         return 0;
  694 }
  695 
  696 static void
  697 awi_stop(struct ifnet *ifp, int disable)
  698 {
  699         struct awi_softc *sc = ifp->if_softc;
  700 
  701         if (!sc->sc_enabled)
  702                 return;
  703 
  704         DPRINTF(("awi_stop(%d)\n", disable));
  705 
  706         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
  707 
  708         if (!sc->sc_invalid) {
  709                 if (sc->sc_cmd_inprog)
  710                         (void)awi_cmd_wait(sc);
  711                 (void)awi_cmd(sc, AWI_CMD_KILL_RX, AWI_WAIT);
  712                 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX;
  713                 awi_write_1(sc, AWI_CA_FTX_DATA, 1);
  714                 awi_write_1(sc, AWI_CA_FTX_MGT, 0);
  715                 awi_write_1(sc, AWI_CA_FTX_BCAST, 0);
  716                 awi_write_1(sc, AWI_CA_FTX_PS, 0);
  717                 awi_write_1(sc, AWI_CA_FTX_CF, 0);
  718                 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX, AWI_WAIT);
  719         }
  720         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
  721         ifp->if_timer = 0;
  722         sc->sc_tx_timer = sc->sc_rx_timer = 0;
  723         if (sc->sc_rxpend != NULL) {
  724                 m_freem(sc->sc_rxpend);
  725                 sc->sc_rxpend = NULL;
  726         }
  727         IFQ_PURGE(&ifp->if_snd);
  728 
  729         if (disable) {
  730                 if (!sc->sc_invalid)
  731                         am79c930_gcr_setbits(&sc->sc_chip,
  732                             AM79C930_GCR_CORESET);
  733                 if (sc->sc_disable)
  734                         (*sc->sc_disable)(sc);
  735                 sc->sc_enabled = 0;
  736         }
  737 }
  738 
  739 static void
  740 awi_start(struct ifnet *ifp)
  741 {
  742         struct awi_softc *sc = ifp->if_softc;
  743         struct ieee80211com *ic = &sc->sc_ic;
  744         struct ieee80211_node *ni;
  745         struct ieee80211_frame *wh;
  746         struct mbuf *m, *m0;
  747         int len, dowep;
  748         u_int32_t txd, frame, ntxd;
  749         u_int8_t rate;
  750 
  751         if (!sc->sc_enabled || sc->sc_invalid)
  752                 return;
  753 
  754         for (;;) {
  755                 txd = sc->sc_txnext;
  756                 IF_POLL(&ic->ic_mgtq, m0);
  757                 dowep = 0;
  758                 if (m0 != NULL) {
  759                         len = m0->m_pkthdr.len;
  760                         if (awi_next_txd(sc, len, &frame, &ntxd)) {
  761                                 ifp->if_flags |= IFF_OACTIVE;
  762                                 break;
  763                         }
  764                         IF_DEQUEUE(&ic->ic_mgtq, m0);
  765                 } else {
  766                         if (ic->ic_state != IEEE80211_S_RUN)
  767                                 break;
  768                         IFQ_POLL(&ifp->if_snd, m0);
  769                         if (m0 == NULL)
  770                                 break;
  771                         /*
  772                          * Need to calculate the real length to determine
  773                          * if the transmit buffer has a room for the packet.
  774                          */
  775                         len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
  776                         if (!(ifp->if_flags & IFF_LINK0) && !sc->sc_adhoc_ap)
  777                                 len += sizeof(struct llc) -
  778                                     sizeof(struct ether_header);
  779                         if (ic->ic_flags & IEEE80211_F_WEPON) {
  780                                 dowep = 1;
  781                                 len += IEEE80211_WEP_IVLEN +
  782                                     IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
  783                         }
  784                         if (awi_next_txd(sc, len, &frame, &ntxd)) {
  785                                 ifp->if_flags |= IFF_OACTIVE;
  786                                 break;
  787                         }
  788                         IFQ_DEQUEUE(&ifp->if_snd, m0);
  789                         ifp->if_opackets++;
  790 #if NBPFILTER > 0
  791                         if (ifp->if_bpf)
  792                                 bpf_mtap(ifp->if_bpf, m0);
  793 #endif
  794                         if ((ifp->if_flags & IFF_LINK0) || sc->sc_adhoc_ap)
  795                                 m0 = awi_ether_encap(sc, m0);
  796                         else
  797                                 m0 = ieee80211_encap(ifp, m0, &ni);
  798                         if (m0 == NULL) {
  799                                 ifp->if_oerrors++;
  800                                 continue;
  801                         }
  802                         if (ni != NULL && ni != ic->ic_bss)
  803                                 ieee80211_free_node(ic, ni);
  804                         wh = mtod(m0, struct ieee80211_frame *);
  805                         if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  806                             (ic->ic_opmode == IEEE80211_M_HOSTAP ||
  807                              ic->ic_opmode == IEEE80211_M_IBSS) &&
  808                             sc->sc_adhoc_ap == 0 &&
  809                             (ifp->if_flags & IFF_LINK0) == 0 &&
  810                             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
  811                             IEEE80211_FC0_TYPE_DATA && ni == NULL) {
  812                                 m_freem(m0);
  813                                 ifp->if_oerrors++;
  814                                 continue;
  815                         }
  816                 }
  817 #if NBPFILTER > 0
  818                 if (ic->ic_rawbpf)
  819                         bpf_mtap(ic->ic_rawbpf, m0);
  820 #endif
  821                 if (dowep) {
  822                         if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
  823                                 ifp->if_oerrors++;
  824                                 continue;
  825                         }
  826                 }
  827 #ifdef DIAGNOSTIC
  828                 if (m0->m_pkthdr.len != len) {
  829                         printf("%s: length %d should be %d\n",
  830                             ic->ic_if.if_xname, m0->m_pkthdr.len, len);
  831                         m_freem(m0);
  832                         ifp->if_oerrors++;
  833                         continue;
  834                 }
  835 #endif
  836 
  837                 if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2))
  838                         ieee80211_dump_pkt(m0->m_data, m0->m_len,
  839                             ic->ic_bss->ni_rates.
  840                                 rs_rates[ic->ic_bss->ni_txrate] &
  841                             IEEE80211_RATE_VAL, -1);
  842 
  843                 for (m = m0, len = 0; m != NULL; m = m->m_next) {
  844                         awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *),
  845                             m->m_len);
  846                         len += m->m_len;
  847                 }
  848                 m_freem(m0);
  849                 rate = (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
  850                     IEEE80211_RATE_VAL) * 5;
  851                 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0);
  852                 awi_write_4(sc, txd + AWI_TXD_START, frame);
  853                 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd);
  854                 awi_write_4(sc, txd + AWI_TXD_LENGTH, len);
  855                 awi_write_1(sc, txd + AWI_TXD_RATE, rate);
  856                 awi_write_4(sc, txd + AWI_TXD_NDA, 0);
  857                 awi_write_4(sc, txd + AWI_TXD_NRA, 0);
  858                 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN);
  859                 sc->sc_txnext = ntxd;
  860 
  861                 sc->sc_tx_timer = 5;
  862                 ifp->if_timer = 1;
  863         }
  864 }
  865 
  866 static void
  867 awi_watchdog(struct ifnet *ifp)
  868 {
  869         struct awi_softc *sc = ifp->if_softc;
  870         u_int32_t prevdone;
  871         int ocansleep;
  872 
  873         ifp->if_timer = 0;
  874         if (!sc->sc_enabled || sc->sc_invalid)
  875                 return;
  876 
  877         ocansleep = sc->sc_cansleep;
  878         sc->sc_cansleep = 0;
  879         if (sc->sc_tx_timer) {
  880                 if (--sc->sc_tx_timer == 0) {
  881                         printf("%s: device timeout\n", ifp->if_xname);
  882                         prevdone = sc->sc_txdone;
  883                         awi_tx_int(sc);
  884                         if (sc->sc_txdone == prevdone) {
  885                                 ifp->if_oerrors++;
  886                                 awi_init(ifp);
  887                                 goto out;
  888                         }
  889                 }
  890                 ifp->if_timer = 1;
  891         }
  892         if (sc->sc_rx_timer) {
  893                 if (--sc->sc_rx_timer == 0) {
  894                         if (sc->sc_ic.ic_state == IEEE80211_S_RUN) {
  895                                 ieee80211_new_state(&sc->sc_ic,
  896                                     IEEE80211_S_SCAN, -1);
  897                                 goto out;
  898                         }
  899                 } else
  900                         ifp->if_timer = 1;
  901         }
  902         /* TODO: rate control */
  903         ieee80211_watchdog(ifp);
  904   out:
  905         sc->sc_cansleep = ocansleep;
  906 }
  907 
  908 static int
  909 awi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  910 {
  911         struct awi_softc *sc = ifp->if_softc;
  912         struct ifreq *ifr = (struct ifreq *)data;
  913         int s, error;
  914 
  915         s = splnet();
  916         /* serialize ioctl, since we may sleep */
  917         if ((error = awi_lock(sc)) != 0)
  918                 goto cantlock;
  919 
  920         switch (cmd) {
  921         case SIOCSIFFLAGS:
  922                 if (ifp->if_flags & IFF_UP) {
  923                         if (sc->sc_enabled) {
  924                                 /*
  925                                  * To avoid rescanning another access point,
  926                                  * do not call awi_init() here.  Instead,
  927                                  * only reflect promisc mode settings.
  928                                  */
  929                                 error = awi_mode_init(sc);
  930                         } else
  931                                 error = awi_init(ifp);
  932                 } else if (sc->sc_enabled)
  933                         awi_stop(ifp, 1);
  934                 break;
  935         case SIOCSIFMEDIA:
  936         case SIOCGIFMEDIA:
  937                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ic.ic_media, cmd);
  938                 break;
  939         case SIOCADDMULTI:
  940         case SIOCDELMULTI:
  941 #ifdef __FreeBSD__
  942                 error = ENETRESET;      /* XXX */
  943 #else
  944                 error = (cmd == SIOCADDMULTI) ?
  945                     ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
  946                     ether_delmulti(ifr, &sc->sc_ic.ic_ec);
  947 #endif
  948                 if (error == ENETRESET) {
  949                         /* do not rescan */
  950                         if (sc->sc_enabled)
  951                                 error = awi_mode_init(sc);
  952                         else
  953                                 error = 0;
  954                 }
  955                 break;
  956         default:
  957                 error = ieee80211_ioctl(ifp, cmd, data);
  958                 if (error == ENETRESET) {
  959                         if (sc->sc_enabled)
  960                                 error = awi_init(ifp);
  961                         else
  962                                 error = 0;
  963                 }
  964                 break;
  965         }
  966         awi_unlock(sc);
  967   cantlock:
  968         splx(s);
  969         return error;
  970 }
  971 
  972 /*
  973  * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
  974  *
  975  * TBD factor with ieee80211_media_change
  976  */
  977 static int
  978 awi_media_change(struct ifnet *ifp)
  979 {
  980         struct awi_softc *sc = ifp->if_softc;
  981         struct ieee80211com *ic = &sc->sc_ic;
  982         struct ifmedia_entry *ime;
  983         enum ieee80211_opmode newmode;
  984         int i, rate, newadhoc_ap, error = 0;
  985 
  986         ime = ic->ic_media.ifm_cur;
  987         if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
  988                 i = -1;
  989         } else {
  990                 struct ieee80211_rateset *rs =
  991                     &ic->ic_sup_rates[(ic->ic_phytype == IEEE80211_T_FH)
  992                     ? IEEE80211_MODE_FH : IEEE80211_MODE_11B];
  993                 rate = ieee80211_media2rate(ime->ifm_media);
  994                 if (rate == 0)
  995                         return EINVAL;
  996                 for (i = 0; i < rs->rs_nrates; i++) {
  997                         if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
  998                                 break;
  999                 }
 1000                 if (i == rs->rs_nrates)
 1001                         return EINVAL;
 1002         }
 1003         if (ic->ic_fixed_rate != i) {
 1004                 ic->ic_fixed_rate = i;
 1005                 error = ENETRESET;
 1006         }
 1007 
 1008         /*
 1009          * combination of mediaopt
 1010          *
 1011          * hostap adhoc flag0   opmode  adhoc_ap        comment
 1012          *   +      -     -     HOSTAP      0           HostAP
 1013          *   -      +     -     IBSS        0           IBSS
 1014          *   -      +     +     AHDEMO      0           WaveLAN adhoc
 1015          *   -      -     +     IBSS        1           Melco old Sta
 1016          *                                                      also LINK0
 1017          *   -      -     -     STA         0           Infra Station
 1018          */
 1019         newadhoc_ap = 0;
 1020         if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
 1021                 newmode = IEEE80211_M_HOSTAP;
 1022         else if (ime->ifm_media & IFM_IEEE80211_ADHOC) {
 1023                 if (ic->ic_phytype == IEEE80211_T_DS &&
 1024                     (ime->ifm_media & IFM_FLAG0))
 1025                         newmode = IEEE80211_M_AHDEMO;
 1026                 else
 1027                         newmode = IEEE80211_M_IBSS;
 1028         } else if (ime->ifm_media & IFM_FLAG0) {
 1029                 newmode = IEEE80211_M_IBSS;
 1030                 newadhoc_ap = 1;
 1031         } else
 1032                 newmode = IEEE80211_M_STA;
 1033         if (ic->ic_opmode != newmode || sc->sc_adhoc_ap != newadhoc_ap) {
 1034                 ic->ic_opmode = newmode;
 1035                 sc->sc_adhoc_ap = newadhoc_ap;
 1036                 error = ENETRESET;
 1037         }
 1038 
 1039         if (error == ENETRESET) {
 1040                 if (sc->sc_enabled)
 1041                         error = awi_init(ifp);
 1042                 else
 1043                         error = 0;
 1044         }
 1045         return error;
 1046 }
 1047 
 1048 static void
 1049 awi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 1050 {
 1051         struct awi_softc *sc = ifp->if_softc;
 1052         struct ieee80211com *ic = &sc->sc_ic;
 1053         int rate;
 1054         enum ieee80211_phymode mode;
 1055 
 1056         imr->ifm_status = IFM_AVALID;
 1057         if (ic->ic_state == IEEE80211_S_RUN)
 1058                 imr->ifm_status |= IFM_ACTIVE;
 1059         imr->ifm_active = IFM_IEEE80211;
 1060         if (ic->ic_phytype == IEEE80211_T_FH)
 1061                 mode = IEEE80211_MODE_FH;
 1062         else
 1063                 mode = IEEE80211_MODE_11B;
 1064         if (ic->ic_state == IEEE80211_S_RUN) {
 1065                 rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
 1066                     IEEE80211_RATE_VAL;
 1067         } else {
 1068                 if (ic->ic_fixed_rate == -1)
 1069                         rate = 0;
 1070                 else
 1071                         rate = ic->ic_sup_rates[mode].
 1072                             rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 1073         }
 1074         imr->ifm_active |= ieee80211_rate2media(ic, rate, mode);
 1075         switch (ic->ic_opmode) {
 1076         case IEEE80211_M_MONITOR: /* we should never reach here */
 1077                 break;
 1078         case IEEE80211_M_STA:
 1079                 break;
 1080         case IEEE80211_M_IBSS:
 1081                 if (sc->sc_adhoc_ap)
 1082                         imr->ifm_active |= IFM_FLAG0;
 1083                 else
 1084                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
 1085                 break;
 1086         case IEEE80211_M_AHDEMO:
 1087                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
 1088                 break;
 1089         case IEEE80211_M_HOSTAP:
 1090                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 1091                 break;
 1092         }
 1093 }
 1094 
 1095 static int
 1096 awi_mode_init(struct awi_softc *sc)
 1097 {
 1098         struct ifnet *ifp = &sc->sc_ic.ic_if;
 1099         int n, error;
 1100 #ifdef __FreeBSD__
 1101         struct ifmultiaddr *ifma;
 1102 #else
 1103         struct ether_multi *enm;
 1104         struct ether_multistep step;
 1105 #endif
 1106 
 1107         /* reinitialize muticast filter */
 1108         n = 0;
 1109         sc->sc_mib_local.Accept_All_Multicast_Dis = 0;
 1110         if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP &&
 1111             (ifp->if_flags & IFF_PROMISC)) {
 1112                 sc->sc_mib_mac.aPromiscuous_Enable = 1;
 1113                 goto set_mib;
 1114         }
 1115         sc->sc_mib_mac.aPromiscuous_Enable = 0;
 1116 #ifdef __FreeBSD__
 1117         if (ifp->if_amcount != 0)
 1118                 goto set_mib;
 1119         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1120                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1121                         continue;
 1122                 if (n == AWI_GROUP_ADDR_SIZE)
 1123                         goto set_mib;
 1124                 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
 1125                     LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 1126                 n++;
 1127         }
 1128 #else
 1129         ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm);
 1130         while (enm != NULL) {
 1131                 if (n == AWI_GROUP_ADDR_SIZE ||
 1132                     !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi))
 1133                         goto set_mib;
 1134                 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
 1135                     enm->enm_addrlo);
 1136                 n++;
 1137                 ETHER_NEXT_MULTI(step, enm);
 1138         }
 1139 #endif
 1140         for (; n < AWI_GROUP_ADDR_SIZE; n++)
 1141                 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0,
 1142                     IEEE80211_ADDR_LEN);
 1143         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
 1144 
 1145   set_mib:
 1146         if (sc->sc_mib_local.Accept_All_Multicast_Dis)
 1147                 ifp->if_flags &= ~IFF_ALLMULTI;
 1148         else
 1149                 ifp->if_flags |= IFF_ALLMULTI;
 1150         sc->sc_mib_mgt.Wep_Required =
 1151             (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) ? AWI_WEP_ON : AWI_WEP_OFF;
 1152 
 1153         if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
 1154             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
 1155             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
 1156             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
 1157             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
 1158                 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error));
 1159                 return error;
 1160         }
 1161         return 0;
 1162 }
 1163 
 1164 static void
 1165 awi_rx_int(struct awi_softc *sc)
 1166 {
 1167         struct ieee80211com *ic = &sc->sc_ic;
 1168         struct ifnet *ifp = &ic->ic_if;
 1169         struct ieee80211_frame *wh;
 1170         struct ieee80211_node *ni;
 1171         u_int8_t state, rate, rssi;
 1172         u_int16_t len;
 1173         u_int32_t frame, next, rstamp, rxoff;
 1174         struct mbuf *m;
 1175 
 1176         rxoff = sc->sc_rxdoff;
 1177         for (;;) {
 1178                 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE);
 1179                 if (state & AWI_RXD_ST_OWN)
 1180                         break;
 1181                 if (!(state & AWI_RXD_ST_CONSUMED)) {
 1182                         if (sc->sc_substate != AWI_ST_NONE)
 1183                                 goto rx_next;
 1184                         if (state & AWI_RXD_ST_RXERROR) {
 1185                                 ifp->if_ierrors++;
 1186                                 goto rx_next;
 1187                         }
 1188                         len    = awi_read_2(sc, rxoff + AWI_RXD_LEN);
 1189                         rate   = awi_read_1(sc, rxoff + AWI_RXD_RATE);
 1190                         rssi   = awi_read_1(sc, rxoff + AWI_RXD_RSSI);
 1191                         frame  = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) &
 1192                             0x7fff;
 1193                         rstamp = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME);
 1194                         m = awi_devget(sc, frame, len);
 1195                         if (m == NULL) {
 1196                                 ifp->if_ierrors++;
 1197                                 goto rx_next;
 1198                         }
 1199                         if (state & AWI_RXD_ST_LF) {
 1200                                 /* TODO check my bss */
 1201                                 if (!(sc->sc_ic.ic_flags & IEEE80211_F_SIBSS) &&
 1202                                     sc->sc_ic.ic_state == IEEE80211_S_RUN) {
 1203                                         sc->sc_rx_timer = 10;
 1204                                         ifp->if_timer = 1;
 1205                                 }
 1206                                 if ((ifp->if_flags & IFF_DEBUG) &&
 1207                                     (ifp->if_flags & IFF_LINK2))
 1208                                         ieee80211_dump_pkt(m->m_data, m->m_len,
 1209                                             rate / 5, rssi);
 1210                                 if ((ifp->if_flags & IFF_LINK0) ||
 1211                                     sc->sc_adhoc_ap)
 1212                                         m = awi_ether_modcap(sc, m);
 1213                                 else
 1214                                         m = m_pullup(m, sizeof(*wh));
 1215                                 if (m == NULL) {
 1216                                         ifp->if_ierrors++;
 1217                                         goto rx_next;
 1218                                 }
 1219                                 wh = mtod(m, struct ieee80211_frame *);
 1220 #ifdef __NetBSD__
 1221                                 ni = ieee80211_find_rxnode(ic, wh);
 1222 #else
 1223                                 if (ic->ic_opmode != IEEE80211_M_STA) {
 1224                                         ni = ieee80211_find_node(ic,
 1225                                             wh->i_addr2);
 1226                                         if (ni == NULL)
 1227                                                 ni = ieee80211_ref_node(
 1228                                                     ic->ic_bss);
 1229                                 } else
 1230                                         ni = ieee80211_ref_node(ic->ic_bss);
 1231 #endif
 1232                                 ieee80211_input(ifp, m, ni, rssi, rstamp);
 1233                                 /*
 1234                                  * The frame may have caused the
 1235                                  * node to be marked for reclamation
 1236                                  * (e.g. in response to a DEAUTH
 1237                                  * message) so use free_node here
 1238                                  * instead of unref_node.
 1239                                  */
 1240                                 if (ni == ic->ic_bss)
 1241                                         ieee80211_unref_node(&ni);
 1242                                 else
 1243                                         ieee80211_free_node(ic, ni);
 1244                         } else
 1245                                 sc->sc_rxpend = m;
 1246   rx_next:
 1247                         state |= AWI_RXD_ST_CONSUMED;
 1248                         awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1249                 }
 1250                 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT);
 1251                 if (next & AWI_RXD_NEXT_LAST)
 1252                         break;
 1253                 /* make sure the next pointer is correct */
 1254                 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT))
 1255                         break;
 1256                 state |= AWI_RXD_ST_OWN;
 1257                 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1258                 rxoff = next & 0x7fff;
 1259         }
 1260         sc->sc_rxdoff = rxoff;
 1261 }
 1262 
 1263 static void
 1264 awi_tx_int(struct awi_softc *sc)
 1265 {
 1266         struct ifnet *ifp = &sc->sc_ic.ic_if;
 1267         u_int8_t flags;
 1268 
 1269         while (sc->sc_txdone != sc->sc_txnext) {
 1270                 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE);
 1271                 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE))
 1272                         break;
 1273                 if (flags & AWI_TXD_ST_ERROR)
 1274                         ifp->if_oerrors++;
 1275                 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) &
 1276                     0x7fff;
 1277         }
 1278         DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
 1279             sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend));
 1280         sc->sc_tx_timer = 0;
 1281         ifp->if_flags &= ~IFF_OACTIVE;
 1282         awi_start(ifp);
 1283 }
 1284 
 1285 static struct mbuf *
 1286 awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len)
 1287 {
 1288         struct ifnet *ifp = &sc->sc_ic.ic_if;
 1289         struct mbuf *m;
 1290         struct mbuf *top, **mp;
 1291         u_int tlen;
 1292 
 1293         top = sc->sc_rxpend;
 1294         mp = &top;
 1295         if (top != NULL) {
 1296                 sc->sc_rxpend = NULL;
 1297                 top->m_pkthdr.len += len;
 1298                 m = top;
 1299                 while (*mp != NULL) {
 1300                         m = *mp;
 1301                         mp = &m->m_next;
 1302                 }
 1303                 if (m->m_flags & M_EXT)
 1304                         tlen = m->m_ext.ext_size;
 1305                 else if (m->m_flags & M_PKTHDR)
 1306                         tlen = MHLEN;
 1307                 else
 1308                         tlen = MLEN;
 1309                 tlen -= m->m_len;
 1310                 if (tlen > len)
 1311                         tlen = len;
 1312                 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen);
 1313                 off += tlen;
 1314                 len -= tlen;
 1315         }
 1316 
 1317         while (len > 0) {
 1318                 if (top == NULL) {
 1319                         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1320                         if (m == NULL)
 1321                                 return NULL;
 1322                         m->m_pkthdr.rcvif = ifp;
 1323                         m->m_pkthdr.len = len;
 1324                         m->m_len = MHLEN;
 1325                         m->m_flags |= M_HASFCS;
 1326                 } else {
 1327                         MGET(m, M_DONTWAIT, MT_DATA);
 1328                         if (m == NULL) {
 1329                                 m_freem(top);
 1330                                 return NULL;
 1331                         }
 1332                         m->m_len = MLEN;
 1333                 }
 1334                 if (len >= MINCLSIZE) {
 1335                         MCLGET(m, M_DONTWAIT);
 1336                         if (m->m_flags & M_EXT)
 1337                                 m->m_len = m->m_ext.ext_size;
 1338                 }
 1339                 if (top == NULL) {
 1340                         int hdrlen = sizeof(struct ieee80211_frame) +
 1341                             sizeof(struct llc);
 1342                         caddr_t newdata = (caddr_t)
 1343                             ALIGN(m->m_data + hdrlen) - hdrlen;
 1344                         m->m_len -= newdata - m->m_data;
 1345                         m->m_data = newdata;
 1346                 }
 1347                 if (m->m_len > len)
 1348                         m->m_len = len;
 1349                 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len);
 1350                 off += m->m_len;
 1351                 len -= m->m_len;
 1352                 *mp = m;
 1353                 mp = &m->m_next;
 1354         }
 1355         return top;
 1356 }
 1357 
 1358 /*
 1359  * Initialize hardware and start firmware to accept commands.
 1360  * Called everytime after power on firmware.
 1361  */
 1362 
 1363 static int
 1364 awi_hw_init(struct awi_softc *sc)
 1365 {
 1366         u_int8_t status;
 1367         u_int16_t intmask;
 1368         int i, error;
 1369 
 1370         sc->sc_enab_intr = 0;
 1371         sc->sc_invalid = 0;     /* XXX: really? */
 1372         awi_drvstate(sc, AWI_DRV_RESET);
 1373 
 1374         /* reset firmware */
 1375         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1376         DELAY(100);
 1377         awi_write_1(sc, AWI_SELFTEST, 0);
 1378         awi_write_1(sc, AWI_CMD, 0);
 1379         awi_write_1(sc, AWI_BANNER, 0);
 1380         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1381         DELAY(100);
 1382 
 1383         /* wait for selftest completion */
 1384         for (i = 0; ; i++) {
 1385                 if (sc->sc_invalid)
 1386                         return ENXIO;
 1387                 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) {
 1388                         printf("%s: failed to complete selftest (timeout)\n",
 1389                             sc->sc_ic.ic_if.if_xname);
 1390                         return ENXIO;
 1391                 }
 1392                 status = awi_read_1(sc, AWI_SELFTEST);
 1393                 if ((status & 0xf0) == 0xf0)
 1394                         break;
 1395                 if (sc->sc_cansleep) {
 1396                         sc->sc_sleep_cnt++;
 1397                         (void)tsleep(sc, PWAIT, "awitst", 1);
 1398                         sc->sc_sleep_cnt--;
 1399                 } else {
 1400                         DELAY(1000*1000/hz);
 1401                 }
 1402         }
 1403         if (status != AWI_SELFTEST_PASSED) {
 1404                 printf("%s: failed to complete selftest (code %x)\n",
 1405                     sc->sc_ic.ic_if.if_xname, status);
 1406                 return ENXIO;
 1407         }
 1408 
 1409         /* check banner to confirm firmware write it */
 1410         awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
 1411         if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
 1412                 printf("%s: failed to complete selftest (bad banner)\n",
 1413                     sc->sc_ic.ic_if.if_xname);
 1414                 for (i = 0; i < AWI_BANNER_LEN; i++)
 1415                         printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
 1416                 printf("\n");
 1417                 return ENXIO;
 1418         }
 1419 
 1420         /* initializing interrupt */
 1421         sc->sc_enab_intr = 1;
 1422         error = awi_intr_lock(sc);
 1423         if (error)
 1424                 return error;
 1425         intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT |
 1426             AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD;
 1427         awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff);
 1428         awi_write_1(sc, AWI_INTMASK2, 0);
 1429         awi_write_1(sc, AWI_INTSTAT, 0);
 1430         awi_write_1(sc, AWI_INTSTAT2, 0);
 1431         awi_intr_unlock(sc);
 1432         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
 1433 
 1434         /* issuing interface test command */
 1435         error = awi_cmd(sc, AWI_CMD_NOP, AWI_WAIT);
 1436         if (error) {
 1437                 printf("%s: failed to complete selftest",
 1438                     sc->sc_ic.ic_if.if_xname);
 1439                 if (error == ENXIO)
 1440                         printf(" (no hardware)\n");
 1441                 else if (error != EWOULDBLOCK)
 1442                         printf(" (error %d)\n", error);
 1443                 else if (sc->sc_cansleep)
 1444                         printf(" (lost interrupt)\n");
 1445                 else
 1446                         printf(" (command timeout)\n");
 1447                 return error;
 1448         }
 1449 
 1450         /* Initialize VBM */
 1451         awi_write_1(sc, AWI_VBM_OFFSET, 0);
 1452         awi_write_1(sc, AWI_VBM_LENGTH, 1);
 1453         awi_write_1(sc, AWI_VBM_BITMAP, 0);
 1454         return 0;
 1455 }
 1456 
 1457 /*
 1458  * Extract the factory default MIB value from firmware and assign the driver
 1459  * default value.
 1460  * Called once at attaching the interface.
 1461  */
 1462 
 1463 static int
 1464 awi_init_mibs(struct awi_softc *sc)
 1465 {
 1466         int chan, i, error;
 1467         struct ieee80211com *ic = &sc->sc_ic;
 1468         struct awi_chanset *cs;
 1469 
 1470         if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
 1471             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
 1472             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
 1473             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
 1474             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
 1475                 printf("%s: failed to get default mib value (error %d)\n",
 1476                     ic->ic_if.if_xname, error);
 1477                 return error;
 1478         }
 1479 
 1480         memset(&sc->sc_ic.ic_chan_avail, 0, sizeof(sc->sc_ic.ic_chan_avail));
 1481         for (cs = awi_chanset; ; cs++) {
 1482                 if (cs->cs_type == 0) {
 1483                         printf("%s: failed to set available channel\n",
 1484                             ic->ic_if.if_xname);
 1485                         return ENXIO;
 1486                 }
 1487                 if (cs->cs_type == sc->sc_mib_phy.IEEE_PHY_Type &&
 1488                     cs->cs_region == sc->sc_mib_phy.aCurrent_Reg_Domain)
 1489                         break;
 1490         }
 1491         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1492                 for (i = cs->cs_min; i <= cs->cs_max; i++) {
 1493                         chan = IEEE80211_FH_CHAN(i % 3 + 1, i);
 1494                         setbit(sc->sc_ic.ic_chan_avail, chan);
 1495                         /* XXX for FHSS, does frequency matter? */
 1496                         ic->ic_channels[chan].ic_freq = 0;
 1497                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
 1498                         /*
 1499                          * According to the IEEE 802.11 specification,
 1500                          * hop pattern parameter for FH phy should be
 1501                          * incremented by 3 for given hop chanset, i.e.,
 1502                          * the chanset parameter is calculated for given
 1503                          * hop patter.  However, BayStack 650 Access Points
 1504                          * apparently use fixed hop chanset parameter value
 1505                          * 1 for any hop pattern.  So we also try this
 1506                          * combination of hop chanset and pattern.
 1507                          */
 1508                         chan = IEEE80211_FH_CHAN(1, i);
 1509                         setbit(sc->sc_ic.ic_chan_avail, chan);
 1510                         ic->ic_channels[chan].ic_freq = 0; /* XXX */
 1511                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
 1512                 }
 1513         } else {
 1514                 for (i = cs->cs_min; i <= cs->cs_max; i++) {
 1515                         setbit(sc->sc_ic.ic_chan_avail, i);
 1516                         ic->ic_channels[i].ic_freq =
 1517                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
 1518                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
 1519                 }
 1520         }
 1521         sc->sc_cur_chan = cs->cs_def;
 1522         ic->ic_ibss_chan = &ic->ic_channels[cs->cs_def];
 1523 
 1524         sc->sc_mib_local.Fragmentation_Dis = 1;
 1525         sc->sc_mib_local.Add_PLCP_Dis = 0;
 1526         sc->sc_mib_local.MAC_Hdr_Prsv = 0;
 1527         sc->sc_mib_local.Rx_Mgmt_Que_En = 0;
 1528         sc->sc_mib_local.Re_Assembly_Dis = 1;
 1529         sc->sc_mib_local.Strip_PLCP_Dis = 0;
 1530         sc->sc_mib_local.Power_Saving_Mode_Dis = 1;
 1531         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
 1532         sc->sc_mib_local.Check_Seq_Cntl_Dis = 0;
 1533         sc->sc_mib_local.Flush_CFP_Queue_On_CF_End = 0;
 1534         sc->sc_mib_local.Network_Mode = 1;
 1535         sc->sc_mib_local.PWD_Lvl = 0;
 1536         sc->sc_mib_local.CFP_Mode = 0;
 1537 
 1538         /* allocate buffers */
 1539         sc->sc_txbase = AWI_BUFFERS;
 1540         sc->sc_txend = sc->sc_txbase +
 1541             (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) +
 1542             sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS;
 1543         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase);
 1544         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size,
 1545             sc->sc_txend - sc->sc_txbase);
 1546         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend);
 1547         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size,
 1548             AWI_BUFFERS_END - sc->sc_txend);
 1549         sc->sc_mib_local.Acting_as_AP = 0;
 1550         sc->sc_mib_local.Fill_CFP = 0;
 1551 
 1552         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
 1553         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
 1554 
 1555         sc->sc_mib_mgt.aPower_Mgt_Mode = 0;
 1556         sc->sc_mib_mgt.aDTIM_Period = 1;
 1557         LE_WRITE_2(&sc->sc_mib_mgt.aATIM_Window, 0);
 1558         return 0;
 1559 }
 1560 
 1561 static int
 1562 awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib, int wflag)
 1563 {
 1564         int error;
 1565         u_int8_t size, *ptr;
 1566 
 1567         switch (mib) {
 1568         case AWI_MIB_LOCAL:
 1569                 ptr = (u_int8_t *)&sc->sc_mib_local;
 1570                 size = sizeof(sc->sc_mib_local);
 1571                 break;
 1572         case AWI_MIB_ADDR:
 1573                 ptr = (u_int8_t *)&sc->sc_mib_addr;
 1574                 size = sizeof(sc->sc_mib_addr);
 1575                 break;
 1576         case AWI_MIB_MAC:
 1577                 ptr = (u_int8_t *)&sc->sc_mib_mac;
 1578                 size = sizeof(sc->sc_mib_mac);
 1579                 break;
 1580         case AWI_MIB_STAT:
 1581                 ptr = (u_int8_t *)&sc->sc_mib_stat;
 1582                 size = sizeof(sc->sc_mib_stat);
 1583                 break;
 1584         case AWI_MIB_MGT:
 1585                 ptr = (u_int8_t *)&sc->sc_mib_mgt;
 1586                 size = sizeof(sc->sc_mib_mgt);
 1587                 break;
 1588         case AWI_MIB_PHY:
 1589                 ptr = (u_int8_t *)&sc->sc_mib_phy;
 1590                 size = sizeof(sc->sc_mib_phy);
 1591                 break;
 1592         default:
 1593                 return EINVAL;
 1594         }
 1595         if (sc->sc_cmd_inprog) {
 1596                 if ((error = awi_cmd_wait(sc)) != 0) {
 1597                         if (error == EWOULDBLOCK)
 1598                                 DPRINTF(("awi_mib: cmd %d inprog",
 1599                                     sc->sc_cmd_inprog));
 1600                         return error;
 1601                 }
 1602         }
 1603         sc->sc_cmd_inprog = cmd;
 1604         if (cmd == AWI_CMD_SET_MIB)
 1605                 awi_write_bytes(sc, AWI_CA_MIB_DATA, ptr, size);
 1606         awi_write_1(sc, AWI_CA_MIB_TYPE, mib);
 1607         awi_write_1(sc, AWI_CA_MIB_SIZE, size);
 1608         awi_write_1(sc, AWI_CA_MIB_INDEX, 0);
 1609         if ((error = awi_cmd(sc, cmd, wflag)) != 0)
 1610                 return error;
 1611         if (cmd == AWI_CMD_GET_MIB) {
 1612                 awi_read_bytes(sc, AWI_CA_MIB_DATA, ptr, size);
 1613 #ifdef AWI_DEBUG
 1614                 if (awi_debug) {
 1615                         int i;
 1616 
 1617                         printf("awi_mib: #%d:", mib);
 1618                         for (i = 0; i < size; i++)
 1619                                 printf(" %02x", ptr[i]);
 1620                         printf("\n");
 1621                 }
 1622 #endif
 1623         }
 1624         return 0;
 1625 }
 1626 
 1627 static int
 1628 awi_cmd(struct awi_softc *sc, u_int8_t cmd, int wflag)
 1629 {
 1630         u_int8_t status;
 1631         int error = 0;
 1632 #ifdef AWI_DEBUG
 1633         static const char *cmdname[] = {
 1634             "IDLE", "NOP", "SET_MIB", "INIT_TX", "FLUSH_TX", "INIT_RX",
 1635             "KILL_RX", "SLEEP", "WAKE", "GET_MIB", "SCAN", "SYNC", "RESUME"
 1636         };
 1637 #endif
 1638 
 1639 #ifdef AWI_DEBUG
 1640         if (awi_debug > 1) {
 1641                 if (cmd >= sizeof(cmdname)/sizeof(cmdname[0]))
 1642                         printf("awi_cmd: #%d", cmd);
 1643                 else
 1644                         printf("awi_cmd: %s", cmdname[cmd]);
 1645                 printf(" %s\n", wflag == AWI_NOWAIT ? "nowait" : "wait");
 1646         }
 1647 #endif
 1648         sc->sc_cmd_inprog = cmd;
 1649         awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE);
 1650         awi_write_1(sc, AWI_CMD, cmd);
 1651         if (wflag == AWI_NOWAIT)
 1652                 return EINPROGRESS;
 1653         if ((error = awi_cmd_wait(sc)) != 0)
 1654                 return error;
 1655         status = awi_read_1(sc, AWI_CMD_STATUS);
 1656         awi_write_1(sc, AWI_CMD, 0);
 1657         switch (status) {
 1658         case AWI_STAT_OK:
 1659                 break;
 1660         case AWI_STAT_BADPARM:
 1661                 return EINVAL;
 1662         default:
 1663                 printf("%s: command %d failed %x\n",
 1664                     sc->sc_ic.ic_if.if_xname, cmd, status);
 1665                 return ENXIO;
 1666         }
 1667         return 0;
 1668 }
 1669 
 1670 static int
 1671 awi_cmd_wait(struct awi_softc *sc)
 1672 {
 1673         int i, error = 0;
 1674 
 1675         i = 0;
 1676         while (sc->sc_cmd_inprog) {
 1677                 if (sc->sc_invalid)
 1678                         return ENXIO;
 1679                 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) {
 1680                         printf("%s: failed to access hardware\n",
 1681                             sc->sc_ic.ic_if.if_xname);
 1682                         sc->sc_invalid = 1;
 1683                         return ENXIO;
 1684                 }
 1685                 if (sc->sc_cansleep) {
 1686                         sc->sc_sleep_cnt++;
 1687                         error = tsleep(sc, PWAIT, "awicmd",
 1688                             AWI_CMD_TIMEOUT*hz/1000);
 1689                         sc->sc_sleep_cnt--;
 1690                 } else {
 1691                         if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) {
 1692                                 awi_cmd_done(sc);
 1693                                 break;
 1694                         }
 1695                         if (i++ >= AWI_CMD_TIMEOUT*1000/10)
 1696                                 error = EWOULDBLOCK;
 1697                         else
 1698                                 DELAY(10);
 1699                 }
 1700                 if (error)
 1701                         break;
 1702         }
 1703         if (error) {
 1704                 DPRINTF(("awi_cmd_wait: cmd 0x%x, error %d\n",
 1705                     sc->sc_cmd_inprog, error));
 1706         }
 1707         return error;
 1708 }
 1709 
 1710 static void
 1711 awi_cmd_done(struct awi_softc *sc)
 1712 {
 1713         u_int8_t cmd, status;
 1714 
 1715         status = awi_read_1(sc, AWI_CMD_STATUS);
 1716         if (status == AWI_STAT_IDLE)
 1717                 return;         /* stray interrupt */
 1718 
 1719         cmd = sc->sc_cmd_inprog;
 1720         sc->sc_cmd_inprog = 0;
 1721         wakeup(sc);
 1722         awi_write_1(sc, AWI_CMD, 0);
 1723 
 1724         if (status != AWI_STAT_OK) {
 1725                 printf("%s: command %d failed %x\n",
 1726                     sc->sc_ic.ic_if.if_xname, cmd, status);
 1727                 sc->sc_substate = AWI_ST_NONE;
 1728                 return;
 1729         }
 1730         if (sc->sc_substate != AWI_ST_NONE)
 1731                 (void)ieee80211_new_state(&sc->sc_ic, sc->sc_nstate, -1);
 1732 }
 1733 
 1734 static int
 1735 awi_next_txd(struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t *ntxdp)
 1736 {
 1737         u_int32_t txd, ntxd, frame;
 1738 
 1739         txd = sc->sc_txnext;
 1740         frame = txd + AWI_TXD_SIZE;
 1741         if (frame + len > sc->sc_txend)
 1742                 frame = sc->sc_txbase;
 1743         ntxd = frame + len;
 1744         if (ntxd + AWI_TXD_SIZE > sc->sc_txend)
 1745                 ntxd = sc->sc_txbase;
 1746         *framep = frame;
 1747         *ntxdp = ntxd;
 1748         /*
 1749          * Determine if there are any room in ring buffer.
 1750          *              --- send wait,  === new data,  +++ conflict (ENOBUFS)
 1751          *   base........................end
 1752          *         done----txd=====ntxd         OK
 1753          *       --txd=====done++++ntxd--       full
 1754          *       --txd=====ntxd    done--       OK
 1755          *       ==ntxd    done----txd===       OK
 1756          *       ==done++++ntxd----txd===       full
 1757          *       ++ntxd    txd=====done++       full
 1758          */
 1759         if (txd < ntxd) {
 1760                 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone)
 1761                         return ENOBUFS;
 1762         } else {
 1763                 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone)
 1764                         return ENOBUFS;
 1765         }
 1766         return 0;
 1767 }
 1768 
 1769 static int
 1770 awi_lock(struct awi_softc *sc)
 1771 {
 1772         int error = 0;
 1773 
 1774 #ifdef __NetBSD__
 1775         if (curlwp == NULL)
 1776 #else
 1777         if (curproc == NULL)
 1778 #endif
 1779         {
 1780                 /*
 1781                  * XXX
 1782                  * Though driver ioctl should be called with context,
 1783                  * KAME ipv6 stack calls ioctl in interrupt for now.
 1784                  * We simply abort the request if there are other
 1785                  * ioctl requests in progress.
 1786                  */
 1787                 if (sc->sc_busy) {
 1788                         if (sc->sc_invalid)
 1789                                 return ENXIO;
 1790                         return EWOULDBLOCK;
 1791                 }
 1792                 sc->sc_busy = 1;
 1793                 sc->sc_cansleep = 0;
 1794                 return 0;
 1795         }
 1796         while (sc->sc_busy) {
 1797                 if (sc->sc_invalid)
 1798                         return ENXIO;
 1799                 sc->sc_sleep_cnt++;
 1800                 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0);
 1801                 sc->sc_sleep_cnt--;
 1802                 if (error)
 1803                         return error;
 1804         }
 1805         sc->sc_busy = 1;
 1806         sc->sc_cansleep = 1;
 1807         return 0;
 1808 }
 1809 
 1810 static void
 1811 awi_unlock(struct awi_softc *sc)
 1812 {
 1813         sc->sc_busy = 0;
 1814         sc->sc_cansleep = 0;
 1815         if (sc->sc_sleep_cnt)
 1816                 wakeup(sc);
 1817 }
 1818 
 1819 static int
 1820 awi_intr_lock(struct awi_softc *sc)
 1821 {
 1822         u_int8_t status;
 1823         int i, retry;
 1824 
 1825         status = 1;
 1826         for (retry = 0; retry < 10; retry++) {
 1827                 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) {
 1828                         if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0)
 1829                                 break;
 1830                         DELAY(5);
 1831                 }
 1832                 if (status != 0)
 1833                         break;
 1834                 awi_write_1(sc, AWI_LOCKOUT_MAC, 1);
 1835                 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0)
 1836                         break;
 1837                 awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
 1838         }
 1839         if (status != 0) {
 1840                 printf("%s: failed to lock interrupt\n",
 1841                     sc->sc_ic.ic_if.if_xname);
 1842                 return ENXIO;
 1843         }
 1844         return 0;
 1845 }
 1846 
 1847 static void
 1848 awi_intr_unlock(struct awi_softc *sc)
 1849 {
 1850 
 1851         awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
 1852 }
 1853 
 1854 static int
 1855 awi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 1856 {
 1857         struct awi_softc *sc = ic->ic_softc;
 1858         struct ieee80211_node *ni;
 1859         struct ifnet *ifp = &ic->ic_if;
 1860         int error;
 1861         u_int8_t newmode;
 1862         enum ieee80211_state ostate;
 1863 #ifdef AWI_DEBUG
 1864         static const char *stname[] =
 1865             { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
 1866         static const char *substname[] =
 1867             { "NONE", "SCAN_INIT", "SCAN_SETMIB", "SCAN_SCCMD",
 1868               "SUB_INIT", "SUB_SETSS", "SUB_SYNC" };
 1869 #endif /* AWI_DEBUG */
 1870 
 1871         ostate = ic->ic_state;
 1872         DPRINTF(("awi_newstate: %s (%s/%s) -> %s\n", stname[ostate],
 1873             stname[sc->sc_nstate], substname[sc->sc_substate], stname[nstate]));
 1874 
 1875         /* set LED */
 1876         switch (nstate) {
 1877         case IEEE80211_S_INIT:
 1878                 awi_drvstate(sc, AWI_DRV_RESET);
 1879                 break;
 1880         case IEEE80211_S_SCAN:
 1881                 if (ic->ic_opmode == IEEE80211_M_IBSS ||
 1882                     ic->ic_opmode == IEEE80211_M_AHDEMO)
 1883                         awi_drvstate(sc, AWI_DRV_ADHSC);
 1884                 else
 1885                         awi_drvstate(sc, AWI_DRV_INFSY);
 1886                 break;
 1887         case IEEE80211_S_AUTH:
 1888                 awi_drvstate(sc, AWI_DRV_INFSY);
 1889                 break;
 1890         case IEEE80211_S_ASSOC:
 1891                 awi_drvstate(sc, AWI_DRV_INFAUTH);
 1892                 break;
 1893         case IEEE80211_S_RUN:
 1894                 if (ic->ic_opmode == IEEE80211_M_IBSS ||
 1895                     ic->ic_opmode == IEEE80211_M_AHDEMO)
 1896                         awi_drvstate(sc, AWI_DRV_ADHSY);
 1897                 else
 1898                         awi_drvstate(sc, AWI_DRV_INFASSOC);
 1899                 break;
 1900         }
 1901 
 1902         if (nstate == IEEE80211_S_INIT) {
 1903                 sc->sc_substate = AWI_ST_NONE;
 1904                 ic->ic_flags &= ~IEEE80211_F_SIBSS;
 1905                 return (*sc->sc_newstate)(ic, nstate, arg);
 1906         }
 1907 
 1908         /* state transition */
 1909         if (nstate == IEEE80211_S_SCAN) {
 1910                 /* SCAN substate */
 1911                 if (sc->sc_substate == AWI_ST_NONE) {
 1912                         sc->sc_nstate = nstate; /* next state in transition */
 1913                         sc->sc_substate = AWI_ST_SCAN_INIT;
 1914                 }
 1915                 switch (sc->sc_substate) {
 1916                 case AWI_ST_SCAN_INIT:
 1917                         sc->sc_substate = AWI_ST_SCAN_SETMIB;
 1918                         switch (ostate) {
 1919                         case IEEE80211_S_RUN:
 1920                                 /* beacon miss */
 1921                                 if (ifp->if_flags & IFF_DEBUG)
 1922                                         printf("%s: no recent beacons from %s;"
 1923                                             " rescanning\n",
 1924                                             ifp->if_xname,
 1925                                             ether_sprintf(ic->ic_bss->ni_bssid));
 1926                                 /* FALLTHRU */
 1927                         case IEEE80211_S_AUTH:
 1928                         case IEEE80211_S_ASSOC:
 1929                         case IEEE80211_S_INIT:
 1930                                 ieee80211_begin_scan(ifp);
 1931                                 /* FALLTHRU */
 1932                         case IEEE80211_S_SCAN:
 1933                                 /* scan next */
 1934                                 break;
 1935                         }
 1936                         if (ic->ic_flags & IEEE80211_F_ASCAN)
 1937                                 newmode = AWI_SCAN_ACTIVE;
 1938                         else
 1939                                 newmode = AWI_SCAN_PASSIVE;
 1940                         if (sc->sc_mib_mgt.aScan_Mode != newmode) {
 1941                                 sc->sc_mib_mgt.aScan_Mode = newmode;
 1942                                 if ((error = awi_mib(sc, AWI_CMD_SET_MIB,
 1943                                     AWI_MIB_MGT, AWI_NOWAIT)) != 0)
 1944                                         break;
 1945                         }
 1946                         /* FALLTHRU */
 1947                 case AWI_ST_SCAN_SETMIB:
 1948                         sc->sc_substate = AWI_ST_SCAN_SCCMD;
 1949                         if (sc->sc_cmd_inprog) {
 1950                                 if ((error = awi_cmd_wait(sc)) != 0)
 1951                                         break;
 1952                         }
 1953                         sc->sc_cmd_inprog = AWI_CMD_SCAN;
 1954                         ni = ic->ic_bss;
 1955                         awi_write_2(sc, AWI_CA_SCAN_DURATION,
 1956                             (ic->ic_flags & IEEE80211_F_ASCAN) ?
 1957                             AWI_ASCAN_DURATION : AWI_PSCAN_DURATION);
 1958                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1959                                 awi_write_1(sc, AWI_CA_SCAN_SET,
 1960                                     IEEE80211_FH_CHANSET(
 1961                                         ieee80211_chan2ieee(ic, ni->ni_chan)));
 1962                                 awi_write_1(sc, AWI_CA_SCAN_PATTERN,
 1963                                     IEEE80211_FH_CHANPAT(
 1964                                         ieee80211_chan2ieee(ic, ni->ni_chan)));
 1965                                 awi_write_1(sc, AWI_CA_SCAN_IDX, 1);
 1966                         } else {
 1967                                 awi_write_1(sc, AWI_CA_SCAN_SET,
 1968                                     ieee80211_chan2ieee(ic, ni->ni_chan));
 1969                                 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 0);
 1970                                 awi_write_1(sc, AWI_CA_SCAN_IDX, 0);
 1971                         }
 1972                         awi_write_1(sc, AWI_CA_SCAN_SUSP, 0);
 1973                         sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
 1974                         if ((error = awi_cmd(sc, AWI_CMD_SCAN, AWI_NOWAIT))
 1975                             != 0)
 1976                                 break;
 1977                         /* FALLTHRU */
 1978                 case AWI_ST_SCAN_SCCMD:
 1979                         ic->ic_state = nstate;
 1980                         sc->sc_substate = AWI_ST_NONE;
 1981                         error = EINPROGRESS;
 1982                         break;
 1983                 default:
 1984                         DPRINTF(("awi_newstate: unexpected state %s/%s\n",
 1985                             stname[nstate], substname[sc->sc_substate]));
 1986                         sc->sc_substate = AWI_ST_NONE;
 1987                         error = EIO;
 1988                         break;
 1989                 }
 1990                 goto out;
 1991         }
 1992 
 1993         if (ostate == IEEE80211_S_SCAN) {
 1994                 /* set SSID and channel */
 1995                 /* substate */
 1996                 if (sc->sc_substate == AWI_ST_NONE) {
 1997                         sc->sc_nstate = nstate; /* next state in transition */
 1998                         sc->sc_substate = AWI_ST_SUB_INIT;
 1999                 }
 2000                 ni = ic->ic_bss;
 2001                 switch (sc->sc_substate) {
 2002                 case AWI_ST_SUB_INIT:
 2003                         sc->sc_substate = AWI_ST_SUB_SETSS;
 2004                         IEEE80211_ADDR_COPY(&sc->sc_mib_mgt.aCurrent_BSS_ID,
 2005                             ni->ni_bssid);
 2006                         memset(&sc->sc_mib_mgt.aCurrent_ESS_ID, 0,
 2007                             AWI_ESS_ID_SIZE);
 2008                         sc->sc_mib_mgt.aCurrent_ESS_ID[0] =
 2009                             IEEE80211_ELEMID_SSID;
 2010                         sc->sc_mib_mgt.aCurrent_ESS_ID[1] = ni->ni_esslen;
 2011                         memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID[2],
 2012                             ni->ni_essid, ni->ni_esslen);
 2013                         LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period,
 2014                             ni->ni_intval);
 2015                         if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT,
 2016                             AWI_NOWAIT)) != 0)
 2017                                 break;
 2018                         /* FALLTHRU */
 2019                 case AWI_ST_SUB_SETSS:
 2020                         sc->sc_substate = AWI_ST_SUB_SYNC;
 2021                         if (sc->sc_cmd_inprog) {
 2022                                 if ((error = awi_cmd_wait(sc)) != 0)
 2023                                         break;
 2024                         }
 2025                         sc->sc_cmd_inprog = AWI_CMD_SYNC;
 2026                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 2027                                 awi_write_1(sc, AWI_CA_SYNC_SET,
 2028                                     IEEE80211_FH_CHANSET(
 2029                                         ieee80211_chan2ieee(ic, ni->ni_chan)));
 2030                                 awi_write_1(sc, AWI_CA_SYNC_PATTERN,
 2031                                     IEEE80211_FH_CHANPAT(
 2032                                         ieee80211_chan2ieee(ic, ni->ni_chan)));
 2033                                 awi_write_1(sc, AWI_CA_SYNC_IDX,
 2034                                     ni->ni_fhindex);
 2035                                 awi_write_2(sc, AWI_CA_SYNC_DWELL,
 2036                                     ni->ni_fhdwell);
 2037                         } else {
 2038                                 awi_write_1(sc, AWI_CA_SYNC_SET,
 2039                                     ieee80211_chan2ieee(ic, ni->ni_chan));
 2040                                 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 0);
 2041                                 awi_write_1(sc, AWI_CA_SYNC_IDX, 0);
 2042                                 awi_write_2(sc, AWI_CA_SYNC_DWELL, 0);
 2043                         }
 2044                         if (ic->ic_flags & IEEE80211_F_SIBSS) {
 2045                                 memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
 2046                                 ni->ni_rstamp = 0;
 2047                                 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1);
 2048                         } else
 2049                                 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0);
 2050                         awi_write_2(sc, AWI_CA_SYNC_MBZ, 0);
 2051                         awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP,
 2052                             ni->ni_tstamp, 8);
 2053                         awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp);
 2054                         sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
 2055                         if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT))
 2056                             != 0)
 2057                                 break;
 2058                         /* FALLTHRU */
 2059                 case AWI_ST_SUB_SYNC:
 2060                         sc->sc_substate = AWI_ST_NONE;
 2061                         if (ic->ic_flags & IEEE80211_F_SIBSS) {
 2062                                 if ((error = awi_mib(sc, AWI_CMD_GET_MIB,
 2063                                     AWI_MIB_MGT, AWI_WAIT)) != 0)
 2064                                         break;
 2065                                 IEEE80211_ADDR_COPY(ni->ni_bssid,
 2066                                     &sc->sc_mib_mgt.aCurrent_BSS_ID);
 2067                         } else {
 2068                                 if (nstate == IEEE80211_S_RUN) {
 2069                                         sc->sc_rx_timer = 10;
 2070                                         ifp->if_timer = 1;
 2071                                 }
 2072                         }
 2073                         error = 0;
 2074                         break;
 2075                 default:
 2076                         DPRINTF(("awi_newstate: unexpected state %s/%s\n",
 2077                             stname[nstate], substname[sc->sc_substate]));
 2078                         sc->sc_substate = AWI_ST_NONE;
 2079                         error = EIO;
 2080                         break;
 2081                 }
 2082                 goto out;
 2083         }
 2084 
 2085         sc->sc_substate = AWI_ST_NONE;
 2086 
 2087         return (*sc->sc_newstate)(ic, nstate, arg);
 2088 out:
 2089         if (error != 0) {
 2090                 if (error == EINPROGRESS)
 2091                         error = 0;
 2092                 return error;
 2093         }
 2094         return (*sc->sc_newstate)(ic, nstate, arg);
 2095 }
 2096 
 2097 static void
 2098 awi_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
 2099         struct ieee80211_node *ni,
 2100         int subtype, int rssi, u_int32_t rstamp)
 2101 {
 2102         struct awi_softc *sc = ic->ic_softc;
 2103 
 2104         /* probe request is handled by hardware */
 2105         if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
 2106                 return;
 2107         (*sc->sc_recv_mgmt)(ic, m0, ni, subtype, rssi, rstamp);
 2108 }
 2109 
 2110 static int
 2111 awi_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
 2112         int type, int arg)
 2113 {
 2114         struct awi_softc *sc = ic->ic_softc;
 2115 
 2116         /* probe request is handled by hardware */
 2117         if (type == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
 2118                 return 0;
 2119         return (*sc->sc_send_mgmt)(ic, ni, type, arg);
 2120 }
 2121 
 2122 static struct mbuf *
 2123 awi_ether_encap(struct awi_softc *sc, struct mbuf *m)
 2124 {
 2125         struct ieee80211com *ic = &sc->sc_ic;
 2126         struct ieee80211_node *ni = ic->ic_bss;
 2127         struct ether_header *eh;
 2128         struct ieee80211_frame *wh;
 2129 
 2130         if (m->m_len < sizeof(struct ether_header)) {
 2131                 m = m_pullup(m, sizeof(struct ether_header));
 2132                 if (m == NULL)
 2133                         return NULL;
 2134         }
 2135         eh = mtod(m, struct ether_header *);
 2136         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
 2137         if (m == NULL)
 2138                 return NULL;
 2139         wh = mtod(m, struct ieee80211_frame *);
 2140         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
 2141         *(u_int16_t *)wh->i_dur = 0;
 2142         *(u_int16_t *)wh->i_seq =
 2143             htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
 2144         ni->ni_txseq++;
 2145         if (ic->ic_opmode == IEEE80211_M_IBSS ||
 2146             ic->ic_opmode == IEEE80211_M_AHDEMO) {
 2147                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 2148                 if (sc->sc_adhoc_ap)
 2149                         IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
 2150                 else
 2151                         IEEE80211_ADDR_COPY(wh->i_addr1, eh->ether_dhost);
 2152                 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
 2153                 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
 2154         } else {
 2155                 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
 2156                 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
 2157                 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
 2158                 IEEE80211_ADDR_COPY(wh->i_addr3, eh->ether_dhost);
 2159         }
 2160         return m;
 2161 }
 2162 
 2163 static struct mbuf *
 2164 awi_ether_modcap(struct awi_softc *sc, struct mbuf *m)
 2165 {
 2166         struct ieee80211com *ic = &sc->sc_ic;
 2167         struct ether_header eh;
 2168         struct ieee80211_frame wh;
 2169         struct llc *llc;
 2170 
 2171         if (m->m_len < sizeof(wh) + sizeof(eh)) {
 2172                 m = m_pullup(m, sizeof(wh) + sizeof(eh));
 2173                 if (m == NULL)
 2174                         return NULL;
 2175         }
 2176         memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
 2177         if (wh.i_fc[0] != (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA))
 2178                 return m;
 2179         memcpy(&eh, mtod(m, caddr_t) + sizeof(wh), sizeof(eh));
 2180         m_adj(m, sizeof(eh) - sizeof(*llc));
 2181         if (ic->ic_opmode == IEEE80211_M_IBSS ||
 2182             ic->ic_opmode == IEEE80211_M_AHDEMO)
 2183                 IEEE80211_ADDR_COPY(wh.i_addr2, eh.ether_shost);
 2184         memcpy(mtod(m, caddr_t), &wh, sizeof(wh));
 2185         llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
 2186         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 2187         llc->llc_control = LLC_UI;
 2188         llc->llc_snap.org_code[0] = 0;
 2189         llc->llc_snap.org_code[1] = 0;
 2190         llc->llc_snap.org_code[2] = 0;
 2191         llc->llc_snap.ether_type = eh.ether_type;
 2192         return m;
 2193 }

Cache object: 9c123184e6cc2a875e4d88bb63840ac7


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


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