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


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

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

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

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

Cache object: 34005528ad3d61d730a518ab0696034a


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