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.73 2006/10/04 15:36:23 christos 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.73 2006/10/04 15:36:23 christos 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_netbsd.h>
  133 #include <net80211/ieee80211_var.h>
  134 
  135 #if NBPFILTER > 0
  136 #include <net/bpf.h>
  137 #endif
  138 
  139 #include <machine/cpu.h>
  140 #include <machine/bus.h>
  141 
  142 #ifdef __NetBSD__
  143 #include <dev/ic/am79c930reg.h>
  144 #include <dev/ic/am79c930var.h>
  145 #include <dev/ic/awireg.h>
  146 #include <dev/ic/awivar.h>
  147 #endif
  148 #ifdef __FreeBSD__
  149 #include <dev/awi/am79c930reg.h>
  150 #include <dev/awi/am79c930var.h>
  151 #include <dev/awi/awireg.h>
  152 #include <dev/awi/awivar.h>
  153 #endif
  154 
  155 #ifdef __FreeBSD__
  156 static void awi_init0(void *);
  157 #endif
  158 static int  awi_init(struct ifnet *);
  159 static void awi_stop(struct ifnet *, int);
  160 static void awi_start(struct ifnet *);
  161 static void awi_watchdog(struct ifnet *);
  162 static int  awi_ioctl(struct ifnet *, u_long, caddr_t);
  163 static int  awi_media_change(struct ifnet *);
  164 static void awi_media_status(struct ifnet *, struct ifmediareq *);
  165 static int  awi_mode_init(struct awi_softc *);
  166 static void awi_rx_int(struct awi_softc *);
  167 static void awi_tx_int(struct awi_softc *);
  168 static struct mbuf *awi_devget(struct awi_softc *, u_int32_t, u_int16_t);
  169 static int  awi_hw_init(struct awi_softc *);
  170 static int  awi_init_mibs(struct awi_softc *);
  171 static int  awi_mib(struct awi_softc *, u_int8_t, u_int8_t, int);
  172 static int  awi_cmd(struct awi_softc *, u_int8_t, int);
  173 static int  awi_cmd_wait(struct awi_softc *);
  174 static void awi_cmd_done(struct awi_softc *);
  175 static int  awi_next_txd(struct awi_softc *, int, u_int32_t *, u_int32_t *);
  176 static int  awi_lock(struct awi_softc *);
  177 static void awi_unlock(struct awi_softc *);
  178 static int  awi_intr_lock(struct awi_softc *);
  179 static void awi_intr_unlock(struct awi_softc *);
  180 static int  awi_newstate(struct ieee80211com *, enum ieee80211_state, int);
  181 static void awi_recv_mgmt(struct ieee80211com *, struct mbuf *,
  182     struct ieee80211_node *, int, int, u_int32_t);
  183 static int  awi_send_mgmt(struct ieee80211com *, struct ieee80211_node *, int,
  184     int);
  185 static struct mbuf *awi_ether_encap(struct awi_softc *, struct mbuf *);
  186 static struct mbuf *awi_ether_modcap(struct awi_softc *, struct mbuf *);
  187 
  188 /* unaligned little endian access */
  189 #define LE_READ_2(p)                                                    \
  190         ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8))
  191 #define LE_READ_4(p)                                                    \
  192         ((((u_int8_t *)(p))[0]      ) | (((u_int8_t *)(p))[1] <<  8) |  \
  193          (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))
  194 #define LE_WRITE_2(p, v)                                                \
  195         ((((u_int8_t *)(p))[0] = (((u_int32_t)(v)      ) & 0xff)),      \
  196          (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >>  8) & 0xff)))
  197 #define LE_WRITE_4(p, v)                                                \
  198         ((((u_int8_t *)(p))[0] = (((u_int32_t)(v)      ) & 0xff)),      \
  199          (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >>  8) & 0xff)),      \
  200          (((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)),      \
  201          (((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff)))
  202 
  203 struct awi_chanset awi_chanset[] = {
  204     /* PHY type        domain            min max def */
  205     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_JP,  6, 17,  6 },
  206     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_ES,  0, 26,  1 },
  207     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_FR,  0, 32,  1 },
  208     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_US,  0, 77,  1 },
  209     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_CA,  0, 77,  1 },
  210     { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_EU,  0, 77,  1 },
  211     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_JP, 14, 14, 14 },
  212     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_ES, 10, 11, 10 },
  213     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_FR, 10, 13, 10 },
  214     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_US,  1, 11,  3 },
  215     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_CA,  1, 11,  3 },
  216     { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_EU,  1, 13,  3 },
  217     { 0, 0, 0, 0, 0 }
  218 };
  219 
  220 #ifdef __FreeBSD__
  221 devclass_t awi_devclass;
  222 
  223 #if __FreeBSD_version < 500043
  224 static char *ether_sprintf(u_int8_t *);
  225 
  226 static char *
  227 ether_sprintf(u_int8_t *enaddr)
  228 {
  229         static char strbuf[18];
  230 
  231         sprintf(strbuf, "%6D", enaddr, ":");
  232         return strbuf;
  233 }
  234 #endif
  235 
  236 #define IFQ_PURGE(ifq)          IF_DRAIN(ifq)
  237 #define IF_POLL(ifq, m)         ((m) = (ifq)->ifq_head)
  238 #define IFQ_POLL(ifq, m)        IF_POLL((ifq), (m))
  239 #define IFQ_DEQUEUE(ifq, m)     IF_DEQUEUE((ifq), (m))
  240 
  241 #endif
  242 
  243 #ifdef AWI_DEBUG
  244 int awi_debug = 0;
  245 
  246 #define DPRINTF(X)      if (awi_debug) printf X
  247 #define DPRINTF2(X)     if (awi_debug > 1) printf X
  248 #else
  249 #define DPRINTF(X)
  250 #define DPRINTF2(X)
  251 #endif
  252 
  253 int
  254 awi_attach(struct awi_softc *sc)
  255 {
  256         struct ieee80211com *ic = &sc->sc_ic;
  257         struct ifnet *ifp = &sc->sc_if;
  258         int s, i, error, nrate;
  259         int mword;
  260         enum ieee80211_phymode mode;
  261 
  262         s = splnet();
  263         sc->sc_busy = 1;
  264         sc->sc_attached = 0;
  265         sc->sc_substate = AWI_ST_NONE;
  266         if ((error = awi_hw_init(sc)) != 0) {
  267                 sc->sc_invalid = 1;
  268                 splx(s);
  269                 return error;
  270         }
  271         error = awi_init_mibs(sc);
  272         if (error != 0) {
  273                 sc->sc_invalid = 1;
  274                 splx(s);
  275                 return error;
  276         }
  277         ifp->if_softc = sc;
  278         ifp->if_flags =
  279 #ifdef IFF_NOTRAILERS
  280             IFF_NOTRAILERS |
  281 #endif
  282             IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
  283         ifp->if_ioctl = awi_ioctl;
  284         ifp->if_start = awi_start;
  285         ifp->if_watchdog = awi_watchdog;
  286 #ifdef __NetBSD__
  287         ifp->if_init = awi_init;
  288         ifp->if_stop = awi_stop;
  289         IFQ_SET_READY(&ifp->if_snd);
  290         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
  291 #endif
  292 #ifdef __FreeBSD__
  293         ifp->if_init = awi_init0;
  294         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  295         if_initname(ifp, device_get_name(sc->sc_dev),
  296             device_get_unit(sc->sc_dev));
  297 #endif
  298 
  299         ic->ic_ifp = ifp;
  300         ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP;
  301         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
  302                 ic->ic_phytype = IEEE80211_T_FH;
  303                 mode = IEEE80211_MODE_FH;
  304         } else {
  305                 ic->ic_phytype = IEEE80211_T_DS;
  306                 ic->ic_caps |= IEEE80211_C_AHDEMO;
  307                 mode = IEEE80211_MODE_11B;
  308         }
  309         ic->ic_opmode = IEEE80211_M_STA;
  310         nrate = sc->sc_mib_phy.aSuprt_Data_Rates[1];
  311         memcpy(ic->ic_sup_rates[mode].rs_rates,
  312             sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate);
  313         ic->ic_sup_rates[mode].rs_nrates = nrate;
  314         IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address);
  315 
  316         printf("%s: IEEE802.11 %s (firmware %s)\n", ifp->if_xname,
  317             (ic->ic_phytype == IEEE80211_T_FH) ? "FH" : "DS", sc->sc_banner);
  318         printf("%s: 802.11 address: %s\n", ifp->if_xname,
  319             ether_sprintf(ic->ic_myaddr));
  320 
  321 #ifdef __NetBSD__
  322         if_attach(ifp);
  323 #endif
  324         ieee80211_ifattach(ic);
  325 
  326         sc->sc_newstate = ic->ic_newstate;
  327         ic->ic_newstate = awi_newstate;
  328 
  329         sc->sc_recv_mgmt = ic->ic_recv_mgmt;
  330         ic->ic_recv_mgmt = awi_recv_mgmt;
  331 
  332         sc->sc_send_mgmt = ic->ic_send_mgmt;
  333         ic->ic_send_mgmt = awi_send_mgmt;
  334 
  335         ieee80211_media_init(ic, awi_media_change, awi_media_status);
  336 
  337         /* Melco compatibility mode. */
  338 #define ADD(s, o)       ifmedia_add(&ic->ic_media, \
  339         IFM_MAKEWORD(IFM_IEEE80211, (s), (o), 0), 0, NULL)
  340         ADD(IFM_AUTO, IFM_FLAG0);
  341 
  342         for (i = 0; i < nrate; i++) {
  343                 mword = ieee80211_rate2media(ic,
  344                     ic->ic_sup_rates[mode].rs_rates[i], mode);
  345                 if (mword == 0)
  346                         continue;
  347                 ADD(mword, IFM_FLAG0);
  348         }
  349 #undef  ADD
  350 
  351 #ifdef __NetBSD__
  352         if ((sc->sc_sdhook = shutdownhook_establish(awi_shutdown, sc)) == NULL)
  353                 printf("%s: WARNING: unable to establish shutdown hook\n",
  354                     ifp->if_xname);
  355         if ((sc->sc_powerhook =
  356              powerhook_establish(ifp->if_xname, 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 ieee80211com *ic = &sc->sc_ic;
  373         struct ifnet *ifp = &sc->sc_if;
  374         int s;
  375 
  376         if (!sc->sc_attached)
  377                 return 0;
  378 
  379         s = splnet();
  380         sc->sc_invalid = 1;
  381         awi_stop(ifp, 1);
  382 
  383         while (sc->sc_sleep_cnt > 0) {
  384                 wakeup(sc);
  385                 (void)tsleep(sc, PWAIT, "awidet", 1);
  386         }
  387         sc->sc_attached = 0;
  388         ieee80211_ifdetach(ic);
  389 #ifdef __NetBSD__
  390         if_detach(ifp);
  391         shutdownhook_disestablish(sc->sc_sdhook);
  392         powerhook_disestablish(sc->sc_powerhook);
  393 #endif
  394         splx(s);
  395         return 0;
  396 }
  397 
  398 #ifdef __NetBSD__
  399 int
  400 awi_activate(struct device *self, enum devact act)
  401 {
  402         struct awi_softc *sc = (struct awi_softc *)self;
  403         struct ifnet *ifp = &sc->sc_if;
  404         int s, error = 0;
  405 
  406         s = splnet();
  407         switch (act) {
  408         case DVACT_ACTIVATE:
  409                 error = EOPNOTSUPP;
  410                 break;
  411         case DVACT_DEACTIVATE:
  412                 sc->sc_invalid = 1;
  413                 if_deactivate(ifp);
  414                 break;
  415         }
  416         splx(s);
  417         return error;
  418 }
  419 
  420 void
  421 awi_power(int why, void *arg)
  422 {
  423         struct awi_softc *sc = arg;
  424         struct ifnet *ifp = &sc->sc_if;
  425         int s;
  426         int ocansleep;
  427 
  428         DPRINTF(("awi_power: %d\n", why));
  429         s = splnet();
  430         ocansleep = sc->sc_cansleep;
  431         sc->sc_cansleep = 0;
  432         switch (why) {
  433         case PWR_SUSPEND:
  434         case PWR_STANDBY:
  435                 awi_stop(ifp, 1);
  436                 break;
  437         case PWR_RESUME:
  438                 if (ifp->if_flags & IFF_UP) {
  439                         awi_init(ifp);
  440                         (void)awi_intr(sc);     /* make sure */
  441                 }
  442                 break;
  443         case PWR_SOFTSUSPEND:
  444         case PWR_SOFTSTANDBY:
  445         case PWR_SOFTRESUME:
  446                 break;
  447         }
  448         sc->sc_cansleep = ocansleep;
  449         splx(s);
  450 }
  451 #endif /* __NetBSD__ */
  452 
  453 void
  454 awi_shutdown(void *arg)
  455 {
  456         struct awi_softc *sc = arg;
  457         struct ifnet *ifp = &sc->sc_if;
  458 
  459         if (sc->sc_attached)
  460                 awi_stop(ifp, 1);
  461 }
  462 
  463 int
  464 awi_intr(void *arg)
  465 {
  466         struct awi_softc *sc = arg;
  467         u_int16_t status;
  468         int handled = 0, ocansleep;
  469 #ifdef AWI_DEBUG
  470         static const char *intname[] = {
  471             "CMD", "RX", "TX", "SCAN_CMPLT",
  472             "CFP_START", "DTIM", "CFP_ENDING", "GROGGY",
  473             "TXDATA", "TXBCAST", "TXPS", "TXCF",
  474             "TXMGT", "#13", "RXDATA", "RXMGT"
  475         };
  476 #endif
  477 
  478         if (!sc->sc_enabled || !sc->sc_enab_intr || sc->sc_invalid) {
  479                 DPRINTF(("awi_intr: stray interrupt: "
  480                     "enabled %d enab_intr %d invalid %d\n",
  481                     sc->sc_enabled, sc->sc_enab_intr, sc->sc_invalid));
  482                 return 0;
  483         }
  484 
  485         am79c930_gcr_setbits(&sc->sc_chip,
  486             AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT);
  487         awi_write_1(sc, AWI_DIS_PWRDN, 1);
  488         ocansleep = sc->sc_cansleep;
  489         sc->sc_cansleep = 0;
  490 
  491         for (;;) {
  492                 if (awi_intr_lock(sc) != 0)
  493                         break;
  494                 status = awi_read_1(sc, AWI_INTSTAT);
  495                 awi_write_1(sc, AWI_INTSTAT, 0);
  496                 awi_write_1(sc, AWI_INTSTAT, 0);
  497                 status |= awi_read_1(sc, AWI_INTSTAT2) << 8;
  498                 awi_write_1(sc, AWI_INTSTAT2, 0);
  499                 DELAY(10);
  500                 awi_intr_unlock(sc);
  501                 if (!sc->sc_cmd_inprog)
  502                         status &= ~AWI_INT_CMD; /* make sure */
  503                 if (status == 0)
  504                         break;
  505 #ifdef AWI_DEBUG
  506                 if (awi_debug > 1) {
  507                         int i;
  508 
  509                         printf("awi_intr: status 0x%04x", status);
  510                         for (i = 0; i < sizeof(intname)/sizeof(intname[0]);
  511                             i++) {
  512                                 if (status & (1 << i))
  513                                         printf(" %s", intname[i]);
  514                         }
  515                         printf("\n");
  516                 }
  517 #endif
  518                 handled = 1;
  519                 if (status & AWI_INT_RX)
  520                         awi_rx_int(sc);
  521                 if (status & AWI_INT_TX)
  522                         awi_tx_int(sc);
  523                 if (status & AWI_INT_CMD)
  524                         awi_cmd_done(sc);
  525                 if (status & AWI_INT_SCAN_CMPLT) {
  526                         if (sc->sc_ic.ic_state == IEEE80211_S_SCAN &&
  527                             sc->sc_substate == AWI_ST_NONE)
  528                                 ieee80211_next_scan(&sc->sc_ic);
  529                 }
  530         }
  531         sc->sc_cansleep = ocansleep;
  532         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
  533         awi_write_1(sc, AWI_DIS_PWRDN, 0);
  534         return handled;
  535 }
  536 
  537 #ifdef __FreeBSD__
  538 static void
  539 awi_init0(void *arg)
  540 {
  541         struct awi_softc *sc = arg;
  542 
  543         (void)awi_init(&sc->sc_if);
  544 }
  545 #endif
  546 
  547 static int
  548 awi_init(struct ifnet *ifp)
  549 {
  550         struct awi_softc *sc = ifp->if_softc;
  551         struct ieee80211com *ic = &sc->sc_ic;
  552         struct ieee80211_node *ni = ic->ic_bss;
  553         struct ieee80211_rateset *rs;
  554         int error, rate, i;
  555 
  556         DPRINTF(("awi_init: enabled=%d\n", sc->sc_enabled));
  557         if (sc->sc_enabled) {
  558                 awi_stop(ifp, 0);
  559         } else {
  560                 if (sc->sc_enable)
  561                         (*sc->sc_enable)(sc);
  562                 sc->sc_enabled = 1;
  563                 if ((error = awi_hw_init(sc)) != 0) {
  564                         if (sc->sc_disable)
  565                                 (*sc->sc_disable)(sc);
  566                         sc->sc_enabled = 0;
  567                         return error;
  568                 }
  569         }
  570         ic->ic_state = IEEE80211_S_INIT;
  571 
  572         ic->ic_flags &= ~IEEE80211_F_IBSSON;
  573         switch (ic->ic_opmode) {
  574         case IEEE80211_M_STA:
  575                 sc->sc_mib_local.Network_Mode = 1;
  576                 sc->sc_mib_local.Acting_as_AP = 0;
  577                 break;
  578         case IEEE80211_M_IBSS:
  579                 ic->ic_flags |= IEEE80211_F_IBSSON;
  580                 /* FALLTHRU */
  581         case IEEE80211_M_AHDEMO:
  582                 sc->sc_mib_local.Network_Mode = 0;
  583                 sc->sc_mib_local.Acting_as_AP = 0;
  584                 break;
  585         case IEEE80211_M_HOSTAP:
  586                 sc->sc_mib_local.Network_Mode = 1;
  587                 sc->sc_mib_local.Acting_as_AP = 1;
  588                 break;
  589         case IEEE80211_M_MONITOR:
  590                 return ENODEV;
  591         }
  592 #if 0
  593         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
  594 #endif
  595         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
  596         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
  597         sc->sc_mib_mac.aDesired_ESS_ID[1] = ic->ic_des_esslen;
  598         memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], ic->ic_des_essid,
  599             ic->ic_des_esslen);
  600 
  601         /* configure basic rate */
  602         if (ic->ic_phytype == IEEE80211_T_FH)
  603                 rs = &ic->ic_sup_rates[IEEE80211_MODE_FH];
  604         else
  605                 rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
  606         if (ic->ic_fixed_rate != -1) {
  607                 rate = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
  608         } else {
  609                 rate = 0;
  610                 for (i = 0; i < rs->rs_nrates; i++) {
  611                         if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
  612                             rate < (rs->rs_rates[i] & IEEE80211_RATE_VAL))
  613                                 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
  614                 }
  615         }
  616         rate *= 5;
  617         LE_WRITE_2(&sc->sc_mib_mac.aStation_Basic_Rate, rate);
  618 
  619         if ((error = awi_mode_init(sc)) != 0) {
  620                 DPRINTF(("awi_init: awi_mode_init failed %d\n", error));
  621                 awi_stop(ifp, 1);
  622                 return error;
  623         }
  624 
  625         /* start transmitter */
  626         sc->sc_txdone = sc->sc_txnext = sc->sc_txbase;
  627         awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0);
  628         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0);
  629         awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0);
  630         awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0);
  631         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0);
  632         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0);
  633         awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0);
  634         awi_write_4(sc, AWI_CA_TX_DATA, sc->sc_txbase);
  635         awi_write_4(sc, AWI_CA_TX_MGT, 0);
  636         awi_write_4(sc, AWI_CA_TX_BCAST, 0);
  637         awi_write_4(sc, AWI_CA_TX_PS, 0);
  638         awi_write_4(sc, AWI_CA_TX_CF, 0);
  639         if ((error = awi_cmd(sc, AWI_CMD_INIT_TX, AWI_WAIT)) != 0) {
  640                 DPRINTF(("awi_init: failed to start transmitter: %d\n", error));
  641                 awi_stop(ifp, 1);
  642                 return error;
  643         }
  644 
  645         /* start receiver */
  646         if ((error = awi_cmd(sc, AWI_CMD_INIT_RX, AWI_WAIT)) != 0) {
  647                 DPRINTF(("awi_init: failed to start receiver: %d\n", error));
  648                 awi_stop(ifp, 1);
  649                 return error;
  650         }
  651         sc->sc_rxdoff = awi_read_4(sc, AWI_CA_IRX_DATA_DESC);
  652         sc->sc_rxmoff = awi_read_4(sc, AWI_CA_IRX_PS_DESC);
  653 
  654         ifp->if_flags |= IFF_RUNNING;
  655         ifp->if_flags &= ~IFF_OACTIVE;
  656         ic->ic_state = IEEE80211_S_INIT;
  657 
  658         if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
  659             ic->ic_opmode == IEEE80211_M_HOSTAP) {
  660                 ni->ni_chan = ic->ic_ibss_chan;
  661                 ni->ni_intval = ic->ic_lintval;
  662                 ni->ni_rssi = 0;
  663                 ni->ni_rstamp = 0;
  664                 memset(&ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
  665                 ni->ni_rates =
  666                     ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
  667                 IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
  668                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
  669                         IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
  670                         ni->ni_esslen = ic->ic_des_esslen;
  671                         memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
  672                         ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
  673                         if (ic->ic_phytype == IEEE80211_T_FH) {
  674                                 ni->ni_fhdwell = 200;   /* XXX */
  675                                 ni->ni_fhindex = 1;
  676                         }
  677                 } else {
  678                         ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
  679                         memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
  680                         ni->ni_esslen = 0;
  681                 }
  682                 if (ic->ic_flags & IEEE80211_F_PRIVACY)
  683                         ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
  684                 if (ic->ic_opmode != IEEE80211_M_AHDEMO)
  685                         ic->ic_flags |= IEEE80211_F_SIBSS;
  686                 ic->ic_state = IEEE80211_S_SCAN;        /*XXX*/
  687                 sc->sc_substate = AWI_ST_NONE;
  688                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
  689         } else {
  690                 /* XXX check sc->sc_cur_chan */
  691                 ni->ni_chan = &ic->ic_channels[sc->sc_cur_chan];
  692                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  693         }
  694         return 0;
  695 }
  696 
  697 static void
  698 awi_stop(struct ifnet *ifp, int disable)
  699 {
  700         struct awi_softc *sc = ifp->if_softc;
  701 
  702         if (!sc->sc_enabled)
  703                 return;
  704 
  705         DPRINTF(("awi_stop(%d)\n", disable));
  706 
  707         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
  708 
  709         if (!sc->sc_invalid) {
  710                 if (sc->sc_cmd_inprog)
  711                         (void)awi_cmd_wait(sc);
  712                 (void)awi_cmd(sc, AWI_CMD_KILL_RX, AWI_WAIT);
  713                 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX;
  714                 awi_write_1(sc, AWI_CA_FTX_DATA, 1);
  715                 awi_write_1(sc, AWI_CA_FTX_MGT, 0);
  716                 awi_write_1(sc, AWI_CA_FTX_BCAST, 0);
  717                 awi_write_1(sc, AWI_CA_FTX_PS, 0);
  718                 awi_write_1(sc, AWI_CA_FTX_CF, 0);
  719                 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX, AWI_WAIT);
  720         }
  721         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
  722         ifp->if_timer = 0;
  723         sc->sc_tx_timer = sc->sc_rx_timer = 0;
  724         if (sc->sc_rxpend != NULL) {
  725                 m_freem(sc->sc_rxpend);
  726                 sc->sc_rxpend = NULL;
  727         }
  728         IFQ_PURGE(&ifp->if_snd);
  729 
  730         if (disable) {
  731                 if (!sc->sc_invalid)
  732                         am79c930_gcr_setbits(&sc->sc_chip,
  733                             AM79C930_GCR_CORESET);
  734                 if (sc->sc_disable)
  735                         (*sc->sc_disable)(sc);
  736                 sc->sc_enabled = 0;
  737         }
  738 }
  739 
  740 static void
  741 awi_start(struct ifnet *ifp)
  742 {
  743         struct awi_softc *sc = ifp->if_softc;
  744         struct ieee80211com *ic = &sc->sc_ic;
  745         struct ether_header *eh;
  746         struct ieee80211_node *ni;
  747         struct ieee80211_frame *wh;
  748         struct mbuf *m, *m0;
  749         int len, dowep;
  750         u_int32_t txd, frame, ntxd;
  751         u_int8_t rate;
  752 
  753         if (!sc->sc_enabled || sc->sc_invalid)
  754                 return;
  755 
  756         for (;;) {
  757                 txd = sc->sc_txnext;
  758                 IF_POLL(&ic->ic_mgtq, m0);
  759                 dowep = 0;
  760                 if (m0 != NULL) {
  761                         len = m0->m_pkthdr.len;
  762                         if (awi_next_txd(sc, len, &frame, &ntxd)) {
  763                                 ifp->if_flags |= IFF_OACTIVE;
  764                                 break;
  765                         }
  766                         IF_DEQUEUE(&ic->ic_mgtq, m0);
  767                         ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
  768                 } else {
  769                         if (ic->ic_state != IEEE80211_S_RUN)
  770                                 break;
  771                         IFQ_POLL(&ifp->if_snd, m0);
  772                         if (m0 == NULL)
  773                                 break;
  774                         /*
  775                          * Need to calculate the real length to determine
  776                          * if the transmit buffer has a room for the packet.
  777                          */
  778                         len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
  779                         if (!(ifp->if_flags & IFF_LINK0) && !sc->sc_adhoc_ap)
  780                                 len += sizeof(struct llc) -
  781                                     sizeof(struct ether_header);
  782                         if (ic->ic_flags & IEEE80211_F_PRIVACY) {
  783                                 dowep = 1;
  784                                 len += IEEE80211_WEP_IVLEN +
  785                                     IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
  786                         }
  787                         if (awi_next_txd(sc, len, &frame, &ntxd)) {
  788                                 ifp->if_flags |= IFF_OACTIVE;
  789                                 break;
  790                         }
  791                         IFQ_DEQUEUE(&ifp->if_snd, m0);
  792                         ifp->if_opackets++;
  793 #if NBPFILTER > 0
  794                         if (ifp->if_bpf)
  795                                 bpf_mtap(ifp->if_bpf, m0);
  796 #endif
  797                         eh = mtod(m0, struct ether_header *);
  798                         ni = ieee80211_find_txnode(ic, eh->ether_dhost);
  799                         if (ni == NULL) {
  800                                 ifp->if_oerrors++;
  801                                 continue;
  802                         }
  803                         if ((ifp->if_flags & IFF_LINK0) || sc->sc_adhoc_ap)
  804                                 m0 = awi_ether_encap(sc, m0);
  805                         else {
  806                                 m0 = ieee80211_encap(ic, m0, ni);
  807                         }
  808                         if (m0 == NULL) {
  809                                 ieee80211_free_node(ni);
  810                                 ifp->if_oerrors++;
  811                                 continue;
  812                         }
  813                         wh = mtod(m0, struct ieee80211_frame *);
  814                         if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
  815                             (ic->ic_opmode == IEEE80211_M_HOSTAP ||
  816                              ic->ic_opmode == IEEE80211_M_IBSS) &&
  817                             sc->sc_adhoc_ap == 0 &&
  818                             (ifp->if_flags & IFF_LINK0) == 0 &&
  819                             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
  820                             IEEE80211_FC0_TYPE_DATA) {
  821                                 m_freem(m0);
  822                                 ieee80211_free_node(ni);
  823                                 ifp->if_oerrors++;
  824                                 continue;
  825                         }
  826                 }
  827 #if NBPFILTER > 0
  828                 if (ic->ic_rawbpf)
  829                         bpf_mtap(ic->ic_rawbpf, m0);
  830 #endif
  831                 if (dowep) {
  832                         if ((ieee80211_crypto_encap(ic, ni, m0)) == NULL) {
  833                                 m_freem(m0);
  834                                 ieee80211_free_node(ni);
  835                                 ifp->if_oerrors++;
  836                                 continue;
  837                         }
  838                 }
  839                 ieee80211_free_node(ni);
  840 #ifdef DIAGNOSTIC
  841                 if (m0->m_pkthdr.len != len) {
  842                         printf("%s: length %d should be %d\n",
  843                             sc->sc_if.if_xname, m0->m_pkthdr.len, len);
  844                         m_freem(m0);
  845                         ifp->if_oerrors++;
  846                         continue;
  847                 }
  848 #endif
  849 
  850                 if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2))
  851                         ieee80211_dump_pkt(m0->m_data, m0->m_len,
  852                             ic->ic_bss->ni_rates.
  853                                 rs_rates[ic->ic_bss->ni_txrate] &
  854                             IEEE80211_RATE_VAL, -1);
  855 
  856                 for (m = m0, len = 0; m != NULL; m = m->m_next) {
  857                         awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *),
  858                             m->m_len);
  859                         len += m->m_len;
  860                 }
  861                 m_freem(m0);
  862                 rate = (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
  863                     IEEE80211_RATE_VAL) * 5;
  864                 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0);
  865                 awi_write_4(sc, txd + AWI_TXD_START, frame);
  866                 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd);
  867                 awi_write_4(sc, txd + AWI_TXD_LENGTH, len);
  868                 awi_write_1(sc, txd + AWI_TXD_RATE, rate);
  869                 awi_write_4(sc, txd + AWI_TXD_NDA, 0);
  870                 awi_write_4(sc, txd + AWI_TXD_NRA, 0);
  871                 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN);
  872                 sc->sc_txnext = ntxd;
  873 
  874                 sc->sc_tx_timer = 5;
  875                 ifp->if_timer = 1;
  876         }
  877 }
  878 
  879 static void
  880 awi_watchdog(struct ifnet *ifp)
  881 {
  882         struct awi_softc *sc = ifp->if_softc;
  883         u_int32_t prevdone;
  884         int ocansleep;
  885 
  886         ifp->if_timer = 0;
  887         if (!sc->sc_enabled || sc->sc_invalid)
  888                 return;
  889 
  890         ocansleep = sc->sc_cansleep;
  891         sc->sc_cansleep = 0;
  892         if (sc->sc_tx_timer) {
  893                 if (--sc->sc_tx_timer == 0) {
  894                         printf("%s: device timeout\n", ifp->if_xname);
  895                         prevdone = sc->sc_txdone;
  896                         awi_tx_int(sc);
  897                         if (sc->sc_txdone == prevdone) {
  898                                 ifp->if_oerrors++;
  899                                 awi_init(ifp);
  900                                 goto out;
  901                         }
  902                 }
  903                 ifp->if_timer = 1;
  904         }
  905         if (sc->sc_rx_timer) {
  906                 if (--sc->sc_rx_timer == 0) {
  907                         if (sc->sc_ic.ic_state == IEEE80211_S_RUN) {
  908                                 ieee80211_new_state(&sc->sc_ic,
  909                                     IEEE80211_S_SCAN, -1);
  910                                 goto out;
  911                         }
  912                 } else
  913                         ifp->if_timer = 1;
  914         }
  915         /* TODO: rate control */
  916         ieee80211_watchdog(&sc->sc_ic);
  917   out:
  918         sc->sc_cansleep = ocansleep;
  919 }
  920 
  921 static int
  922 awi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  923 {
  924         struct awi_softc *sc = ifp->if_softc;
  925         struct ifreq *ifr = (struct ifreq *)data;
  926         int s, error;
  927 
  928         s = splnet();
  929         /* serialize ioctl, since we may sleep */
  930         if ((error = awi_lock(sc)) != 0)
  931                 goto cantlock;
  932 
  933         switch (cmd) {
  934         case SIOCSIFFLAGS:
  935                 if (ifp->if_flags & IFF_UP) {
  936                         if (sc->sc_enabled) {
  937                                 /*
  938                                  * To avoid rescanning another access point,
  939                                  * do not call awi_init() here.  Instead,
  940                                  * only reflect promisc mode settings.
  941                                  */
  942                                 error = awi_mode_init(sc);
  943                         } else
  944                                 error = awi_init(ifp);
  945                 } else if (sc->sc_enabled)
  946                         awi_stop(ifp, 1);
  947                 break;
  948         case SIOCSIFMEDIA:
  949         case SIOCGIFMEDIA:
  950                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ic.ic_media, cmd);
  951                 break;
  952         case SIOCADDMULTI:
  953         case SIOCDELMULTI:
  954 #ifdef __FreeBSD__
  955                 error = ENETRESET;      /* XXX */
  956 #else
  957                 error = (cmd == SIOCADDMULTI) ?
  958                     ether_addmulti(ifr, &sc->sc_ec) :
  959                     ether_delmulti(ifr, &sc->sc_ec);
  960 #endif
  961                 if (error == ENETRESET) {
  962                         /* do not rescan */
  963                         if (ifp->if_flags & IFF_RUNNING)
  964                                 error = awi_mode_init(sc);
  965                         else
  966                                 error = 0;
  967                 }
  968                 break;
  969         default:
  970                 error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
  971                 if (error == ENETRESET) {
  972                         if (sc->sc_enabled)
  973                                 error = awi_init(ifp);
  974                         else
  975                                 error = 0;
  976                 }
  977                 break;
  978         }
  979         awi_unlock(sc);
  980   cantlock:
  981         splx(s);
  982         return error;
  983 }
  984 
  985 /*
  986  * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
  987  *
  988  * TBD factor with ieee80211_media_change
  989  */
  990 static int
  991 awi_media_change(struct ifnet *ifp)
  992 {
  993         struct awi_softc *sc = ifp->if_softc;
  994         struct ieee80211com *ic = &sc->sc_ic;
  995         struct ifmedia_entry *ime;
  996         enum ieee80211_opmode newmode;
  997         int i, rate, newadhoc_ap, error = 0;
  998 
  999         ime = ic->ic_media.ifm_cur;
 1000         if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) {
 1001                 i = -1;
 1002         } else {
 1003                 struct ieee80211_rateset *rs =
 1004                     &ic->ic_sup_rates[(ic->ic_phytype == IEEE80211_T_FH)
 1005                     ? IEEE80211_MODE_FH : IEEE80211_MODE_11B];
 1006                 rate = ieee80211_media2rate(ime->ifm_media);
 1007                 if (rate == 0)
 1008                         return EINVAL;
 1009                 for (i = 0; i < rs->rs_nrates; i++) {
 1010                         if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate)
 1011                                 break;
 1012                 }
 1013                 if (i == rs->rs_nrates)
 1014                         return EINVAL;
 1015         }
 1016         if (ic->ic_fixed_rate != i) {
 1017                 ic->ic_fixed_rate = i;
 1018                 error = ENETRESET;
 1019         }
 1020 
 1021         /*
 1022          * combination of mediaopt
 1023          *
 1024          * hostap adhoc flag0   opmode  adhoc_ap        comment
 1025          *   +      -     -     HOSTAP      0           HostAP
 1026          *   -      +     -     IBSS        0           IBSS
 1027          *   -      +     +     AHDEMO      0           WaveLAN adhoc
 1028          *   -      -     +     IBSS        1           Melco old Sta
 1029          *                                                      also LINK0
 1030          *   -      -     -     STA         0           Infra Station
 1031          */
 1032         newadhoc_ap = 0;
 1033         if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
 1034                 newmode = IEEE80211_M_HOSTAP;
 1035         else if (ime->ifm_media & IFM_IEEE80211_ADHOC) {
 1036                 if (ic->ic_phytype == IEEE80211_T_DS &&
 1037                     (ime->ifm_media & IFM_FLAG0))
 1038                         newmode = IEEE80211_M_AHDEMO;
 1039                 else
 1040                         newmode = IEEE80211_M_IBSS;
 1041         } else if (ime->ifm_media & IFM_FLAG0) {
 1042                 newmode = IEEE80211_M_IBSS;
 1043                 newadhoc_ap = 1;
 1044         } else
 1045                 newmode = IEEE80211_M_STA;
 1046         if (ic->ic_opmode != newmode || sc->sc_adhoc_ap != newadhoc_ap) {
 1047                 ic->ic_opmode = newmode;
 1048                 sc->sc_adhoc_ap = newadhoc_ap;
 1049                 error = ENETRESET;
 1050         }
 1051 
 1052         if (error == ENETRESET) {
 1053                 if (sc->sc_enabled)
 1054                         error = awi_init(ifp);
 1055                 else
 1056                         error = 0;
 1057         }
 1058         return error;
 1059 }
 1060 
 1061 static void
 1062 awi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 1063 {
 1064         struct awi_softc *sc = ifp->if_softc;
 1065         struct ieee80211com *ic = &sc->sc_ic;
 1066         int rate;
 1067         enum ieee80211_phymode mode;
 1068 
 1069         imr->ifm_status = IFM_AVALID;
 1070         if (ic->ic_state == IEEE80211_S_RUN)
 1071                 imr->ifm_status |= IFM_ACTIVE;
 1072         imr->ifm_active = IFM_IEEE80211;
 1073         if (ic->ic_phytype == IEEE80211_T_FH)
 1074                 mode = IEEE80211_MODE_FH;
 1075         else
 1076                 mode = IEEE80211_MODE_11B;
 1077         if (ic->ic_state == IEEE80211_S_RUN) {
 1078                 rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] &
 1079                     IEEE80211_RATE_VAL;
 1080         } else {
 1081                 if (ic->ic_fixed_rate == -1)
 1082                         rate = 0;
 1083                 else
 1084                         rate = ic->ic_sup_rates[mode].
 1085                             rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 1086         }
 1087         imr->ifm_active |= ieee80211_rate2media(ic, rate, mode);
 1088         switch (ic->ic_opmode) {
 1089         case IEEE80211_M_MONITOR: /* we should never reach here */
 1090                 break;
 1091         case IEEE80211_M_STA:
 1092                 break;
 1093         case IEEE80211_M_IBSS:
 1094                 if (sc->sc_adhoc_ap)
 1095                         imr->ifm_active |= IFM_FLAG0;
 1096                 else
 1097                         imr->ifm_active |= IFM_IEEE80211_ADHOC;
 1098                 break;
 1099         case IEEE80211_M_AHDEMO:
 1100                 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
 1101                 break;
 1102         case IEEE80211_M_HOSTAP:
 1103                 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
 1104                 break;
 1105         }
 1106 }
 1107 
 1108 static int
 1109 awi_mode_init(struct awi_softc *sc)
 1110 {
 1111         struct ifnet *ifp = &sc->sc_if;
 1112         int n, error;
 1113 #ifdef __FreeBSD__
 1114         struct ifmultiaddr *ifma;
 1115 #else
 1116         struct ether_multi *enm;
 1117         struct ether_multistep step;
 1118 #endif
 1119 
 1120         /* reinitialize muticast filter */
 1121         n = 0;
 1122         sc->sc_mib_local.Accept_All_Multicast_Dis = 0;
 1123         if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP &&
 1124             (ifp->if_flags & IFF_PROMISC)) {
 1125                 sc->sc_mib_mac.aPromiscuous_Enable = 1;
 1126                 goto set_mib;
 1127         }
 1128         sc->sc_mib_mac.aPromiscuous_Enable = 0;
 1129 #ifdef __FreeBSD__
 1130         if (ifp->if_amcount != 0)
 1131                 goto set_mib;
 1132         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1133                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1134                         continue;
 1135                 if (n == AWI_GROUP_ADDR_SIZE)
 1136                         goto set_mib;
 1137                 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
 1138                     LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 1139                 n++;
 1140         }
 1141 #else
 1142         ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
 1143         while (enm != NULL) {
 1144                 if (n == AWI_GROUP_ADDR_SIZE ||
 1145                     !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi))
 1146                         goto set_mib;
 1147                 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
 1148                     enm->enm_addrlo);
 1149                 n++;
 1150                 ETHER_NEXT_MULTI(step, enm);
 1151         }
 1152 #endif
 1153         for (; n < AWI_GROUP_ADDR_SIZE; n++)
 1154                 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0,
 1155                     IEEE80211_ADDR_LEN);
 1156         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
 1157 
 1158   set_mib:
 1159         if (sc->sc_mib_local.Accept_All_Multicast_Dis)
 1160                 ifp->if_flags &= ~IFF_ALLMULTI;
 1161         else
 1162                 ifp->if_flags |= IFF_ALLMULTI;
 1163         sc->sc_mib_mgt.Wep_Required =
 1164             (sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) ? AWI_WEP_ON : AWI_WEP_OFF;
 1165 
 1166         if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
 1167             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
 1168             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
 1169             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
 1170             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
 1171                 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error));
 1172                 return error;
 1173         }
 1174         return 0;
 1175 }
 1176 
 1177 static void
 1178 awi_rx_int(struct awi_softc *sc)
 1179 {
 1180         struct ieee80211com *ic = &sc->sc_ic;
 1181         struct ifnet *ifp = &sc->sc_if;
 1182         struct ieee80211_frame_min *wh;
 1183         struct ieee80211_node *ni;
 1184         u_int8_t state, rate, rssi;
 1185         u_int16_t len;
 1186         u_int32_t frame, next, rstamp, rxoff;
 1187         struct mbuf *m;
 1188 
 1189         rxoff = sc->sc_rxdoff;
 1190         for (;;) {
 1191                 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE);
 1192                 if (state & AWI_RXD_ST_OWN)
 1193                         break;
 1194                 if (!(state & AWI_RXD_ST_CONSUMED)) {
 1195                         if (sc->sc_substate != AWI_ST_NONE)
 1196                                 goto rx_next;
 1197                         if (state & AWI_RXD_ST_RXERROR) {
 1198                                 ifp->if_ierrors++;
 1199                                 goto rx_next;
 1200                         }
 1201                         len    = awi_read_2(sc, rxoff + AWI_RXD_LEN);
 1202                         rate   = awi_read_1(sc, rxoff + AWI_RXD_RATE);
 1203                         rssi   = awi_read_1(sc, rxoff + AWI_RXD_RSSI);
 1204                         frame  = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) &
 1205                             0x7fff;
 1206                         rstamp = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME);
 1207                         m = awi_devget(sc, frame, len);
 1208                         if (m == NULL) {
 1209                                 ifp->if_ierrors++;
 1210                                 goto rx_next;
 1211                         }
 1212                         if (state & AWI_RXD_ST_LF) {
 1213                                 /* TODO check my bss */
 1214                                 if (!(sc->sc_ic.ic_flags & IEEE80211_F_SIBSS) &&
 1215                                     sc->sc_ic.ic_state == IEEE80211_S_RUN) {
 1216                                         sc->sc_rx_timer = 10;
 1217                                         ifp->if_timer = 1;
 1218                                 }
 1219                                 if ((ifp->if_flags & IFF_DEBUG) &&
 1220                                     (ifp->if_flags & IFF_LINK2))
 1221                                         ieee80211_dump_pkt(m->m_data, m->m_len,
 1222                                             rate / 5, rssi);
 1223                                 if ((ifp->if_flags & IFF_LINK0) ||
 1224                                     sc->sc_adhoc_ap)
 1225                                         m = awi_ether_modcap(sc, m);
 1226                                 else
 1227                                         m = m_pullup(m, sizeof(*wh));
 1228                                 if (m == NULL) {
 1229                                         ifp->if_ierrors++;
 1230                                         goto rx_next;
 1231                                 }
 1232                                 wh = mtod(m, struct ieee80211_frame_min *);
 1233                                 ni = ieee80211_find_rxnode(ic, wh);
 1234                                 ieee80211_input(ic, m, ni, rssi, rstamp);
 1235                                 /*
 1236                                  * The frame may have caused the
 1237                                  * node to be marked for reclamation
 1238                                  * (e.g. in response to a DEAUTH
 1239                                  * message) so use release_node here
 1240                                  * instead of unref_node.
 1241                                  */
 1242                                 ieee80211_free_node(ni);
 1243                         } else
 1244                                 sc->sc_rxpend = m;
 1245   rx_next:
 1246                         state |= AWI_RXD_ST_CONSUMED;
 1247                         awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1248                 }
 1249                 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT);
 1250                 if (next & AWI_RXD_NEXT_LAST)
 1251                         break;
 1252                 /* make sure the next pointer is correct */
 1253                 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT))
 1254                         break;
 1255                 state |= AWI_RXD_ST_OWN;
 1256                 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1257                 rxoff = next & 0x7fff;
 1258         }
 1259         sc->sc_rxdoff = rxoff;
 1260 }
 1261 
 1262 static void
 1263 awi_tx_int(struct awi_softc *sc)
 1264 {
 1265         struct ifnet *ifp = &sc->sc_if;
 1266         u_int8_t flags;
 1267 
 1268         while (sc->sc_txdone != sc->sc_txnext) {
 1269                 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE);
 1270                 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE))
 1271                         break;
 1272                 if (flags & AWI_TXD_ST_ERROR)
 1273                         ifp->if_oerrors++;
 1274                 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) &
 1275                     0x7fff;
 1276         }
 1277         DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
 1278             sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend));
 1279         sc->sc_tx_timer = 0;
 1280         ifp->if_flags &= ~IFF_OACTIVE;
 1281         awi_start(ifp);
 1282 }
 1283 
 1284 static struct mbuf *
 1285 awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len)
 1286 {
 1287         struct ifnet *ifp = &sc->sc_if;
 1288         struct mbuf *m;
 1289         struct mbuf *top, **mp;
 1290         u_int tlen;
 1291 
 1292         top = sc->sc_rxpend;
 1293         mp = &top;
 1294         if (top != NULL) {
 1295                 sc->sc_rxpend = NULL;
 1296                 top->m_pkthdr.len += len;
 1297                 m = top;
 1298                 while (*mp != NULL) {
 1299                         m = *mp;
 1300                         mp = &m->m_next;
 1301                 }
 1302                 if (m->m_flags & M_EXT)
 1303                         tlen = m->m_ext.ext_size;
 1304                 else if (m->m_flags & M_PKTHDR)
 1305                         tlen = MHLEN;
 1306                 else
 1307                         tlen = MLEN;
 1308                 tlen -= m->m_len;
 1309                 if (tlen > len)
 1310                         tlen = len;
 1311                 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen);
 1312                 off += tlen;
 1313                 len -= tlen;
 1314         }
 1315 
 1316         while (len > 0) {
 1317                 if (top == NULL) {
 1318                         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1319                         if (m == NULL)
 1320                                 return NULL;
 1321                         m->m_pkthdr.rcvif = ifp;
 1322                         m->m_pkthdr.len = len;
 1323                         m->m_len = MHLEN;
 1324                         m->m_flags |= M_HASFCS;
 1325                 } else {
 1326                         MGET(m, M_DONTWAIT, MT_DATA);
 1327                         if (m == NULL) {
 1328                                 m_freem(top);
 1329                                 return NULL;
 1330                         }
 1331                         m->m_len = MLEN;
 1332                 }
 1333                 if (len >= MINCLSIZE) {
 1334                         MCLGET(m, M_DONTWAIT);
 1335                         if (m->m_flags & M_EXT)
 1336                                 m->m_len = m->m_ext.ext_size;
 1337                 }
 1338                 if (top == NULL) {
 1339                         int hdrlen = sizeof(struct ieee80211_frame) +
 1340                             sizeof(struct llc);
 1341                         caddr_t newdata = (caddr_t)
 1342                             ALIGN(m->m_data + hdrlen) - hdrlen;
 1343                         m->m_len -= newdata - m->m_data;
 1344                         m->m_data = newdata;
 1345                 }
 1346                 if (m->m_len > len)
 1347                         m->m_len = len;
 1348                 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len);
 1349                 off += m->m_len;
 1350                 len -= m->m_len;
 1351                 *mp = m;
 1352                 mp = &m->m_next;
 1353         }
 1354         return top;
 1355 }
 1356 
 1357 /*
 1358  * Initialize hardware and start firmware to accept commands.
 1359  * Called everytime after power on firmware.
 1360  */
 1361 
 1362 static int
 1363 awi_hw_init(struct awi_softc *sc)
 1364 {
 1365         u_int8_t status;
 1366         u_int16_t intmask;
 1367         int i, error;
 1368 
 1369         sc->sc_enab_intr = 0;
 1370         sc->sc_invalid = 0;     /* XXX: really? */
 1371         awi_drvstate(sc, AWI_DRV_RESET);
 1372 
 1373         /* reset firmware */
 1374         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1375         DELAY(100);
 1376         awi_write_1(sc, AWI_SELFTEST, 0);
 1377         awi_write_1(sc, AWI_CMD, 0);
 1378         awi_write_1(sc, AWI_BANNER, 0);
 1379         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1380         DELAY(100);
 1381 
 1382         /* wait for selftest completion */
 1383         for (i = 0; ; i++) {
 1384                 if (sc->sc_invalid)
 1385                         return ENXIO;
 1386                 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) {
 1387                         printf("%s: failed to complete selftest (timeout)\n",
 1388                             sc->sc_if.if_xname);
 1389                         return ENXIO;
 1390                 }
 1391                 status = awi_read_1(sc, AWI_SELFTEST);
 1392                 if ((status & 0xf0) == 0xf0)
 1393                         break;
 1394                 if (sc->sc_cansleep) {
 1395                         sc->sc_sleep_cnt++;
 1396                         (void)tsleep(sc, PWAIT, "awitst", 1);
 1397                         sc->sc_sleep_cnt--;
 1398                 } else {
 1399                         DELAY(1000*1000/hz);
 1400                 }
 1401         }
 1402         if (status != AWI_SELFTEST_PASSED) {
 1403                 printf("%s: failed to complete selftest (code %x)\n",
 1404                     sc->sc_if.if_xname, status);
 1405                 return ENXIO;
 1406         }
 1407 
 1408         /* check banner to confirm firmware write it */
 1409         awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
 1410         if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
 1411                 printf("%s: failed to complete selftest (bad banner)\n",
 1412                     sc->sc_if.if_xname);
 1413                 for (i = 0; i < AWI_BANNER_LEN; i++)
 1414                         printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
 1415                 printf("\n");
 1416                 return ENXIO;
 1417         }
 1418 
 1419         /* initializing interrupt */
 1420         sc->sc_enab_intr = 1;
 1421         error = awi_intr_lock(sc);
 1422         if (error)
 1423                 return error;
 1424         intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT |
 1425             AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD;
 1426         awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff);
 1427         awi_write_1(sc, AWI_INTMASK2, 0);
 1428         awi_write_1(sc, AWI_INTSTAT, 0);
 1429         awi_write_1(sc, AWI_INTSTAT2, 0);
 1430         awi_intr_unlock(sc);
 1431         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
 1432 
 1433         /* issuing interface test command */
 1434         error = awi_cmd(sc, AWI_CMD_NOP, AWI_WAIT);
 1435         if (error) {
 1436                 printf("%s: failed to complete selftest",
 1437                     sc->sc_if.if_xname);
 1438                 if (error == ENXIO)
 1439                         printf(" (no hardware)\n");
 1440                 else if (error != EWOULDBLOCK)
 1441                         printf(" (error %d)\n", error);
 1442                 else if (sc->sc_cansleep)
 1443                         printf(" (lost interrupt)\n");
 1444                 else
 1445                         printf(" (command timeout)\n");
 1446                 return error;
 1447         }
 1448 
 1449         /* Initialize VBM */
 1450         awi_write_1(sc, AWI_VBM_OFFSET, 0);
 1451         awi_write_1(sc, AWI_VBM_LENGTH, 1);
 1452         awi_write_1(sc, AWI_VBM_BITMAP, 0);
 1453         return 0;
 1454 }
 1455 
 1456 /*
 1457  * Extract the factory default MIB value from firmware and assign the driver
 1458  * default value.
 1459  * Called once at attaching the interface.
 1460  */
 1461 
 1462 static int
 1463 awi_init_mibs(struct awi_softc *sc)
 1464 {
 1465         int chan, i, error;
 1466         struct ieee80211com *ic = &sc->sc_ic;
 1467         struct awi_chanset *cs;
 1468 
 1469         if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) ||
 1470             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR, AWI_WAIT)) ||
 1471             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC, AWI_WAIT)) ||
 1472             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) ||
 1473             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY, AWI_WAIT))) {
 1474                 printf("%s: failed to get default mib value (error %d)\n",
 1475                     sc->sc_if.if_xname, error);
 1476                 return error;
 1477         }
 1478 
 1479         memset(&sc->sc_ic.ic_chan_avail, 0, sizeof(sc->sc_ic.ic_chan_avail));
 1480         for (cs = awi_chanset; ; cs++) {
 1481                 if (cs->cs_type == 0) {
 1482                         printf("%s: failed to set available channel\n",
 1483                             sc->sc_if.if_xname);
 1484                         return ENXIO;
 1485                 }
 1486                 if (cs->cs_type == sc->sc_mib_phy.IEEE_PHY_Type &&
 1487                     cs->cs_region == sc->sc_mib_phy.aCurrent_Reg_Domain)
 1488                         break;
 1489         }
 1490         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1491                 for (i = cs->cs_min; i <= cs->cs_max; i++) {
 1492                         chan = IEEE80211_FH_CHAN(i % 3 + 1, i);
 1493                         setbit(sc->sc_ic.ic_chan_avail, chan);
 1494                         /* XXX for FHSS, does frequency matter? */
 1495                         ic->ic_channels[chan].ic_freq = 0;
 1496                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
 1497                         /*
 1498                          * According to the IEEE 802.11 specification,
 1499                          * hop pattern parameter for FH phy should be
 1500                          * incremented by 3 for given hop chanset, i.e.,
 1501                          * the chanset parameter is calculated for given
 1502                          * hop patter.  However, BayStack 650 Access Points
 1503                          * apparently use fixed hop chanset parameter value
 1504                          * 1 for any hop pattern.  So we also try this
 1505                          * combination of hop chanset and pattern.
 1506                          */
 1507                         chan = IEEE80211_FH_CHAN(1, i);
 1508                         setbit(sc->sc_ic.ic_chan_avail, chan);
 1509                         ic->ic_channels[chan].ic_freq = 0; /* XXX */
 1510                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_FHSS;
 1511                 }
 1512         } else {
 1513                 for (i = cs->cs_min; i <= cs->cs_max; i++) {
 1514                         setbit(sc->sc_ic.ic_chan_avail, i);
 1515                         ic->ic_channels[i].ic_freq =
 1516                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
 1517                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
 1518                 }
 1519         }
 1520         sc->sc_cur_chan = cs->cs_def;
 1521         ic->ic_ibss_chan = &ic->ic_channels[cs->cs_def];
 1522 
 1523         sc->sc_mib_local.Fragmentation_Dis = 1;
 1524         sc->sc_mib_local.Add_PLCP_Dis = 0;
 1525         sc->sc_mib_local.MAC_Hdr_Prsv = 0;
 1526         sc->sc_mib_local.Rx_Mgmt_Que_En = 0;
 1527         sc->sc_mib_local.Re_Assembly_Dis = 1;
 1528         sc->sc_mib_local.Strip_PLCP_Dis = 0;
 1529         sc->sc_mib_local.Power_Saving_Mode_Dis = 1;
 1530         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
 1531         sc->sc_mib_local.Check_Seq_Cntl_Dis = 0;
 1532         sc->sc_mib_local.Flush_CFP_Queue_On_CF_End = 0;
 1533         sc->sc_mib_local.Network_Mode = 1;
 1534         sc->sc_mib_local.PWD_Lvl = 0;
 1535         sc->sc_mib_local.CFP_Mode = 0;
 1536 
 1537         /* allocate buffers */
 1538         sc->sc_txbase = AWI_BUFFERS;
 1539         sc->sc_txend = sc->sc_txbase +
 1540             (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) +
 1541             sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS;
 1542         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase);
 1543         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size,
 1544             sc->sc_txend - sc->sc_txbase);
 1545         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend);
 1546         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size,
 1547             AWI_BUFFERS_END - sc->sc_txend);
 1548         sc->sc_mib_local.Acting_as_AP = 0;
 1549         sc->sc_mib_local.Fill_CFP = 0;
 1550 
 1551         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
 1552         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
 1553 
 1554         sc->sc_mib_mgt.aPower_Mgt_Mode = 0;
 1555         sc->sc_mib_mgt.aDTIM_Period = 1;
 1556         LE_WRITE_2(&sc->sc_mib_mgt.aATIM_Window, 0);
 1557         return 0;
 1558 }
 1559 
 1560 static int
 1561 awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib, int wflag)
 1562 {
 1563         int error;
 1564         u_int8_t size, *ptr;
 1565 
 1566         switch (mib) {
 1567         case AWI_MIB_LOCAL:
 1568                 ptr = (u_int8_t *)&sc->sc_mib_local;
 1569                 size = sizeof(sc->sc_mib_local);
 1570                 break;
 1571         case AWI_MIB_ADDR:
 1572                 ptr = (u_int8_t *)&sc->sc_mib_addr;
 1573                 size = sizeof(sc->sc_mib_addr);
 1574                 break;
 1575         case AWI_MIB_MAC:
 1576                 ptr = (u_int8_t *)&sc->sc_mib_mac;
 1577                 size = sizeof(sc->sc_mib_mac);
 1578                 break;
 1579         case AWI_MIB_STAT:
 1580                 ptr = (u_int8_t *)&sc->sc_mib_stat;
 1581                 size = sizeof(sc->sc_mib_stat);
 1582                 break;
 1583         case AWI_MIB_MGT:
 1584                 ptr = (u_int8_t *)&sc->sc_mib_mgt;
 1585                 size = sizeof(sc->sc_mib_mgt);
 1586                 break;
 1587         case AWI_MIB_PHY:
 1588                 ptr = (u_int8_t *)&sc->sc_mib_phy;
 1589                 size = sizeof(sc->sc_mib_phy);
 1590                 break;
 1591         default:
 1592                 return EINVAL;
 1593         }
 1594         if (sc->sc_cmd_inprog) {
 1595                 if ((error = awi_cmd_wait(sc)) != 0) {
 1596                         if (error == EWOULDBLOCK) {
 1597                                 DPRINTF(("awi_mib: cmd %d inprog",
 1598                                     sc->sc_cmd_inprog));
 1599                         }
 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_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_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_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_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 ifnet *ifp = ic->ic_ifp;
 1858         struct awi_softc *sc = ifp->if_softc;
 1859         struct ieee80211_node *ni;
 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(ic, 1);
 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,
 2046                                     sizeof(ni->ni_tstamp));
 2047                                 ni->ni_rstamp = 0;
 2048                                 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1);
 2049                         } else
 2050                                 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0);
 2051                         awi_write_2(sc, AWI_CA_SYNC_MBZ, 0);
 2052                         awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP,
 2053                             ni->ni_tstamp.data, sizeof(ni->ni_tstamp.data));
 2054                         awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp);
 2055                         sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan);
 2056                         if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT))
 2057                             != 0)
 2058                                 break;
 2059                         /* FALLTHRU */
 2060                 case AWI_ST_SUB_SYNC:
 2061                         sc->sc_substate = AWI_ST_NONE;
 2062                         if (ic->ic_flags & IEEE80211_F_SIBSS) {
 2063                                 if ((error = awi_mib(sc, AWI_CMD_GET_MIB,
 2064                                     AWI_MIB_MGT, AWI_WAIT)) != 0)
 2065                                         break;
 2066                                 IEEE80211_ADDR_COPY(ni->ni_bssid,
 2067                                     &sc->sc_mib_mgt.aCurrent_BSS_ID);
 2068                         } else {
 2069                                 if (nstate == IEEE80211_S_RUN) {
 2070                                         sc->sc_rx_timer = 10;
 2071                                         ifp->if_timer = 1;
 2072                                 }
 2073                         }
 2074                         error = 0;
 2075                         break;
 2076                 default:
 2077                         DPRINTF(("awi_newstate: unexpected state %s/%s\n",
 2078                             stname[nstate], substname[sc->sc_substate]));
 2079                         sc->sc_substate = AWI_ST_NONE;
 2080                         error = EIO;
 2081                         break;
 2082                 }
 2083                 goto out;
 2084         }
 2085 
 2086         sc->sc_substate = AWI_ST_NONE;
 2087 
 2088         return (*sc->sc_newstate)(ic, nstate, arg);
 2089 out:
 2090         if (error != 0) {
 2091                 if (error == EINPROGRESS)
 2092                         error = 0;
 2093                 return error;
 2094         }
 2095         return (*sc->sc_newstate)(ic, nstate, arg);
 2096 }
 2097 
 2098 static void
 2099 awi_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
 2100         struct ieee80211_node *ni,
 2101         int subtype, int rssi, u_int32_t rstamp)
 2102 {
 2103         struct awi_softc *sc = ic->ic_ifp->if_softc;
 2104 
 2105         /* probe request is handled by hardware */
 2106         if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
 2107                 return;
 2108         (*sc->sc_recv_mgmt)(ic, m0, ni, subtype, rssi, rstamp);
 2109 }
 2110 
 2111 static int
 2112 awi_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
 2113         int type, int arg)
 2114 {
 2115         struct awi_softc *sc = ic->ic_ifp->if_softc;
 2116 
 2117         /* probe request is handled by hardware */
 2118         if (type == IEEE80211_FC0_SUBTYPE_PROBE_REQ)
 2119                 return 0;
 2120         return (*sc->sc_send_mgmt)(ic, ni, type, arg);
 2121 }
 2122 
 2123 static struct mbuf *
 2124 awi_ether_encap(struct awi_softc *sc, struct mbuf *m)
 2125 {
 2126         struct ieee80211com *ic = &sc->sc_ic;
 2127         struct ieee80211_node *ni = ic->ic_bss;
 2128         struct ether_header *eh;
 2129         struct ieee80211_frame *wh;
 2130 
 2131         if (m->m_len < sizeof(struct ether_header)) {
 2132                 m = m_pullup(m, sizeof(struct ether_header));
 2133                 if (m == NULL)
 2134                         return NULL;
 2135         }
 2136         eh = mtod(m, struct ether_header *);
 2137         M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
 2138         if (m == NULL)
 2139                 return NULL;
 2140         wh = mtod(m, struct ieee80211_frame *);
 2141         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
 2142         *(u_int16_t *)wh->i_dur = 0;
 2143         *(u_int16_t *)wh->i_seq =
 2144             htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
 2145         ni->ni_txseqs[0]++;
 2146         if (ic->ic_opmode == IEEE80211_M_IBSS ||
 2147             ic->ic_opmode == IEEE80211_M_AHDEMO) {
 2148                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 2149                 if (sc->sc_adhoc_ap)
 2150                         IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
 2151                 else
 2152                         IEEE80211_ADDR_COPY(wh->i_addr1, eh->ether_dhost);
 2153                 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
 2154                 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
 2155         } else {
 2156                 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
 2157                 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
 2158                 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost);
 2159                 IEEE80211_ADDR_COPY(wh->i_addr3, eh->ether_dhost);
 2160         }
 2161         return m;
 2162 }
 2163 
 2164 static struct mbuf *
 2165 awi_ether_modcap(struct awi_softc *sc, struct mbuf *m)
 2166 {
 2167         struct ieee80211com *ic = &sc->sc_ic;
 2168         struct ether_header eh;
 2169         struct ieee80211_frame wh;
 2170         struct llc *llc;
 2171 
 2172         if (m->m_len < sizeof(wh) + sizeof(eh)) {
 2173                 m = m_pullup(m, sizeof(wh) + sizeof(eh));
 2174                 if (m == NULL)
 2175                         return NULL;
 2176         }
 2177         memcpy(&wh, mtod(m, caddr_t), sizeof(wh));
 2178         if (wh.i_fc[0] != (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA))
 2179                 return m;
 2180         memcpy(&eh, mtod(m, caddr_t) + sizeof(wh), sizeof(eh));
 2181         m_adj(m, sizeof(eh) - sizeof(*llc));
 2182         if (ic->ic_opmode == IEEE80211_M_IBSS ||
 2183             ic->ic_opmode == IEEE80211_M_AHDEMO)
 2184                 IEEE80211_ADDR_COPY(wh.i_addr2, eh.ether_shost);
 2185         memcpy(mtod(m, caddr_t), &wh, sizeof(wh));
 2186         llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh));
 2187         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 2188         llc->llc_control = LLC_UI;
 2189         llc->llc_snap.org_code[0] = 0;
 2190         llc->llc_snap.org_code[1] = 0;
 2191         llc->llc_snap.org_code[2] = 0;
 2192         llc->llc_snap.ether_type = eh.ether_type;
 2193         return m;
 2194 }

Cache object: 7013af799639ca24b6c048b347cbf84f


[ 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.