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/awi/awi.c

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

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

Cache object: f9a9f0d8a9cc116cddfa36413bf6fc88


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