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

Cache object: b119f973e262721b8e4d25b7aeeed3b3


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