root/dev/ic/awi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ether_sprintf
  2. awi_attach
  3. awi_detach
  4. awi_activate
  5. awi_power
  6. awi_ioctl
  7. awi_media_rate2opt
  8. awi_media_opt2rate
  9. awi_media_change
  10. awi_media_status
  11. awi_intr
  12. awi_init
  13. awi_stop
  14. awi_watchdog
  15. awi_start
  16. awi_txint
  17. awi_fix_txhdr
  18. awi_fix_rxhdr
  19. awi_input
  20. awi_rxint
  21. awi_devget
  22. awi_init_hw
  23. awi_init_mibs
  24. awi_init_txrx
  25. awi_stop_txrx
  26. awi_init_region
  27. awi_start_scan
  28. awi_next_scan
  29. awi_stop_scan
  30. awi_recv_beacon
  31. awi_set_ss
  32. awi_try_sync
  33. awi_sync_done
  34. awi_send_deauth
  35. awi_send_auth
  36. awi_recv_auth
  37. awi_send_asreq
  38. awi_recv_asresp
  39. awi_mib
  40. awi_cmd_scan
  41. awi_cmd
  42. awi_cmd_done
  43. awi_next_txd
  44. awi_lock
  45. awi_unlock
  46. awi_intr_lock
  47. awi_intr_unlock
  48. awi_cmd_wait
  49. awi_print_essid
  50. awi_dump_pkt

    1 /*      $OpenBSD: awi.c,v 1.23 2007/02/11 20:29:22 miod Exp $   */
    2 /*      $NetBSD: awi.c,v 1.26 2000/07/21 04:48:55 onoe Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Bill Sommerfeld
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 /*
   40  * Driver for AMD 802.11 firmware.
   41  * Uses am79c930 chip driver to talk to firmware running on the am79c930.
   42  *
   43  * More-or-less a generic ethernet-like if driver, with 802.11 gorp added.
   44  */
   45 
   46 /*
   47  * todo:
   48  *      - flush tx queue on resynch.
   49  *      - clear oactive on "down".
   50  *      - rewrite copy-into-mbuf code
   51  *      - mgmt state machine gets stuck retransmitting assoc requests.
   52  *      - multicast filter.
   53  *      - fix device reset so it's more likely to work
   54  *      - show status goo through ifmedia.
   55  *
   56  * more todo:
   57  *      - deal with more 802.11 frames.
   58  *              - send reassoc request
   59  *              - deal with reassoc response
   60  *              - send/deal with disassociation
   61  *      - deal with "full" access points (no room for me).
   62  *      - power save mode
   63  *
   64  * later:
   65  *      - SSID preferences
   66  *      - need ioctls for poking at the MIBs
   67  *      - implement ad-hoc mode (including bss creation).
   68  *      - decide when to do "ad hoc" vs. infrastructure mode (IFF_LINK flags?)
   69  *              (focus on inf. mode since that will be needed for ietf)
   70  *      - deal with DH vs. FH versions of the card
   71  *      - deal with faster cards (2mb/s)
   72  *      - ?WEP goo (mmm, rc4) (it looks not particularly useful).
   73  *      - ifmedia revision.
   74  *      - common 802.11 mibish things.
   75  *      - common 802.11 media layer.
   76  */
   77 
   78 /*
   79  * Driver for AMD 802.11 PCnetMobile firmware.
   80  * Uses am79c930 chip driver to talk to firmware running on the am79c930.
   81  *
   82  * The initial version of the driver was written by
   83  * Bill Sommerfeld <sommerfeld@netbsd.org>.
   84  * Then the driver module completely rewritten to support cards with DS phy
   85  * and to support adhoc mode by Atsushi Onoe <onoe@netbsd.org>
   86  */
   87 
   88 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
   89 #define NBPFILTER       1
   90 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3
   91 #include "bpf.h"
   92 #define NBPFILTER       NBPF
   93 #else
   94 #include "bpfilter.h"
   95 #endif
   96 
   97 #include <sys/param.h>
   98 #include <sys/systm.h>
   99 #include <sys/kernel.h>
  100 #include <sys/mbuf.h>
  101 #include <sys/malloc.h>
  102 #include <sys/proc.h>
  103 #include <sys/socket.h>
  104 #include <sys/sockio.h>
  105 #include <sys/errno.h>
  106 #include <sys/syslog.h>
  107 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
  108 #include <sys/bus.h>
  109 #else
  110 #include <sys/device.h>
  111 #endif
  112 
  113 #include <net/if.h>
  114 #include <net/if_dl.h>
  115 #ifndef __OpenBSD__
  116 #ifdef __FreeBSD__
  117 #include <net/ethernet.h>
  118 #else
  119 #include <net/if_ether.h>
  120 #endif
  121 #endif
  122 #include <net/if_media.h>
  123 #include <net/if_llc.h>
  124 
  125 #ifdef INET
  126 #include <netinet/in.h>
  127 #include <netinet/in_systm.h>
  128 #include <netinet/in_var.h>
  129 #include <netinet/ip.h>
  130 #ifdef __NetBSD__
  131 #include <netinet/if_inarp.h>
  132 #else
  133 #include <netinet/if_ether.h>
  134 #endif
  135 #endif
  136 
  137 #include <net80211/ieee80211.h>
  138 #include <net80211/ieee80211_ioctl.h>
  139 
  140 #if NBPFILTER > 0
  141 #include <net/bpf.h>
  142 #endif
  143 
  144 #include <machine/cpu.h>
  145 #include <machine/bus.h>
  146 #ifdef __NetBSD__
  147 #include <machine/intr.h>
  148 #endif
  149 #ifdef __FreeBSD__
  150 #include <machine/clock.h>
  151 #endif
  152 
  153 #if defined(__NetBSD__) || defined(__OpenBSD__)
  154 #include <dev/ic/am79c930reg.h>
  155 #include <dev/ic/am79c930var.h>
  156 #include <dev/ic/awireg.h>
  157 #include <dev/ic/awivar.h>
  158 #endif
  159 #ifdef __FreeBSD__
  160 #include <dev/awi/am79c930reg.h>
  161 #include <dev/awi/am79c930var.h>
  162 #include <dev/awi/awireg.h>
  163 #include <dev/awi/awivar.h>
  164 #endif
  165 
  166 static int awi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
  167 #ifdef IFM_IEEE80211
  168 static int awi_media_rate2opt(struct awi_softc *sc, int rate);
  169 static int awi_media_opt2rate(struct awi_softc *sc, int opt);
  170 static int awi_media_change(struct ifnet *ifp);
  171 static void awi_media_status(struct ifnet *ifp, struct ifmediareq *imr);
  172 #endif
  173 static void awi_watchdog(struct ifnet *ifp);
  174 static void awi_start(struct ifnet *ifp);
  175 static void awi_txint(struct awi_softc *sc);
  176 static struct mbuf * awi_fix_txhdr(struct awi_softc *sc, struct mbuf *m0);
  177 static struct mbuf * awi_fix_rxhdr(struct awi_softc *sc, struct mbuf *m0);
  178 static void awi_input(struct awi_softc *sc, struct mbuf *m, u_int32_t rxts, u_int8_t rssi);
  179 static void awi_rxint(struct awi_softc *sc);
  180 static struct mbuf * awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len);
  181 static int awi_init_hw(struct awi_softc *sc);
  182 static int awi_init_mibs(struct awi_softc *sc);
  183 static int awi_init_txrx(struct awi_softc *sc);
  184 static void awi_stop_txrx(struct awi_softc *sc);
  185 static int awi_start_scan(struct awi_softc *sc);
  186 static int awi_next_scan(struct awi_softc *sc);
  187 static void awi_stop_scan(struct awi_softc *sc);
  188 static void awi_recv_beacon(struct awi_softc *sc, struct mbuf *m0, u_int32_t rxts, u_int8_t rssi);
  189 static int awi_set_ss(struct awi_softc *sc);
  190 static void awi_try_sync(struct awi_softc *sc);
  191 static void awi_sync_done(struct awi_softc *sc);
  192 static void awi_send_deauth(struct awi_softc *sc);
  193 static void awi_send_auth(struct awi_softc *sc, int seq);
  194 static void awi_recv_auth(struct awi_softc *sc, struct mbuf *m0);
  195 static void awi_send_asreq(struct awi_softc *sc, int reassoc);
  196 static void awi_recv_asresp(struct awi_softc *sc, struct mbuf *m0);
  197 static int awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib);
  198 static int awi_cmd_scan(struct awi_softc *sc);
  199 static int awi_cmd(struct awi_softc *sc, u_int8_t cmd);
  200 static void awi_cmd_done(struct awi_softc *sc);
  201 static int awi_next_txd(struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t*ntxdp);
  202 static int awi_lock(struct awi_softc *sc);
  203 static void awi_unlock(struct awi_softc *sc);
  204 static int awi_intr_lock(struct awi_softc *sc);
  205 static void awi_intr_unlock(struct awi_softc *sc);
  206 static int awi_cmd_wait(struct awi_softc *sc);
  207 static void awi_print_essid(u_int8_t *essid);
  208 
  209 #ifdef AWI_DEBUG
  210 static void awi_dump_pkt(struct awi_softc *sc, struct mbuf *m, int rssi);
  211 int awi_verbose = 0;
  212 int awi_dump = 0;
  213 #define AWI_DUMP_MASK(fc0)  (1 << (((fc0) & IEEE80211_FC0_SUBTYPE_MASK) >> 4))
  214 int awi_dump_mask = AWI_DUMP_MASK(IEEE80211_FC0_SUBTYPE_BEACON);
  215 int awi_dump_hdr = 0;
  216 int awi_dump_len = 28;
  217 #endif
  218 
  219 #if NBPFILTER > 0
  220 #define AWI_BPF_NORM    0
  221 #define AWI_BPF_RAW     1
  222 #ifdef __FreeBSD__
  223 #define AWI_BPF_MTAP(sc, m, raw, dir) do {                              \
  224         if ((sc)->sc_ifp->if_bpf && (sc)->sc_rawbpf == (raw))           \
  225                 bpf_mtap((sc)->sc_ifp, (m));                            \
  226 } while (0);
  227 #else
  228 #define AWI_BPF_MTAP(sc, m, raw, dir) do {                              \
  229         if ((sc)->sc_ifp->if_bpf && (sc)->sc_rawbpf == (raw))           \
  230                 bpf_mtap((sc)->sc_ifp->if_bpf, (m), dir);               \
  231 } while (0);
  232 #endif
  233 #else
  234 #define AWI_BPF_MTAP(sc, m, raw, dir)
  235 #endif
  236 
  237 #ifndef llc_snap
  238 #define llc_snap              llc_un.type_snap
  239 #endif
  240 
  241 #ifdef __OpenBSD__
  242 struct cfdriver awi_cd = {
  243         NULL, "awi", DV_IFNET
  244 };
  245 #endif
  246 
  247 #ifdef __FreeBSD__
  248 #if __FreeBSD__ >= 4
  249 devclass_t awi_devclass;
  250 #endif
  251 
  252 /* NetBSD compatible functions  */
  253 static char * ether_sprintf(u_int8_t *);
  254 
  255 static char *
  256 ether_sprintf(enaddr)
  257         u_int8_t *enaddr;
  258 {
  259         static char strbuf[18];
  260 
  261         snprintf(strbuf, sizeof strbuf, "%6D", enaddr, ":");
  262         return strbuf;
  263 }
  264 #endif
  265 
  266 int
  267 awi_attach(sc)
  268         struct awi_softc *sc;
  269 {
  270         struct ifnet *ifp = sc->sc_ifp;
  271         int s;
  272         int error;
  273 #ifdef IFM_IEEE80211
  274         int i;
  275         u_int8_t *phy_rates;
  276         int mword;
  277         struct ifmediareq imr;
  278 #endif
  279 
  280         s = splnet();
  281         /*
  282          * Even if we can sleep in initialization state,
  283          * all other processes (e.g. ifconfig) have to wait for
  284          * completion of attaching interface.
  285          */
  286         sc->sc_busy = 1;
  287         sc->sc_status = AWI_ST_INIT;
  288         TAILQ_INIT(&sc->sc_scan);
  289         error = awi_init_hw(sc);
  290         if (error) {
  291                 sc->sc_invalid = 1;
  292                 splx(s);
  293                 return error;
  294         }
  295         error = awi_init_mibs(sc);
  296         splx(s);
  297         if (error) {
  298                 sc->sc_invalid = 1;
  299                 return error;
  300         }
  301 
  302         ifp->if_softc = sc;
  303         ifp->if_start = awi_start;
  304         ifp->if_ioctl = awi_ioctl;
  305         ifp->if_watchdog = awi_watchdog;
  306         ifp->if_hdrlen = sizeof(struct ieee80211_frame) +
  307             sizeof(struct ether_header);
  308         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  309 #ifdef IFF_NOTRAILERS
  310         ifp->if_flags |= IFF_NOTRAILERS;
  311 #endif
  312 #if defined(__NetBSD__) || defined(__OpenBSD__)
  313         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
  314 #endif
  315 #ifdef __FreeBSD__
  316         ifp->if_output = ether_output;
  317         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  318         memcpy(sc->sc_ec.ac_enaddr, sc->sc_mib_addr.aMAC_Address,
  319             ETHER_ADDR_LEN);
  320 #endif
  321         IFQ_SET_READY(&ifp->if_snd);
  322 
  323         printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n",
  324             sc->sc_dev.dv_xname,
  325             sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH ? "FH" : "DS",
  326             sc->sc_tx_rate / 10, sc->sc_banner);
  327         printf("%s: address %s\n",
  328             sc->sc_dev.dv_xname,  ether_sprintf(sc->sc_mib_addr.aMAC_Address));
  329         if_attach(ifp);
  330 #ifdef __OpenBSD__
  331         ether_ifattach(ifp);
  332 #elif defined(__FreeBSD__)
  333         ether_ifattach(ifp);
  334 #if NBPFILTER > 0
  335         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
  336 #endif
  337 #elif defined(__NetBSD__)
  338         ether_ifattach(ifp, sc->sc_mib_addr.aMAC_Address);
  339 #endif
  340 
  341 #ifdef IFM_IEEE80211
  342         ifmedia_init(&sc->sc_media, 0, awi_media_change, awi_media_status);
  343         phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
  344         for (i = 0; i < phy_rates[1]; i++) {
  345                 mword = awi_media_rate2opt(sc, AWI_80211_RATE(phy_rates[2 + i]));
  346                 if (mword == 0)
  347                         continue;
  348                 mword |= IFM_IEEE80211;
  349                 ifmedia_add(&sc->sc_media, mword, 0, NULL);
  350                 ifmedia_add(&sc->sc_media,
  351                     mword | IFM_IEEE80211_ADHOC, 0, NULL);
  352                 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH)
  353                         ifmedia_add(&sc->sc_media,
  354                             mword | IFM_IEEE80211_ADHOC | IFM_FLAG0, 0, NULL);
  355         }
  356         awi_media_status(ifp, &imr);
  357         ifmedia_set(&sc->sc_media, imr.ifm_active);
  358 #endif
  359 
  360         /* ready to accept ioctl */
  361         awi_unlock(sc);
  362 
  363         /* Attach is successful. */
  364         sc->sc_attached = 1;
  365         return 0;
  366 }
  367 
  368 #ifndef __FreeBSD__
  369 int
  370 awi_detach(sc)
  371         struct awi_softc *sc;
  372 {
  373         struct ifnet *ifp = sc->sc_ifp;
  374         int s;
  375 
  376         /* Succeed if there is no work to do. */
  377         if (!sc->sc_attached)
  378                 return (0);
  379 
  380         s = splnet();
  381         sc->sc_invalid = 1;
  382         awi_stop(sc);
  383         while (sc->sc_sleep_cnt > 0) {
  384                 wakeup(sc);
  385                 (void)tsleep(sc, PWAIT, "awidet", 1);
  386         }
  387         if (sc->sc_wep_ctx != NULL)
  388                 free(sc->sc_wep_ctx, M_DEVBUF);
  389 #ifdef IFM_IEEE80211
  390         ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
  391 #endif
  392         ether_ifdetach(ifp);
  393         if_detach(ifp);
  394         if (sc->sc_enabled) {
  395                 if (sc->sc_disable)
  396                         (*sc->sc_disable)(sc);
  397                 sc->sc_enabled = 0;
  398         }
  399         splx(s);
  400         return 0;
  401 }
  402 
  403 int
  404 awi_activate(self, act)
  405         struct device *self;
  406         enum devact act;
  407 {
  408         struct awi_softc *sc = (struct awi_softc *)self;
  409         int s, error = 0;
  410 
  411         s = splnet();
  412         switch (act) {
  413         case DVACT_ACTIVATE:
  414                 break;
  415 
  416         case DVACT_DEACTIVATE:
  417                 sc->sc_invalid = 1;
  418 #ifdef __NetBSD__
  419                 if (sc->sc_ifp)
  420                         if_deactivate(sc->sc_ifp);
  421 #endif
  422                 break;
  423         }
  424         splx(s);
  425 
  426         return error;
  427 }
  428 
  429 void
  430 awi_power(sc, why)
  431         struct awi_softc *sc;
  432         int why;
  433 {
  434         int s;
  435         int ocansleep;
  436 
  437         if (!sc->sc_enabled)
  438                 return;
  439 
  440         s = splnet();
  441         ocansleep = sc->sc_cansleep;
  442         sc->sc_cansleep = 0;
  443 #ifdef needtobefixed    /*ONOE*/
  444         if (why == PWR_RESUME) {
  445                 sc->sc_enabled = 0;
  446                 awi_init(sc);
  447                 (void)awi_intr(sc);
  448         } else {
  449                 awi_stop(sc);
  450                 if (sc->sc_disable)
  451                         (*sc->sc_disable)(sc);
  452         }
  453 #endif
  454         sc->sc_cansleep = ocansleep;
  455         splx(s);
  456 }
  457 #endif /* __NetBSD__ */
  458 
  459 static int
  460 awi_ioctl(ifp, cmd, data)
  461         struct ifnet *ifp;
  462         u_long cmd;
  463         caddr_t data;
  464 {
  465         struct awi_softc *sc = ifp->if_softc;
  466         struct ifreq *ifr = (struct ifreq *)data;
  467         struct ifaddr *ifa = (struct ifaddr *)data;
  468         int s, error;
  469         struct ieee80211_nwid nwid;
  470         u_int8_t *p;
  471 
  472         s = splnet();
  473 
  474 #ifdef __OpenBSD__
  475         if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
  476                 splx(s);
  477                 return (error);
  478         }
  479 #endif
  480 
  481         /* serialize ioctl */
  482         error = awi_lock(sc);
  483         if (error)
  484                 goto cantlock;
  485         switch (cmd) {
  486         case SIOCSIFADDR:
  487                 ifp->if_flags |= IFF_UP;
  488                 switch (ifa->ifa_addr->sa_family) {
  489 #ifdef INET
  490                 case AF_INET:
  491                         arp_ifinit((void *)ifp, ifa);
  492                         break;
  493 #endif
  494                 }
  495                 /* FALLTHROUGH */
  496         case SIOCSIFFLAGS:
  497                 sc->sc_format_llc = !(ifp->if_flags & IFF_LINK0);
  498                 if (!(ifp->if_flags & IFF_UP)) {
  499                         if (sc->sc_enabled) {
  500                                 awi_stop(sc);
  501                                 if (sc->sc_disable)
  502                                         (*sc->sc_disable)(sc);
  503                                 sc->sc_enabled = 0;
  504                         }
  505                         break;
  506                 }
  507                 error = awi_init(sc);
  508                 break;
  509 
  510         case SIOCADDMULTI:
  511         case SIOCDELMULTI:
  512 #ifdef __FreeBSD__
  513                 error = ENETRESET;      /*XXX*/
  514 #else
  515                 error = (cmd == SIOCADDMULTI) ?
  516                     ether_addmulti(ifr, &sc->sc_arpcom) :
  517                     ether_delmulti(ifr, &sc->sc_arpcom);
  518 #endif
  519                 /*
  520                  * Do not rescan BSS.  Rather, just reset multicast filter.
  521                  */
  522                 if (error == ENETRESET) {
  523                         if (ifp->if_flags & IFF_RUNNING)
  524                                 error = awi_init(sc);
  525                         else
  526                                 error = 0;
  527                 }
  528                 break;
  529         case SIOCSIFMTU:
  530                 if (ifr->ifr_mtu > ETHERMTU)
  531                         error = EINVAL;
  532                 else
  533                         ifp->if_mtu = ifr->ifr_mtu;
  534                 break;
  535         case SIOCS80211NWID:
  536                 if ((error = suser(curproc, 0)) != 0)
  537                         break;
  538                 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
  539                 if (error)
  540                         break;
  541                 if (nwid.i_len > IEEE80211_NWID_LEN) {
  542                         error = EINVAL;
  543                         break;
  544                 }
  545                 if (sc->sc_mib_mac.aDesired_ESS_ID[1] == nwid.i_len &&
  546                     memcmp(&sc->sc_mib_mac.aDesired_ESS_ID[2], nwid.i_nwid,
  547                     nwid.i_len) == 0)
  548                         break;
  549                 memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
  550                 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
  551                 sc->sc_mib_mac.aDesired_ESS_ID[1] = nwid.i_len;
  552                 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], nwid.i_nwid,
  553                     nwid.i_len);
  554                 if (sc->sc_enabled) {
  555                         awi_stop(sc);
  556                         error = awi_init(sc);
  557                 }
  558                 break;
  559         case SIOCG80211NWID:
  560                 if (ifp->if_flags & IFF_RUNNING)
  561                         p = sc->sc_bss.essid;
  562                 else
  563                         p = sc->sc_mib_mac.aDesired_ESS_ID;
  564                 error = copyout(p + 1, ifr->ifr_data, 1 + IEEE80211_NWID_LEN);
  565                 break;
  566         case SIOCS80211NWKEY:
  567                 if ((error = suser(curproc, 0)) != 0)
  568                         break;
  569                 error = awi_wep_setnwkey(sc, (struct ieee80211_nwkey *)data);
  570                 break;
  571         case SIOCG80211NWKEY:
  572                 error = awi_wep_getnwkey(sc, (struct ieee80211_nwkey *)data);
  573                 break;
  574 #ifdef IFM_IEEE80211
  575         case SIOCSIFMEDIA:
  576         case SIOCGIFMEDIA:
  577                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
  578                 break;
  579 #endif
  580         default:
  581 #ifdef notyet
  582                 error = awi_wicfg(ifp, cmd, data);
  583 #else
  584                 error = EINVAL;
  585 #endif
  586                 break;
  587         }
  588         awi_unlock(sc);
  589   cantlock:
  590         splx(s);
  591         return error;
  592 }
  593 
  594 #ifdef IFM_IEEE80211
  595 static int
  596 awi_media_rate2opt(sc, rate)
  597         struct awi_softc *sc;
  598         int rate;
  599 {
  600         int mword;
  601 
  602         mword = 0;
  603         switch (rate) {
  604         case 10:
  605                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
  606                         mword = IFM_IEEE80211_FH1;
  607                 else
  608                         mword = IFM_IEEE80211_DS1;
  609                 break;
  610         case 20:
  611                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
  612                         mword = IFM_IEEE80211_FH2;
  613                 else
  614                         mword = IFM_IEEE80211_DS2;
  615                 break;
  616         case 55:
  617                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_DS)
  618                         mword = IFM_IEEE80211_DS5;
  619                 break;
  620         case 110:
  621                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_DS)
  622                         mword = IFM_IEEE80211_DS11;
  623                 break;
  624         }
  625         return mword;
  626 }
  627 
  628 static int
  629 awi_media_opt2rate(sc, opt)
  630         struct awi_softc *sc;
  631         int opt;
  632 {
  633         int rate;
  634 
  635         rate = 0;
  636         switch (IFM_SUBTYPE(opt)) {
  637         case IFM_IEEE80211_FH1:
  638         case IFM_IEEE80211_FH2:
  639                 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH)
  640                         return 0;
  641                 break;
  642         case IFM_IEEE80211_DS1:
  643         case IFM_IEEE80211_DS2:
  644         case IFM_IEEE80211_DS5:
  645         case IFM_IEEE80211_DS11:
  646                 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_DS)
  647                         return 0;
  648                 break;
  649         }
  650 
  651         switch (IFM_SUBTYPE(opt)) {
  652         case IFM_IEEE80211_FH1:
  653         case IFM_IEEE80211_DS1:
  654                 rate = 10;
  655                 break;
  656         case IFM_IEEE80211_FH2:
  657         case IFM_IEEE80211_DS2:
  658                 rate = 20;
  659                 break;
  660         case IFM_IEEE80211_DS5:
  661                 rate = 55;
  662                 break;
  663         case IFM_IEEE80211_DS11:
  664                 rate = 110;
  665                 break;
  666         }
  667         return rate;
  668 }
  669 
  670 /*
  671  * Called from ifmedia_ioctl via awi_ioctl with lock obtained.
  672  */
  673 static int
  674 awi_media_change(ifp)
  675         struct ifnet *ifp;
  676 {
  677         struct awi_softc *sc = ifp->if_softc;
  678         struct ifmedia_entry *ime;
  679         u_int8_t *phy_rates;
  680         int i, rate, error;
  681 
  682         error = 0;
  683         ime = sc->sc_media.ifm_cur;
  684         rate = awi_media_opt2rate(sc, ime->ifm_media);
  685         if (rate == 0)
  686                 return EINVAL;
  687         if (rate != sc->sc_tx_rate) {
  688                 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
  689                 for (i = 0; i < phy_rates[1]; i++) {
  690                         if (rate == AWI_80211_RATE(phy_rates[2 + i]))
  691                                 break;
  692                 }
  693                 if (i == phy_rates[1])
  694                         return EINVAL;
  695         }
  696         if (ime->ifm_media & IFM_IEEE80211_ADHOC) {
  697                 sc->sc_mib_local.Network_Mode = 0;
  698                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
  699                         sc->sc_no_bssid = 0;
  700                 else
  701                         sc->sc_no_bssid = (ime->ifm_media & IFM_FLAG0) ? 1 : 0;
  702         } else {
  703                 sc->sc_mib_local.Network_Mode = 1;
  704         }
  705         if (sc->sc_enabled) {
  706                 awi_stop(sc);
  707                 error = awi_init(sc);
  708         }
  709         return error;
  710 }
  711 
  712 static void
  713 awi_media_status(ifp, imr)
  714         struct ifnet *ifp;
  715         struct ifmediareq *imr;
  716 {
  717         struct awi_softc *sc = ifp->if_softc;
  718 
  719         imr->ifm_status = IFM_AVALID;
  720         if (ifp->if_flags & IFF_RUNNING)
  721                 imr->ifm_status |= IFM_ACTIVE;
  722         imr->ifm_active = IFM_IEEE80211;
  723         imr->ifm_active |= awi_media_rate2opt(sc, sc->sc_tx_rate);
  724         if (sc->sc_mib_local.Network_Mode == 0) {
  725                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
  726                 if (sc->sc_no_bssid)
  727                         imr->ifm_active |= IFM_FLAG0;
  728         }
  729 }
  730 #endif /* IFM_IEEE80211 */
  731 
  732 int
  733 awi_intr(arg)
  734         void *arg;
  735 {
  736         struct awi_softc *sc = arg;
  737         u_int16_t status;
  738         int error, handled = 0, ocansleep;
  739 
  740         if (!sc->sc_enabled || !sc->sc_enab_intr || sc->sc_invalid)
  741                 return 0;
  742 
  743         am79c930_gcr_setbits(&sc->sc_chip,
  744             AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT);
  745         awi_write_1(sc, AWI_DIS_PWRDN, 1);
  746         ocansleep = sc->sc_cansleep;
  747         sc->sc_cansleep = 0;
  748 
  749         for (;;) {
  750                 error = awi_intr_lock(sc);
  751                 if (error)
  752                         break;
  753                 status = awi_read_1(sc, AWI_INTSTAT);
  754                 awi_write_1(sc, AWI_INTSTAT, 0);
  755                 awi_write_1(sc, AWI_INTSTAT, 0);
  756                 status |= awi_read_1(sc, AWI_INTSTAT2) << 8;
  757                 awi_write_1(sc, AWI_INTSTAT2, 0);
  758                 DELAY(10);
  759                 awi_intr_unlock(sc);
  760                 if (!sc->sc_cmd_inprog)
  761                         status &= ~AWI_INT_CMD; /* make sure */
  762                 if (status == 0)
  763                         break;
  764                 handled = 1;
  765                 if (status & AWI_INT_RX)
  766                         awi_rxint(sc);
  767                 if (status & AWI_INT_TX)
  768                         awi_txint(sc);
  769                 if (status & AWI_INT_CMD)
  770                         awi_cmd_done(sc);
  771                 if (status & AWI_INT_SCAN_CMPLT) {
  772                         if (sc->sc_status == AWI_ST_SCAN &&
  773                             sc->sc_mgt_timer > 0)
  774                                 (void)awi_next_scan(sc);
  775                 }
  776         }
  777         sc->sc_cansleep = ocansleep;
  778         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN);
  779         awi_write_1(sc, AWI_DIS_PWRDN, 0);
  780         return handled;
  781 }
  782 
  783 int
  784 awi_init(sc)
  785         struct awi_softc *sc;
  786 {
  787         int error, ostatus;
  788         int n;
  789         struct ifnet *ifp = sc->sc_ifp;
  790 #ifdef __FreeBSD__
  791         struct ifmultiaddr *ifma;
  792 #else
  793         struct ether_multi *enm;
  794         struct ether_multistep step;
  795 #endif
  796 
  797         /* reinitialize muticast filter */
  798         n = 0;
  799         ifp->if_flags |= IFF_ALLMULTI;
  800         sc->sc_mib_local.Accept_All_Multicast_Dis = 0;
  801         if (ifp->if_flags & IFF_PROMISC) {
  802                 sc->sc_mib_mac.aPromiscuous_Enable = 1;
  803                 goto set_mib;
  804         }
  805         sc->sc_mib_mac.aPromiscuous_Enable = 0;
  806 #ifdef __FreeBSD__
  807         if (ifp->if_amcount != 0)
  808                 goto set_mib;
  809         for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
  810             ifma = LIST_NEXT(ifma, ifma_link)) {
  811                 if (ifma->ifma_addr->sa_family != AF_LINK)
  812                         continue;
  813                 if (n == AWI_GROUP_ADDR_SIZE)
  814                         goto set_mib;
  815                 memcpy(sc->sc_mib_addr.aGroup_Addresses[n],
  816                     LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
  817                     ETHER_ADDR_LEN);
  818                 n++;
  819         }
  820 #else
  821         ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
  822         while (enm != NULL) {
  823                 if (n == AWI_GROUP_ADDR_SIZE ||
  824                     memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)
  825                     != 0)
  826                         goto set_mib;
  827                 memcpy(sc->sc_mib_addr.aGroup_Addresses[n], enm->enm_addrlo,
  828                     ETHER_ADDR_LEN);
  829                 n++;
  830                 ETHER_NEXT_MULTI(step, enm);
  831         }
  832 #endif
  833         for (; n < AWI_GROUP_ADDR_SIZE; n++)
  834                 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0, ETHER_ADDR_LEN);
  835         ifp->if_flags &= ~IFF_ALLMULTI;
  836         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
  837 
  838   set_mib:
  839 #ifdef notdef   /* allow non-encrypted frame for receiving. */
  840         sc->sc_mib_mgt.Wep_Required = sc->sc_wep_algo != NULL ? 1 : 0;
  841 #endif
  842         if (!sc->sc_enabled) {
  843                 sc->sc_enabled = 1;
  844                 if (sc->sc_enable)
  845                         (*sc->sc_enable)(sc);
  846                 sc->sc_status = AWI_ST_INIT;
  847                 error = awi_init_hw(sc);
  848                 if (error)
  849                         return error;
  850         }
  851         ostatus = sc->sc_status;
  852         sc->sc_status = AWI_ST_INIT;
  853         if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL)) != 0 ||
  854             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR)) != 0 ||
  855             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC)) != 0 ||
  856             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT)) != 0 ||
  857             (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY)) != 0) {
  858                 awi_stop(sc);
  859                 return error;
  860         }
  861         if (ifp->if_flags & IFF_RUNNING)
  862                 sc->sc_status = AWI_ST_RUNNING;
  863         else {
  864                 if (ostatus == AWI_ST_INIT) {
  865                         error = awi_init_txrx(sc);
  866                         if (error)
  867                                 return error;
  868                 }
  869                 error = awi_start_scan(sc);
  870         }
  871         return error;
  872 }
  873 
  874 void
  875 awi_stop(sc)
  876         struct awi_softc *sc;
  877 {
  878         struct ifnet *ifp = sc->sc_ifp;
  879         struct awi_bss *bp;
  880         struct mbuf *m;
  881 
  882         sc->sc_status = AWI_ST_INIT;
  883         if (!sc->sc_invalid) {
  884                 (void)awi_cmd_wait(sc);
  885                 if (sc->sc_mib_local.Network_Mode &&
  886                     sc->sc_status > AWI_ST_AUTH)
  887                         awi_send_deauth(sc);
  888                 awi_stop_txrx(sc);
  889         }
  890         ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
  891         ifp->if_timer = 0;
  892         sc->sc_tx_timer = sc->sc_rx_timer = sc->sc_mgt_timer = 0;
  893         for (;;) {
  894                 IF_DEQUEUE(&sc->sc_mgtq, m);
  895                 if (m == NULL)
  896                         break;
  897                 m_freem(m);
  898         }
  899         IFQ_PURGE(&ifp->if_snd);
  900         while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
  901                 TAILQ_REMOVE(&sc->sc_scan, bp, list);
  902                 free(bp, M_DEVBUF);
  903         }
  904 }
  905 
  906 static void
  907 awi_watchdog(ifp)
  908         struct ifnet *ifp;
  909 {
  910         struct awi_softc *sc = ifp->if_softc;
  911         int ocansleep;
  912 
  913         if (sc->sc_invalid) {
  914                 ifp->if_timer = 0;
  915                 return;
  916         }
  917 
  918         ocansleep = sc->sc_cansleep;
  919         sc->sc_cansleep = 0;
  920         if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
  921                 printf("%s: transmit timeout\n", sc->sc_dev.dv_xname);
  922                 awi_txint(sc);
  923         }
  924         if (sc->sc_rx_timer && --sc->sc_rx_timer == 0) {
  925                 if (ifp->if_flags & IFF_DEBUG) {
  926                         printf("%s: no recent beacons from %s; rescanning\n",
  927                             sc->sc_dev.dv_xname,
  928                             ether_sprintf(sc->sc_bss.bssid));
  929                 }
  930                 ifp->if_flags &= ~IFF_RUNNING;
  931                 awi_start_scan(sc);
  932         }
  933         if (sc->sc_mgt_timer && --sc->sc_mgt_timer == 0) {
  934                 switch (sc->sc_status) {
  935                 case AWI_ST_SCAN:
  936                         awi_stop_scan(sc);
  937                         break;
  938                 case AWI_ST_AUTH:
  939                 case AWI_ST_ASSOC:
  940                         /* restart scan */
  941                         awi_start_scan(sc);
  942                         break;
  943                 default:
  944                         break;
  945                 }
  946         }
  947 
  948         if (sc->sc_tx_timer == 0 && sc->sc_rx_timer == 0 &&
  949             sc->sc_mgt_timer == 0)
  950                 ifp->if_timer = 0;
  951         else
  952                 ifp->if_timer = 1;
  953         sc->sc_cansleep = ocansleep;
  954 }
  955 
  956 static void
  957 awi_start(ifp)
  958         struct ifnet *ifp;
  959 {
  960         struct awi_softc *sc = ifp->if_softc;
  961         struct mbuf *m0, *m;
  962         u_int32_t txd, frame, ntxd;
  963         u_int8_t rate;
  964         int len, sent = 0;
  965 
  966         for (;;) {
  967                 txd = sc->sc_txnext;
  968                 IF_DEQUEUE(&sc->sc_mgtq, m0);
  969                 if (m0 != NULL) {
  970                         if (awi_next_txd(sc, m0->m_pkthdr.len, &frame, &ntxd)) {
  971                                 IF_PREPEND(&sc->sc_mgtq, m0);
  972                                 ifp->if_flags |= IFF_OACTIVE;
  973                                 break;
  974                         }
  975                 } else {
  976                         if (!(ifp->if_flags & IFF_RUNNING))
  977                                 break;
  978                         IFQ_POLL(&ifp->if_snd, m0);
  979                         if (m0 == NULL)
  980                                 break;
  981                         len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
  982                         if (sc->sc_format_llc)
  983                                 len += sizeof(struct llc) -
  984                                     sizeof(struct ether_header);
  985                         if (sc->sc_wep_algo != NULL)
  986                                 len += IEEE80211_WEP_IVLEN +
  987                                     IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
  988                         if (awi_next_txd(sc, len, &frame, &ntxd)) {
  989                                 ifp->if_flags |= IFF_OACTIVE;
  990                                 break;
  991                         }
  992                         IFQ_DEQUEUE(&ifp->if_snd, m0);
  993                         AWI_BPF_MTAP(sc, m0, AWI_BPF_NORM, BPF_DIRECTION_OUT);
  994                         m0 = awi_fix_txhdr(sc, m0);
  995                         if (sc->sc_wep_algo != NULL && m0 != NULL)
  996                                 m0 = awi_wep_encrypt(sc, m0, 1);
  997                         if (m0 == NULL) {
  998                                 ifp->if_oerrors++;
  999                                 continue;
 1000                         }
 1001                         ifp->if_opackets++;
 1002                 }
 1003 #ifdef AWI_DEBUG
 1004                 if (awi_dump)
 1005                         awi_dump_pkt(sc, m0, -1);
 1006 #endif
 1007                 AWI_BPF_MTAP(sc, m0, AWI_BPF_RAW, BPF_DIRECTION_OUT);
 1008                 len = 0;
 1009                 for (m = m0; m != NULL; m = m->m_next) {
 1010                         awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *),
 1011                             m->m_len);
 1012                         len += m->m_len;
 1013                 }
 1014                 m_freem(m0);
 1015                 rate = sc->sc_tx_rate;  /*XXX*/
 1016                 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0);
 1017                 awi_write_4(sc, txd + AWI_TXD_START, frame);
 1018                 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd);
 1019                 awi_write_4(sc, txd + AWI_TXD_LENGTH, len);
 1020                 awi_write_1(sc, txd + AWI_TXD_RATE, rate);
 1021                 awi_write_4(sc, txd + AWI_TXD_NDA, 0);
 1022                 awi_write_4(sc, txd + AWI_TXD_NRA, 0);
 1023                 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN);
 1024                 sc->sc_txnext = ntxd;
 1025                 sent++;
 1026         }
 1027         if (sent) {
 1028                 if (sc->sc_tx_timer == 0)
 1029                         sc->sc_tx_timer = 5;
 1030                 ifp->if_timer = 1;
 1031 #ifdef AWI_DEBUG
 1032                 if (awi_verbose)
 1033                         printf("awi_start: sent %d txdone %d txnext %d txbase %d txend %d\n", sent, sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend);
 1034 #endif
 1035         }
 1036 }
 1037 
 1038 static void
 1039 awi_txint(sc)
 1040         struct awi_softc *sc;
 1041 {
 1042         struct ifnet *ifp = sc->sc_ifp;
 1043         u_int8_t flags;
 1044 
 1045         while (sc->sc_txdone != sc->sc_txnext) {
 1046                 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE);
 1047                 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE))
 1048                         break;
 1049                 if (flags & AWI_TXD_ST_ERROR)
 1050                         ifp->if_oerrors++;
 1051                 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) &
 1052                     0x7fff;
 1053         }
 1054         sc->sc_tx_timer = 0;
 1055         ifp->if_flags &= ~IFF_OACTIVE;
 1056 #ifdef AWI_DEBUG
 1057         if (awi_verbose)
 1058                 printf("awi_txint: txdone %d txnext %d txbase %d txend %d\n",
 1059                     sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend);
 1060 #endif
 1061         awi_start(ifp);
 1062 }
 1063 
 1064 static struct mbuf *
 1065 awi_fix_txhdr(sc, m0)
 1066         struct awi_softc *sc;
 1067         struct mbuf *m0;
 1068 {
 1069         struct ether_header eh;
 1070         struct ieee80211_frame *wh;
 1071         struct llc *llc;
 1072 
 1073         if (m0->m_len < sizeof(eh)) {
 1074                 m0 = m_pullup(m0, sizeof(eh));
 1075                 if (m0 == NULL)
 1076                         return NULL;
 1077         }
 1078         memcpy(&eh, mtod(m0, caddr_t), sizeof(eh));
 1079         if (sc->sc_format_llc) {
 1080                 m_adj(m0, sizeof(struct ether_header) - sizeof(struct llc));
 1081                 llc = mtod(m0, struct llc *);
 1082                 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
 1083                 llc->llc_control = LLC_UI;
 1084                 llc->llc_snap.org_code[0] = llc->llc_snap.org_code[1] = 
 1085                     llc->llc_snap.org_code[2] = 0;
 1086                 llc->llc_snap.ether_type = eh.ether_type;
 1087         }
 1088         M_PREPEND(m0, sizeof(struct ieee80211_frame), M_DONTWAIT);
 1089         if (m0 == NULL)
 1090                 return NULL;
 1091         wh = mtod(m0, struct ieee80211_frame *);
 1092 
 1093         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
 1094         LE_WRITE_2(wh->i_dur, 0);
 1095         LE_WRITE_2(wh->i_seq, 0);
 1096         if (sc->sc_mib_local.Network_Mode) {
 1097                 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
 1098                 memcpy(wh->i_addr1, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 1099                 memcpy(wh->i_addr2, eh.ether_shost, ETHER_ADDR_LEN);
 1100                 memcpy(wh->i_addr3, eh.ether_dhost, ETHER_ADDR_LEN);
 1101         } else {
 1102                 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 1103                 memcpy(wh->i_addr1, eh.ether_dhost, ETHER_ADDR_LEN);
 1104                 memcpy(wh->i_addr2, eh.ether_shost, ETHER_ADDR_LEN);
 1105                 memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 1106         }
 1107         return m0;
 1108 }
 1109 
 1110 static struct mbuf *
 1111 awi_fix_rxhdr(sc, m0)
 1112         struct awi_softc *sc;
 1113         struct mbuf *m0;
 1114 {
 1115         struct ieee80211_frame wh;
 1116         struct ether_header *eh;
 1117         struct llc *llc;
 1118 
 1119         if (m0->m_len < sizeof(wh)) {
 1120                 m_freem(m0);
 1121                 return NULL;
 1122         }
 1123         llc = (struct llc *)(mtod(m0, caddr_t) + sizeof(wh));
 1124         if (llc->llc_dsap == LLC_SNAP_LSAP &&
 1125             llc->llc_ssap == LLC_SNAP_LSAP &&
 1126             llc->llc_control == LLC_UI &&
 1127             llc->llc_snap.org_code[0] == 0 &&
 1128             llc->llc_snap.org_code[1] == 0 &&
 1129             llc->llc_snap.org_code[2] == 0) {
 1130                 memcpy(&wh, mtod(m0, caddr_t), sizeof(wh));
 1131                 m_adj(m0, sizeof(wh) + sizeof(*llc) - sizeof(*eh));
 1132                 eh = mtod(m0, struct ether_header *);
 1133                 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
 1134                 case IEEE80211_FC1_DIR_NODS:
 1135                         memcpy(eh->ether_dhost, wh.i_addr1, ETHER_ADDR_LEN);
 1136                         memcpy(eh->ether_shost, wh.i_addr2, ETHER_ADDR_LEN);
 1137                         break;
 1138                 case IEEE80211_FC1_DIR_TODS:
 1139                         memcpy(eh->ether_dhost, wh.i_addr3, ETHER_ADDR_LEN);
 1140                         memcpy(eh->ether_shost, wh.i_addr2, ETHER_ADDR_LEN);
 1141                         break;
 1142                 case IEEE80211_FC1_DIR_FROMDS:
 1143                         memcpy(eh->ether_dhost, wh.i_addr1, ETHER_ADDR_LEN);
 1144                         memcpy(eh->ether_shost, wh.i_addr3, ETHER_ADDR_LEN);
 1145                         break;
 1146                 case IEEE80211_FC1_DIR_DSTODS:
 1147                         m_freem(m0);
 1148                         return NULL;
 1149                 }
 1150         } else {
 1151                 /* assuming ethernet encapsulation, just strip 802.11 header */
 1152                 m_adj(m0, sizeof(wh));
 1153         }
 1154         if (ALIGN(mtod(m0, caddr_t) + sizeof(struct ether_header)) !=
 1155             (u_int)(mtod(m0, caddr_t) + sizeof(struct ether_header))) {
 1156                 /* XXX: we lose to estimate the type of encapsulation */
 1157                 struct mbuf *n, *n0, **np;
 1158                 caddr_t newdata;
 1159                 int off, oldmlen;
 1160 
 1161                 n0 = NULL;
 1162                 np = &n0;
 1163                 off = 0;
 1164                 oldmlen = m0->m_pkthdr.len;
 1165                 while (oldmlen > off) {
 1166                         if (n0 == NULL) {
 1167                                 MGETHDR(n, M_DONTWAIT, MT_DATA);
 1168                                 if (n == NULL) {
 1169                                         m_freem(m0);
 1170                                         return NULL;
 1171                                 }
 1172                                 M_MOVE_PKTHDR(n, m0);
 1173                                 n->m_len = MHLEN;
 1174                         } else {
 1175                                 MGET(n, M_DONTWAIT, MT_DATA);
 1176                                 if (n == NULL) {
 1177                                         m_freem(m0);
 1178                                         m_freem(n0);
 1179                                         return NULL;
 1180                                 }
 1181                                 n->m_len = MLEN;
 1182                         }
 1183                         if (oldmlen - off >= MINCLSIZE) {
 1184                                 MCLGET(n, M_DONTWAIT);
 1185                                 if (n->m_flags & M_EXT)
 1186                                         n->m_len = n->m_ext.ext_size;
 1187                         }
 1188                         if (n0 == NULL) {
 1189                                 newdata = (caddr_t)
 1190                                     ALIGN(n->m_data
 1191                                     + sizeof(struct ether_header))
 1192                                     - sizeof(struct ether_header);
 1193                                 n->m_len -= newdata - n->m_data;
 1194                                 n->m_data = newdata;
 1195                         }
 1196                         if (n->m_len > oldmlen - off)
 1197                                 n->m_len = oldmlen - off;
 1198                         m_copydata(m0, off, n->m_len, mtod(n, caddr_t));
 1199                         off += n->m_len;
 1200                         *np = n;
 1201                         np = &n->m_next;
 1202                 }
 1203                 m_freem(m0);
 1204                 m0 = n0;
 1205         }
 1206         return m0;
 1207 }
 1208 
 1209 static void
 1210 awi_input(sc, m, rxts, rssi)
 1211         struct awi_softc *sc;
 1212         struct mbuf *m;
 1213         u_int32_t rxts;
 1214         u_int8_t rssi;
 1215 {
 1216         struct ifnet *ifp = sc->sc_ifp;
 1217         struct ieee80211_frame *wh;
 1218 
 1219         /* trim CRC here for WEP can find its own CRC at the end of packet. */
 1220         m_adj(m, -ETHER_CRC_LEN);
 1221         AWI_BPF_MTAP(sc, m, AWI_BPF_RAW, BPF_DIRECTION_IN);
 1222         wh = mtod(m, struct ieee80211_frame *);
 1223         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
 1224             IEEE80211_FC0_VERSION_0) {
 1225                 printf("%s; receive packet with wrong version: %x\n",
 1226                     sc->sc_dev.dv_xname, wh->i_fc[0]);
 1227                 m_freem(m);
 1228                 ifp->if_ierrors++;
 1229                 return;
 1230         }
 1231         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 1232                 m = awi_wep_encrypt(sc, m, 0);
 1233                 if (m == NULL) {
 1234                         ifp->if_ierrors++;
 1235                         return;
 1236                 }
 1237                 wh = mtod(m, struct ieee80211_frame *);
 1238         }
 1239 #ifdef AWI_DEBUG
 1240         if (awi_dump)
 1241                 awi_dump_pkt(sc, m, rssi);
 1242 #endif
 1243 
 1244         if ((sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid) &&
 1245             sc->sc_status == AWI_ST_RUNNING) {
 1246                 if (memcmp(wh->i_addr2, sc->sc_bss.bssid, ETHER_ADDR_LEN) == 0) {
 1247                         sc->sc_rx_timer = 10;
 1248                         sc->sc_bss.rssi = rssi;
 1249                 }
 1250         }
 1251         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
 1252         case IEEE80211_FC0_TYPE_DATA:
 1253                 if (sc->sc_mib_local.Network_Mode) {
 1254                         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
 1255                             IEEE80211_FC1_DIR_FROMDS) {
 1256                                 m_freem(m);
 1257                                 return;
 1258                         }
 1259                 } else {
 1260                         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
 1261                             IEEE80211_FC1_DIR_NODS) {
 1262                                 m_freem(m);
 1263                                 return;
 1264                         }
 1265                 }
 1266                 m = awi_fix_rxhdr(sc, m);
 1267                 if (m == NULL) {
 1268                         ifp->if_ierrors++;
 1269                         break;
 1270                 }
 1271                 ifp->if_ipackets++;
 1272 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
 1273                 AWI_BPF_MTAP(sc, m, AWI_BPF_NORM, BPF_DIRECTION_IN);
 1274 #endif
 1275 #ifdef __NetBSD__
 1276                 (*ifp->if_input)(ifp, m);
 1277 #else
 1278                 ether_input_mbuf(ifp, m);
 1279 #endif
 1280                 break;
 1281         case IEEE80211_FC0_TYPE_MGT:
 1282                 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
 1283                    IEEE80211_FC1_DIR_NODS) {
 1284                         m_freem(m);
 1285                         return;
 1286                 }
 1287                 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
 1288                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 1289                 case IEEE80211_FC0_SUBTYPE_BEACON:
 1290                         awi_recv_beacon(sc, m, rxts, rssi);
 1291                         break;
 1292                 case IEEE80211_FC0_SUBTYPE_AUTH:
 1293                         awi_recv_auth(sc, m);
 1294                         break;
 1295                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 1296                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
 1297                         awi_recv_asresp(sc, m);
 1298                         break;
 1299                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
 1300                         if (sc->sc_mib_local.Network_Mode)
 1301                                 awi_send_auth(sc, 1);
 1302                         break;
 1303                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
 1304                         if (sc->sc_mib_local.Network_Mode)
 1305                                 awi_send_asreq(sc, 1);
 1306                         break;
 1307                 }
 1308                 m_freem(m);
 1309                 break;
 1310         case IEEE80211_FC0_TYPE_CTL:
 1311         default:
 1312                 /* should not come here */
 1313                 m_freem(m);
 1314                 break;
 1315         }
 1316 }
 1317 
 1318 static void
 1319 awi_rxint(sc)
 1320         struct awi_softc *sc;
 1321 {
 1322         u_int8_t state, rate, rssi;
 1323         u_int16_t len;
 1324         u_int32_t frame, next, rxts, rxoff;
 1325         struct mbuf *m;
 1326 
 1327         rxoff = sc->sc_rxdoff;
 1328         for (;;) {
 1329                 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE);
 1330                 if (state & AWI_RXD_ST_OWN)
 1331                         break;
 1332                 if (!(state & AWI_RXD_ST_CONSUMED)) {
 1333                         if (state & AWI_RXD_ST_RXERROR)
 1334                                 sc->sc_ifp->if_ierrors++;
 1335                         else {
 1336                                 len   = awi_read_2(sc, rxoff + AWI_RXD_LEN);
 1337                                 rate  = awi_read_1(sc, rxoff + AWI_RXD_RATE);
 1338                                 rssi  = awi_read_1(sc, rxoff + AWI_RXD_RSSI);
 1339                                 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) & 0x7fff;
 1340                                 rxts  = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME);
 1341                                 m = awi_devget(sc, frame, len);
 1342                                 if (state & AWI_RXD_ST_LF)
 1343                                         awi_input(sc, m, rxts, rssi);
 1344                                 else
 1345                                         sc->sc_rxpend = m;
 1346                         }
 1347                         state |= AWI_RXD_ST_CONSUMED;
 1348                         awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1349                 }
 1350                 next  = awi_read_4(sc, rxoff + AWI_RXD_NEXT);
 1351                 if (next & AWI_RXD_NEXT_LAST)
 1352                         break;
 1353                 /* make sure the next pointer is correct */
 1354                 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT))
 1355                         break;
 1356                 state |= AWI_RXD_ST_OWN;
 1357                 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
 1358                 rxoff = next & 0x7fff;
 1359         }
 1360         sc->sc_rxdoff = rxoff;
 1361 }
 1362 
 1363 static struct mbuf *
 1364 awi_devget(sc, off, len)
 1365         struct awi_softc *sc;
 1366         u_int32_t off;
 1367         u_int16_t len;
 1368 {
 1369         struct mbuf *m;
 1370         struct mbuf *top, **mp;
 1371         u_int tlen;
 1372 
 1373         top = sc->sc_rxpend;
 1374         mp = &top;
 1375         if (top != NULL) {
 1376                 sc->sc_rxpend = NULL;
 1377                 top->m_pkthdr.len += len;
 1378                 m = top;
 1379                 while (*mp != NULL) {
 1380                         m = *mp;
 1381                         mp = &m->m_next;
 1382                 }
 1383                 if (m->m_flags & M_EXT)
 1384                         tlen = m->m_ext.ext_size;
 1385                 else if (m->m_flags & M_PKTHDR)
 1386                         tlen = MHLEN;
 1387                 else
 1388                         tlen = MLEN;
 1389                 tlen -= m->m_len;
 1390                 if (tlen > len)
 1391                         tlen = len;
 1392                 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen);
 1393                 off += tlen;
 1394                 len -= tlen;
 1395         }
 1396 
 1397         while (len > 0) {
 1398                 if (top == NULL) {
 1399                         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1400                         if (m == NULL)
 1401                                 return NULL;
 1402                         m->m_pkthdr.rcvif = sc->sc_ifp;
 1403                         m->m_pkthdr.len = len;
 1404                         m->m_len = MHLEN;
 1405                 } else {
 1406                         MGET(m, M_DONTWAIT, MT_DATA);
 1407                         if (m == NULL) {
 1408                                 m_freem(top);
 1409                                 return NULL;
 1410                         }
 1411                         m->m_len = MLEN;
 1412                 }
 1413                 if (len >= MINCLSIZE) {
 1414                         MCLGET(m, M_DONTWAIT);
 1415                         if (m->m_flags & M_EXT)
 1416                                 m->m_len = m->m_ext.ext_size;
 1417                 }
 1418                 if (top == NULL) {
 1419                         int hdrlen = sizeof(struct ieee80211_frame) +
 1420                             (sc->sc_format_llc ? sizeof(struct llc) :
 1421                             sizeof(struct ether_header));
 1422                         caddr_t newdata = (caddr_t)
 1423                             ALIGN(m->m_data + hdrlen) - hdrlen;
 1424                         m->m_len -= newdata - m->m_data;
 1425                         m->m_data = newdata;
 1426                 }
 1427                 if (m->m_len > len)
 1428                         m->m_len = len;
 1429                 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len);
 1430                 off += m->m_len;
 1431                 len -= m->m_len;
 1432                 *mp = m;
 1433                 mp = &m->m_next;
 1434         }
 1435         return top;
 1436 }
 1437 
 1438 /*
 1439  * Initialize hardware and start firmware to accept commands.
 1440  * Called everytime after power on firmware.
 1441  */
 1442 
 1443 static int
 1444 awi_init_hw(sc)
 1445         struct awi_softc *sc;
 1446 {
 1447         u_int8_t status;
 1448         u_int16_t intmask;
 1449         int i, error;
 1450 
 1451         sc->sc_enab_intr = 0;
 1452         sc->sc_invalid = 0;     /* XXX: really? */
 1453         awi_drvstate(sc, AWI_DRV_RESET);
 1454 
 1455         /* reset firmware */
 1456         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1457         DELAY(100);
 1458         awi_write_1(sc, AWI_SELFTEST, 0);
 1459         awi_write_1(sc, AWI_CMD, 0);
 1460         awi_write_1(sc, AWI_BANNER, 0);
 1461         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET);
 1462         DELAY(100);
 1463 
 1464         /* wait for selftest completion */
 1465         for (i = 0; ; i++) {
 1466                 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) {
 1467                         printf("%s: failed to complete selftest (timeout)\n",
 1468                             sc->sc_dev.dv_xname);
 1469                         return ENXIO;
 1470                 }
 1471                 status = awi_read_1(sc, AWI_SELFTEST);
 1472                 if ((status & 0xf0) == 0xf0)
 1473                         break;
 1474                 if (sc->sc_cansleep) {
 1475                         sc->sc_sleep_cnt++;
 1476                         (void)tsleep(sc, PWAIT, "awitst", 1);
 1477                         sc->sc_sleep_cnt--;
 1478                 } else {
 1479                         DELAY(1000*1000/hz);
 1480                 }
 1481         }
 1482         if (status != AWI_SELFTEST_PASSED) {
 1483                 printf("%s: failed to complete selftest (code %x)\n",
 1484                     sc->sc_dev.dv_xname, status);
 1485                 return ENXIO;
 1486         }
 1487 
 1488         /* check banner to confirm firmware write it */
 1489         awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
 1490         if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
 1491                 printf("%s: failed to complete selftest (bad banner)\n",
 1492                     sc->sc_dev.dv_xname);
 1493                 for (i = 0; i < AWI_BANNER_LEN; i++)
 1494                         printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
 1495                 printf("\n");
 1496                 return ENXIO;
 1497         }
 1498 
 1499         /* initializing interrupt */
 1500         sc->sc_enab_intr = 1;
 1501         error = awi_intr_lock(sc);
 1502         if (error)
 1503                 return error;
 1504         intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT |
 1505             AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD;
 1506         awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff);
 1507         awi_write_1(sc, AWI_INTMASK2, 0);
 1508         awi_write_1(sc, AWI_INTSTAT, 0);
 1509         awi_write_1(sc, AWI_INTSTAT2, 0);
 1510         awi_intr_unlock(sc);
 1511         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
 1512 
 1513         /* issueing interface test command */
 1514         error = awi_cmd(sc, AWI_CMD_NOP);
 1515         if (error) {
 1516                 printf("%s: failed to complete selftest", sc->sc_dev.dv_xname);
 1517                 if (error == ENXIO)
 1518                         printf(" (no hardware)\n");
 1519                 else if (error != EWOULDBLOCK)
 1520                         printf(" (error %d)\n", error);
 1521                 else if (sc->sc_cansleep)
 1522                         printf(" (lost interrupt)\n");
 1523                 else
 1524                         printf(" (command timeout)\n");
 1525         }
 1526         return error;
 1527 }
 1528 
 1529 /*
 1530  * Extract the factory default MIB value from firmware and assign the driver
 1531  * default value.
 1532  * Called once at attaching the interface.
 1533  */
 1534 
 1535 static int
 1536 awi_init_mibs(sc)
 1537         struct awi_softc *sc;
 1538 {
 1539         int i, error;
 1540         u_int8_t *rate;
 1541 
 1542         if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL)) != 0 ||
 1543             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR)) != 0 ||
 1544             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC)) != 0 ||
 1545             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT)) != 0 ||
 1546             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY)) != 0) {
 1547                 printf("%s: failed to get default mib value (error %d)\n",
 1548                     sc->sc_dev.dv_xname, error);
 1549                 return error;
 1550         }
 1551 
 1552         rate = sc->sc_mib_phy.aSuprt_Data_Rates;
 1553         sc->sc_tx_rate = AWI_RATE_1MBIT;
 1554         for (i = 0; i < rate[1]; i++) {
 1555                 if (AWI_80211_RATE(rate[2 + i]) > sc->sc_tx_rate)
 1556                         sc->sc_tx_rate = AWI_80211_RATE(rate[2 + i]);
 1557         }
 1558         awi_init_region(sc);
 1559         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
 1560         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
 1561         sc->sc_mib_local.Fragmentation_Dis = 1;
 1562         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
 1563         sc->sc_mib_local.Power_Saving_Mode_Dis = 1;
 1564 
 1565         /* allocate buffers */
 1566         sc->sc_txbase = AWI_BUFFERS;
 1567         sc->sc_txend = sc->sc_txbase +
 1568             (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) +
 1569             sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS;
 1570         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase);
 1571         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size,
 1572             sc->sc_txend - sc->sc_txbase);
 1573         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend);
 1574         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size,
 1575             AWI_BUFFERS_END - sc->sc_txend);
 1576         sc->sc_mib_local.Network_Mode = 1;
 1577         sc->sc_mib_local.Acting_as_AP = 0;
 1578         return 0;
 1579 }
 1580 
 1581 /*
 1582  * Start transmitter and receiver of firmware
 1583  * Called after awi_init_hw() to start operation.
 1584  */
 1585 
 1586 static int
 1587 awi_init_txrx(sc)
 1588         struct awi_softc *sc;
 1589 {
 1590         int error;
 1591 
 1592         /* start transmitter */
 1593         sc->sc_txdone = sc->sc_txnext = sc->sc_txbase;
 1594         awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0);
 1595         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0);
 1596         awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0);
 1597         awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0);
 1598         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0);
 1599         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0);
 1600         awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0);
 1601         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_DATA, sc->sc_txbase);
 1602         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_MGT, 0);
 1603         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_BCAST, 0);
 1604         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_PS, 0);
 1605         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_CF, 0);
 1606         error = awi_cmd(sc, AWI_CMD_INIT_TX);
 1607         if (error)
 1608                 return error;
 1609 
 1610         /* start receiver */
 1611         if (sc->sc_rxpend) {
 1612                 m_freem(sc->sc_rxpend);
 1613                 sc->sc_rxpend = NULL;
 1614         }
 1615         error = awi_cmd(sc, AWI_CMD_INIT_RX);
 1616         if (error)
 1617                 return error;
 1618         sc->sc_rxdoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_DATA_DESC);
 1619         sc->sc_rxmoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_PS_DESC);
 1620         return 0;
 1621 }
 1622 
 1623 static void
 1624 awi_stop_txrx(sc)
 1625         struct awi_softc *sc;
 1626 {
 1627 
 1628         if (sc->sc_cmd_inprog)
 1629                 (void)awi_cmd_wait(sc);
 1630         (void)awi_cmd(sc, AWI_CMD_KILL_RX);
 1631         (void)awi_cmd_wait(sc);
 1632         sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX;
 1633         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_DATA, 1);
 1634         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_MGT, 0);
 1635         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_BCAST, 0);
 1636         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_PS, 0);
 1637         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_CF, 0);
 1638         (void)awi_cmd(sc, AWI_CMD_FLUSH_TX);
 1639         (void)awi_cmd_wait(sc);
 1640 }
 1641 
 1642 int
 1643 awi_init_region(sc)
 1644         struct awi_softc *sc;
 1645 {
 1646 
 1647         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1648                 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
 1649                 case AWI_REG_DOMAIN_US:
 1650                 case AWI_REG_DOMAIN_CA:
 1651                 case AWI_REG_DOMAIN_EU:
 1652                         sc->sc_scan_min = 0;
 1653                         sc->sc_scan_max = 77;
 1654                         break;
 1655                 case AWI_REG_DOMAIN_ES:
 1656                         sc->sc_scan_min = 0;
 1657                         sc->sc_scan_max = 26;
 1658                         break;
 1659                 case AWI_REG_DOMAIN_FR:
 1660                         sc->sc_scan_min = 0;
 1661                         sc->sc_scan_max = 32;
 1662                         break;
 1663                 case AWI_REG_DOMAIN_JP:
 1664                         sc->sc_scan_min = 6;
 1665                         sc->sc_scan_max = 17;
 1666                         break;
 1667                 default:
 1668                         return EINVAL;
 1669                 }
 1670                 sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
 1671         } else {
 1672                 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
 1673                 case AWI_REG_DOMAIN_US:
 1674                 case AWI_REG_DOMAIN_CA:
 1675                         sc->sc_scan_min = 1;
 1676                         sc->sc_scan_max = 11;
 1677                         sc->sc_scan_cur = 3;
 1678                         break;
 1679                 case AWI_REG_DOMAIN_EU:
 1680                         sc->sc_scan_min = 1;
 1681                         sc->sc_scan_max = 13;
 1682                         sc->sc_scan_cur = 3;
 1683                         break;
 1684                 case AWI_REG_DOMAIN_ES:
 1685                         sc->sc_scan_min = 10;
 1686                         sc->sc_scan_max = 11;
 1687                         sc->sc_scan_cur = 10;
 1688                         break;
 1689                 case AWI_REG_DOMAIN_FR:
 1690                         sc->sc_scan_min = 10;
 1691                         sc->sc_scan_max = 13;
 1692                         sc->sc_scan_cur = 10;
 1693                         break;
 1694                 case AWI_REG_DOMAIN_JP:
 1695                         sc->sc_scan_min = 14;
 1696                         sc->sc_scan_max = 14;
 1697                         sc->sc_scan_cur = 14;
 1698                         break;
 1699                 default:
 1700                         return EINVAL;
 1701                 }
 1702         }
 1703         sc->sc_ownch = sc->sc_scan_cur;
 1704         return 0;
 1705 }
 1706 
 1707 static int
 1708 awi_start_scan(sc)
 1709         struct awi_softc *sc;
 1710 {
 1711         int error = 0;
 1712         struct awi_bss *bp;
 1713 
 1714         while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
 1715                 TAILQ_REMOVE(&sc->sc_scan, bp, list);
 1716                 free(bp, M_DEVBUF);
 1717         }
 1718         if (!sc->sc_mib_local.Network_Mode && sc->sc_no_bssid) {
 1719                 memset(&sc->sc_bss, 0, sizeof(sc->sc_bss));
 1720                 sc->sc_bss.essid[0] = IEEE80211_ELEMID_SSID;
 1721                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1722                         sc->sc_bss.chanset = sc->sc_ownch % 3 + 1;
 1723                         sc->sc_bss.pattern = sc->sc_ownch;
 1724                         sc->sc_bss.index = 1;
 1725                         sc->sc_bss.dwell_time = 200;    /*XXX*/
 1726                 } else
 1727                         sc->sc_bss.chanset = sc->sc_ownch;
 1728                 sc->sc_status = AWI_ST_SETSS;
 1729                 error = awi_set_ss(sc);
 1730         } else {
 1731                 if (sc->sc_mib_local.Network_Mode)
 1732                         awi_drvstate(sc, AWI_DRV_INFSC);
 1733                 else
 1734                         awi_drvstate(sc, AWI_DRV_ADHSC);
 1735                 sc->sc_start_bss = 0;
 1736                 sc->sc_active_scan = 1;
 1737                 sc->sc_mgt_timer = AWI_ASCAN_WAIT / 1000;
 1738                 sc->sc_ifp->if_timer = 1;
 1739                 sc->sc_status = AWI_ST_SCAN;
 1740                 error = awi_cmd_scan(sc);
 1741         }
 1742         return error;
 1743 }
 1744 
 1745 static int
 1746 awi_next_scan(sc)
 1747         struct awi_softc *sc;
 1748 {
 1749         int error;
 1750 
 1751         for (;;) {
 1752                 /*
 1753                  * The pattern parameter for FH phy should be incremented
 1754                  * by 3.  But BayStack 650 Access Points apparently always
 1755                  * assign hop pattern set parameter to 1 for any pattern.
 1756                  * So we try all combinations of pattern/set parameters.
 1757                  * Since this causes no error, it may be a bug of
 1758                  * PCnetMobile firmware.
 1759                  */
 1760                 sc->sc_scan_cur++;
 1761                 if (sc->sc_scan_cur > sc->sc_scan_max) {
 1762                         sc->sc_scan_cur = sc->sc_scan_min;
 1763                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
 1764                                 sc->sc_scan_set = sc->sc_scan_set % 3 + 1;
 1765                 }
 1766                 error = awi_cmd_scan(sc);
 1767                 if (error != EINVAL)
 1768                         break;
 1769         }
 1770         return error;
 1771 }
 1772 
 1773 static void
 1774 awi_stop_scan(sc)
 1775         struct awi_softc *sc;
 1776 {
 1777         struct ifnet *ifp = sc->sc_ifp;
 1778         struct awi_bss *bp, *sbp;
 1779         int fail;
 1780 
 1781         bp = TAILQ_FIRST(&sc->sc_scan);
 1782         if (bp == NULL) {
 1783   notfound:
 1784                 if (sc->sc_active_scan) {
 1785                         if (ifp->if_flags & IFF_DEBUG)
 1786                                 printf("%s: entering passive scan mode\n",
 1787                                     sc->sc_dev.dv_xname);
 1788                         sc->sc_active_scan = 0;
 1789                 }
 1790                 sc->sc_mgt_timer = AWI_PSCAN_WAIT / 1000;
 1791                 ifp->if_timer = 1;
 1792                 (void)awi_next_scan(sc);
 1793                 return;
 1794         }
 1795         sbp = NULL;
 1796         if (ifp->if_flags & IFF_DEBUG)
 1797                 printf("%s:\tmacaddr     ch/pat   sig flag  wep  essid\n",
 1798                     sc->sc_dev.dv_xname);
 1799         for (; bp != NULL; bp = TAILQ_NEXT(bp, list)) {
 1800                 if (bp->fails) {
 1801                         /*
 1802                          * The configuration of the access points may change
 1803                          * during my scan.  So we retries to associate with
 1804                          * it unless there are any suitable AP.
 1805                          */
 1806                         if (bp->fails++ < 3)
 1807                                 continue;
 1808                         bp->fails = 0;
 1809                 }
 1810                 fail = 0;
 1811                 /*
 1812                  * Since the firmware apparently scans not only the specified
 1813                  * channel of SCAN command but all available channel within
 1814                  * the region, we should filter out unnecessary responses here.
 1815                  */
 1816                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1817                         if (bp->pattern < sc->sc_scan_min ||
 1818                             bp->pattern > sc->sc_scan_max)
 1819                                 fail |= 0x01;
 1820                 } else {
 1821                         if (bp->chanset < sc->sc_scan_min ||
 1822                             bp->chanset > sc->sc_scan_max)
 1823                                 fail |= 0x01;
 1824                 }
 1825                 if (sc->sc_mib_local.Network_Mode) {
 1826                         if (!(bp->capinfo & IEEE80211_CAPINFO_ESS) ||
 1827                             (bp->capinfo & IEEE80211_CAPINFO_IBSS))
 1828                                 fail |= 0x02;
 1829                 } else {
 1830                         if ((bp->capinfo & IEEE80211_CAPINFO_ESS) ||
 1831                             !(bp->capinfo & IEEE80211_CAPINFO_IBSS))
 1832                                 fail |= 0x02;
 1833                 }
 1834                 if (sc->sc_wep_algo == NULL) {
 1835                         if (bp->capinfo & IEEE80211_CAPINFO_PRIVACY)
 1836                                 fail |= 0x04;
 1837                 } else {
 1838                         if (!(bp->capinfo & IEEE80211_CAPINFO_PRIVACY))
 1839                                 fail |= 0x04;
 1840                 }
 1841                 if (sc->sc_mib_mac.aDesired_ESS_ID[1] != 0 &&
 1842                     memcmp(&sc->sc_mib_mac.aDesired_ESS_ID, bp->essid,
 1843                     sizeof(bp->essid)) != 0)
 1844                         fail |= 0x08;
 1845                 if (ifp->if_flags & IFF_DEBUG) {
 1846                         printf(" %c %s", fail ? '-' : '+',
 1847                             ether_sprintf(bp->esrc));
 1848                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
 1849                                 printf("  %2d/%d%c", bp->pattern, bp->chanset,
 1850                                     fail & 0x01 ? '!' : ' ');
 1851                         else
 1852                                 printf("  %4d%c", bp->chanset,
 1853                                     fail & 0x01 ? '!' : ' ');
 1854                         printf(" %+4d", bp->rssi);
 1855                         printf(" %4s%c",
 1856                             (bp->capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
 1857                             (bp->capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
 1858                             "????",
 1859                             fail & 0x02 ? '!' : ' ');
 1860                         printf(" %3s%c ",
 1861                             (bp->capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" :
 1862                             "no",
 1863                             fail & 0x04 ? '!' : ' ');
 1864                         awi_print_essid(bp->essid);
 1865                         printf("%s\n", fail & 0x08 ? "!" : "");
 1866                 }
 1867                 if (!fail) {
 1868                         if (sbp == NULL || bp->rssi > sbp->rssi)
 1869                                 sbp = bp;
 1870                 }
 1871         }
 1872         if (sbp == NULL)
 1873                 goto notfound;
 1874         sc->sc_bss = *sbp;
 1875         (void)awi_set_ss(sc);
 1876 }
 1877 
 1878 static void
 1879 awi_recv_beacon(sc, m0, rxts, rssi)
 1880         struct awi_softc *sc;
 1881         struct mbuf *m0;
 1882         u_int32_t rxts;
 1883         u_int8_t rssi;
 1884 {
 1885         struct ieee80211_frame *wh;
 1886         struct awi_bss *bp;
 1887         u_int8_t *frame, *eframe;
 1888         u_int8_t *tstamp, *bintval, *capinfo, *ssid, *rates, *parms;
 1889 
 1890         if (sc->sc_status != AWI_ST_SCAN)
 1891                 return;
 1892         wh = mtod(m0, struct ieee80211_frame *);
 1893 
 1894         frame = (u_int8_t *)&wh[1];
 1895         eframe = mtod(m0, u_int8_t *) + m0->m_len;
 1896         /*
 1897          * XXX:
 1898          *      timestamp [8]
 1899          *      beacon interval [2]
 1900          *      capability information [2]
 1901          *      ssid [tlv]
 1902          *      supported rates [tlv]
 1903          *      parameter set [tlv]
 1904          *      ...
 1905          */
 1906         if (frame + 12 > eframe) {
 1907 #ifdef AWI_DEBUG
 1908                 if (awi_verbose)
 1909                         printf("awi_recv_beacon: frame too short \n");
 1910 #endif
 1911                 return;
 1912         }
 1913         tstamp = frame;
 1914         frame += 8;
 1915         bintval = frame;
 1916         frame += 2;
 1917         capinfo = frame;
 1918         frame += 2;
 1919 
 1920         ssid = rates = parms = NULL;
 1921         while (frame < eframe) {
 1922                 switch (*frame) {
 1923                 case IEEE80211_ELEMID_SSID:
 1924                         ssid = frame;
 1925                         break;
 1926                 case IEEE80211_ELEMID_RATES:
 1927                         rates = frame;
 1928                         break;
 1929                 case IEEE80211_ELEMID_FHPARMS:
 1930                 case IEEE80211_ELEMID_DSPARMS:
 1931                         parms = frame;
 1932                         break;
 1933                 }
 1934                 frame += frame[1] + 2;
 1935         }
 1936         if (ssid == NULL || rates == NULL || parms == NULL) {
 1937 #ifdef AWI_DEBUG
 1938                 if (awi_verbose)
 1939                         printf("awi_recv_beacon: ssid=%p, rates=%p, parms=%p\n",
 1940                             ssid, rates, parms);
 1941 #endif
 1942                 return;
 1943         }
 1944         if (ssid[1] > IEEE80211_NWID_LEN) {
 1945 #ifdef AWI_DEBUG
 1946                 if (awi_verbose)
 1947                         printf("awi_recv_beacon: bad ssid len: %d from %s\n",
 1948                             ssid[1], ether_sprintf(wh->i_addr2));
 1949 #endif
 1950                 return;
 1951         }
 1952 
 1953         for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
 1954             bp = TAILQ_NEXT(bp, list)) {
 1955                 if (memcmp(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN) == 0 &&
 1956                     memcmp(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN) == 0)
 1957                         break;
 1958         }
 1959         if (bp == NULL) {
 1960                 bp = malloc(sizeof(struct awi_bss), M_DEVBUF, M_NOWAIT);
 1961                 if (bp == NULL)
 1962                         return;
 1963                 TAILQ_INSERT_TAIL(&sc->sc_scan, bp, list);
 1964                 memcpy(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN);
 1965                 memcpy(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN);
 1966                 memset(bp->essid, 0, sizeof(bp->essid));
 1967                 memcpy(bp->essid, ssid, 2 + ssid[1]);
 1968         }
 1969         bp->rssi = rssi;
 1970         bp->rxtime = rxts;
 1971         memcpy(bp->timestamp, tstamp, sizeof(bp->timestamp));
 1972         bp->interval = LE_READ_2(bintval);
 1973         bp->capinfo = LE_READ_2(capinfo);
 1974         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 1975                 bp->chanset = parms[4];
 1976                 bp->pattern = parms[5];
 1977                 bp->index = parms[6];
 1978                 bp->dwell_time = LE_READ_2(parms + 2);
 1979         } else {
 1980                 bp->chanset = parms[2];
 1981                 bp->pattern = 0;
 1982                 bp->index = 0;
 1983                 bp->dwell_time = 0;
 1984         }
 1985         if (sc->sc_mgt_timer == 0)
 1986                 awi_stop_scan(sc);
 1987 }
 1988 
 1989 static int
 1990 awi_set_ss(sc)
 1991         struct awi_softc *sc;
 1992 {
 1993         struct ifnet *ifp = sc->sc_ifp;
 1994         struct awi_bss *bp;
 1995         int error;
 1996 
 1997         sc->sc_status = AWI_ST_SETSS;
 1998         bp = &sc->sc_bss;
 1999         if (ifp->if_flags & IFF_DEBUG) {
 2000                 printf("%s: ch %d pat %d id %d dw %d iv %d bss %s ssid ",
 2001                     sc->sc_dev.dv_xname, bp->chanset,
 2002                     bp->pattern, bp->index, bp->dwell_time, bp->interval,
 2003                     ether_sprintf(bp->bssid));
 2004                 awi_print_essid(bp->essid);
 2005                 printf("\n");
 2006         }
 2007         memcpy(&sc->sc_mib_mgt.aCurrent_BSS_ID, bp->bssid, ETHER_ADDR_LEN);
 2008         memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID, bp->essid,
 2009             AWI_ESS_ID_SIZE);
 2010         LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, bp->interval);
 2011         error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT);
 2012         return error;
 2013 }
 2014 
 2015 static void
 2016 awi_try_sync(sc)
 2017         struct awi_softc *sc;
 2018 {
 2019         struct awi_bss *bp;
 2020 
 2021         sc->sc_status = AWI_ST_SYNC;
 2022         bp = &sc->sc_bss;
 2023 
 2024         if (sc->sc_cmd_inprog) {
 2025                 if (awi_cmd_wait(sc))
 2026                         return;
 2027         }
 2028         sc->sc_cmd_inprog = AWI_CMD_SYNC;
 2029         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_SET, bp->chanset);
 2030         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_PATTERN, bp->pattern);
 2031         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_IDX, bp->index);
 2032         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_STARTBSS,
 2033             sc->sc_start_bss ? 1 : 0); 
 2034         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_DWELL, bp->dwell_time);
 2035         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_MBZ, 0);
 2036         awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_TIMESTAMP,
 2037             bp->timestamp, 8);
 2038         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_REFTIME, bp->rxtime);
 2039         (void)awi_cmd(sc, AWI_CMD_SYNC);
 2040 }
 2041 
 2042 static void
 2043 awi_sync_done(sc)
 2044         struct awi_softc *sc;
 2045 {
 2046         struct ifnet *ifp = sc->sc_ifp;
 2047 
 2048         if (sc->sc_mib_local.Network_Mode) {
 2049                 awi_drvstate(sc, AWI_DRV_INFSY);
 2050                 awi_send_auth(sc, 1);
 2051         } else {
 2052                 if (ifp->if_flags & IFF_DEBUG) {
 2053                         printf("%s: synced with", sc->sc_dev.dv_xname);
 2054                         if (sc->sc_no_bssid)
 2055                                 printf(" no-bssid");
 2056                         else {
 2057                                 printf(" %s ssid ",
 2058                                     ether_sprintf(sc->sc_bss.bssid));
 2059                                 awi_print_essid(sc->sc_bss.essid);
 2060                         }
 2061                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
 2062                                 printf(" at chanset %d pattern %d\n",
 2063                                     sc->sc_bss.chanset, sc->sc_bss.pattern);
 2064                         else
 2065                                 printf(" at channel %d\n", sc->sc_bss.chanset);
 2066                 }
 2067                 awi_drvstate(sc, AWI_DRV_ADHSY);
 2068                 sc->sc_status = AWI_ST_RUNNING;
 2069                 ifp->if_flags |= IFF_RUNNING;
 2070                 awi_start(ifp);
 2071         }
 2072 }
 2073 
 2074 static void
 2075 awi_send_deauth(sc)
 2076         struct awi_softc *sc;
 2077 {
 2078         struct ifnet *ifp = sc->sc_ifp;
 2079         struct mbuf *m;
 2080         struct ieee80211_frame *wh;
 2081         u_int8_t *deauth;
 2082 
 2083         MGETHDR(m, M_DONTWAIT, MT_DATA);
 2084         if (m == NULL)
 2085                 return;
 2086         if (ifp->if_flags & IFF_DEBUG)
 2087                 printf("%s: sending deauth to %s\n", sc->sc_dev.dv_xname,
 2088                     ether_sprintf(sc->sc_bss.bssid));
 2089 
 2090         wh = mtod(m, struct ieee80211_frame *);
 2091         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
 2092             IEEE80211_FC0_SUBTYPE_AUTH;
 2093         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 2094         LE_WRITE_2(wh->i_dur, 0);
 2095         LE_WRITE_2(wh->i_seq, 0);
 2096         memcpy(wh->i_addr1, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 2097         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
 2098         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 2099 
 2100         deauth = (u_int8_t *)&wh[1];
 2101         LE_WRITE_2(deauth, IEEE80211_REASON_AUTH_LEAVE);
 2102         deauth += 2;
 2103 
 2104         m->m_pkthdr.len = m->m_len = deauth - mtod(m, u_int8_t *);
 2105         IF_ENQUEUE(&sc->sc_mgtq, m);
 2106         awi_start(ifp);
 2107         awi_drvstate(sc, AWI_DRV_INFTOSS);
 2108 }
 2109 
 2110 static void
 2111 awi_send_auth(sc, seq)
 2112         struct awi_softc *sc;
 2113         int seq;
 2114 {
 2115         struct ifnet *ifp = sc->sc_ifp;
 2116         struct mbuf *m;
 2117         struct ieee80211_frame *wh;
 2118         u_int8_t *auth;
 2119 
 2120         MGETHDR(m, M_DONTWAIT, MT_DATA);
 2121         if (m == NULL)
 2122                 return;
 2123         sc->sc_status = AWI_ST_AUTH;
 2124         if (ifp->if_flags & IFF_DEBUG)
 2125                 printf("%s: sending auth to %s\n", sc->sc_dev.dv_xname,
 2126                     ether_sprintf(sc->sc_bss.bssid));
 2127 
 2128         wh = mtod(m, struct ieee80211_frame *);
 2129         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
 2130             IEEE80211_FC0_SUBTYPE_AUTH;
 2131         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 2132         LE_WRITE_2(wh->i_dur, 0);
 2133         LE_WRITE_2(wh->i_seq, 0);
 2134         memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN);
 2135         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
 2136         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 2137 
 2138         auth = (u_int8_t *)&wh[1];
 2139         /* algorithm number */
 2140         LE_WRITE_2(auth, IEEE80211_AUTH_ALG_OPEN);
 2141         auth += 2;
 2142         /* sequence number */
 2143         LE_WRITE_2(auth, seq);
 2144         auth += 2;
 2145         /* status */
 2146         LE_WRITE_2(auth, 0);
 2147         auth += 2;
 2148 
 2149         m->m_pkthdr.len = m->m_len = auth - mtod(m, u_int8_t *);
 2150         IF_ENQUEUE(&sc->sc_mgtq, m);
 2151         awi_start(ifp);
 2152 
 2153         sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000;
 2154         ifp->if_timer = 1;
 2155 }
 2156 
 2157 static void
 2158 awi_recv_auth(sc, m0)
 2159         struct awi_softc *sc;
 2160         struct mbuf *m0;
 2161 {
 2162         struct ieee80211_frame *wh;
 2163         u_int8_t *auth, *eframe;
 2164         struct awi_bss *bp;
 2165         u_int16_t status;
 2166 
 2167         wh = mtod(m0, struct ieee80211_frame *);
 2168         auth = (u_int8_t *)&wh[1];
 2169         eframe = mtod(m0, u_int8_t *) + m0->m_len;
 2170         if (sc->sc_ifp->if_flags & IFF_DEBUG)
 2171                 printf("%s: receive auth from %s\n", sc->sc_dev.dv_xname,
 2172                     ether_sprintf(wh->i_addr2));
 2173 
 2174         /* algorithm number */
 2175         if (LE_READ_2(auth) != IEEE80211_AUTH_ALG_OPEN)
 2176                 return;
 2177         auth += 2;
 2178         if (!sc->sc_mib_local.Network_Mode) {
 2179                 if (sc->sc_status != AWI_ST_RUNNING)
 2180                         return;
 2181                 if (LE_READ_2(auth) == 1)
 2182                         awi_send_auth(sc, 2);
 2183                 return;
 2184         }
 2185         if (sc->sc_status != AWI_ST_AUTH)
 2186                 return;
 2187         /* sequence number */
 2188         if (LE_READ_2(auth) != 2)
 2189                 return;
 2190         auth += 2;
 2191         /* status */
 2192         status = LE_READ_2(auth);
 2193         if (status != 0) {
 2194                 printf("%s: authentication failed (reason %d)\n",
 2195                     sc->sc_dev.dv_xname, status);
 2196                 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
 2197                     bp = TAILQ_NEXT(bp, list)) {
 2198                         if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN)
 2199                             == 0) {
 2200                                 bp->fails++;
 2201                                 break;
 2202                         }
 2203                 }
 2204                 return;
 2205         }
 2206         sc->sc_mgt_timer = 0;
 2207         awi_drvstate(sc, AWI_DRV_INFAUTH);
 2208         awi_send_asreq(sc, 0);
 2209 }
 2210 
 2211 static void
 2212 awi_send_asreq(sc, reassoc)
 2213         struct awi_softc *sc;
 2214         int reassoc;
 2215 {
 2216         struct ifnet *ifp = sc->sc_ifp;
 2217         struct mbuf *m;
 2218         struct ieee80211_frame *wh;
 2219         u_int16_t lintval;
 2220         u_int8_t *asreq;
 2221 
 2222         MGETHDR(m, M_DONTWAIT, MT_DATA);
 2223         if (m == NULL)
 2224                 return;
 2225         sc->sc_status = AWI_ST_ASSOC;
 2226         if (ifp->if_flags & IFF_DEBUG)
 2227                 printf("%s: sending %sassoc req to %s\n", sc->sc_dev.dv_xname,
 2228                     reassoc ? "re" : "",
 2229                     ether_sprintf(sc->sc_bss.bssid));
 2230 
 2231         wh = mtod(m, struct ieee80211_frame *);
 2232         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT;
 2233         if (reassoc)
 2234                 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
 2235         else
 2236                 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
 2237         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 2238         LE_WRITE_2(wh->i_dur, 0);
 2239         LE_WRITE_2(wh->i_seq, 0);
 2240         memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN);
 2241         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
 2242         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 2243 
 2244         asreq = (u_int8_t *)&wh[1];
 2245 
 2246         /* capability info */
 2247         if (sc->sc_wep_algo == NULL)
 2248                 LE_WRITE_2(asreq, IEEE80211_CAPINFO_CF_POLLABLE);
 2249         else
 2250                 LE_WRITE_2(asreq,
 2251                     IEEE80211_CAPINFO_CF_POLLABLE | IEEE80211_CAPINFO_PRIVACY);
 2252         asreq += 2;
 2253         /* listen interval */
 2254         lintval = LE_READ_2(&sc->sc_mib_mgt.aListen_Interval);
 2255         LE_WRITE_2(asreq, lintval);
 2256         asreq += 2;
 2257         if (reassoc) {
 2258                 /* current AP address */
 2259                 memcpy(asreq, sc->sc_bss.bssid, ETHER_ADDR_LEN);
 2260                 asreq += ETHER_ADDR_LEN;
 2261         }
 2262         /* ssid */
 2263         memcpy(asreq, sc->sc_bss.essid, 2 + sc->sc_bss.essid[1]);
 2264         asreq += 2 + asreq[1];
 2265         /* supported rates */
 2266         memcpy(asreq, &sc->sc_mib_phy.aSuprt_Data_Rates, 4);
 2267         asreq += 2 + asreq[1];
 2268 
 2269         m->m_pkthdr.len = m->m_len = asreq - mtod(m, u_int8_t *);
 2270         IF_ENQUEUE(&sc->sc_mgtq, m);
 2271         awi_start(ifp);
 2272 
 2273         sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000;
 2274         ifp->if_timer = 1;
 2275 }
 2276 
 2277 static void
 2278 awi_recv_asresp(sc, m0)
 2279         struct awi_softc *sc;
 2280         struct mbuf *m0;
 2281 {
 2282         struct ieee80211_frame *wh;
 2283         u_int8_t *asresp, *eframe;
 2284         u_int16_t status;
 2285         u_int8_t rate, *phy_rates;
 2286         struct awi_bss *bp;
 2287         int i, j;
 2288 
 2289         wh = mtod(m0, struct ieee80211_frame *);
 2290         asresp = (u_int8_t *)&wh[1];
 2291         eframe = mtod(m0, u_int8_t *) + m0->m_len;
 2292         if (sc->sc_ifp->if_flags & IFF_DEBUG)
 2293                 printf("%s: receive assoc resp from %s\n", sc->sc_dev.dv_xname,
 2294                     ether_sprintf(wh->i_addr2));
 2295 
 2296         if (!sc->sc_mib_local.Network_Mode)
 2297                 return;
 2298 
 2299         if (sc->sc_status != AWI_ST_ASSOC)
 2300                 return;
 2301         /* capability info */
 2302         asresp += 2;
 2303         /* status */
 2304         status = LE_READ_2(asresp);
 2305         if (status != 0) {
 2306                 printf("%s: association failed (reason %d)\n",
 2307                     sc->sc_dev.dv_xname, status);
 2308                 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
 2309                     bp = TAILQ_NEXT(bp, list)) {
 2310                         if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN)
 2311                             == 0) {
 2312                                 bp->fails++;
 2313                                 break;
 2314                         }
 2315                 }
 2316                 return;
 2317         }
 2318         asresp += 2;
 2319         /* association id */
 2320         asresp += 2;
 2321         /* supported rates */
 2322         rate = AWI_RATE_1MBIT;
 2323         for (i = 0; i < asresp[1]; i++) {
 2324                 if (AWI_80211_RATE(asresp[2 + i]) <= rate)
 2325                         continue;
 2326                 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
 2327                 for (j = 0; j < phy_rates[1]; j++) {
 2328                         if (AWI_80211_RATE(asresp[2 + i]) ==
 2329                             AWI_80211_RATE(phy_rates[2 + j]))
 2330                                 rate = AWI_80211_RATE(asresp[2 + i]);
 2331                 }
 2332         }
 2333         if (sc->sc_ifp->if_flags & IFF_DEBUG) {
 2334                 printf("%s: associated with %s ssid ",
 2335                     sc->sc_dev.dv_xname, ether_sprintf(sc->sc_bss.bssid));
 2336                 awi_print_essid(sc->sc_bss.essid);
 2337                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
 2338                         printf(" chanset %d pattern %d\n",
 2339                             sc->sc_bss.chanset, sc->sc_bss.pattern);
 2340                 else
 2341                         printf(" channel %d\n", sc->sc_bss.chanset);
 2342         }
 2343         sc->sc_tx_rate = rate;
 2344         sc->sc_mgt_timer = 0;
 2345         sc->sc_rx_timer = 10;
 2346         sc->sc_ifp->if_timer = 1;
 2347         sc->sc_status = AWI_ST_RUNNING;
 2348         sc->sc_ifp->if_flags |= IFF_RUNNING;
 2349         awi_drvstate(sc, AWI_DRV_INFASSOC);
 2350         awi_start(sc->sc_ifp);
 2351 }
 2352 
 2353 static int
 2354 awi_mib(sc, cmd, mib)
 2355         struct awi_softc *sc;
 2356         u_int8_t cmd;
 2357         u_int8_t mib;
 2358 {
 2359         int error;
 2360         u_int8_t size, *ptr;
 2361 
 2362         switch (mib) {
 2363         case AWI_MIB_LOCAL:
 2364                 ptr = (u_int8_t *)&sc->sc_mib_local;
 2365                 size = sizeof(sc->sc_mib_local);
 2366                 break;
 2367         case AWI_MIB_ADDR:
 2368                 ptr = (u_int8_t *)&sc->sc_mib_addr;
 2369                 size = sizeof(sc->sc_mib_addr);
 2370                 break;
 2371         case AWI_MIB_MAC:
 2372                 ptr = (u_int8_t *)&sc->sc_mib_mac;
 2373                 size = sizeof(sc->sc_mib_mac);
 2374                 break;
 2375         case AWI_MIB_STAT:
 2376                 ptr = (u_int8_t *)&sc->sc_mib_stat;
 2377                 size = sizeof(sc->sc_mib_stat);
 2378                 break;
 2379         case AWI_MIB_MGT:
 2380                 ptr = (u_int8_t *)&sc->sc_mib_mgt;
 2381                 size = sizeof(sc->sc_mib_mgt);
 2382                 break;
 2383         case AWI_MIB_PHY:
 2384                 ptr = (u_int8_t *)&sc->sc_mib_phy;
 2385                 size = sizeof(sc->sc_mib_phy);
 2386                 break;
 2387         default:
 2388                 return EINVAL;
 2389         }
 2390         if (sc->sc_cmd_inprog) {
 2391                 error = awi_cmd_wait(sc);
 2392                 if (error) {
 2393                         if (error == EWOULDBLOCK)
 2394                                 printf("awi_mib: cmd %d inprog",
 2395                                     sc->sc_cmd_inprog);
 2396                         return error;
 2397                 }
 2398         }
 2399         sc->sc_cmd_inprog = cmd;
 2400         if (cmd == AWI_CMD_SET_MIB)
 2401                 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size);
 2402         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, mib);
 2403         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, size);
 2404         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX, 0);
 2405         error = awi_cmd(sc, cmd);
 2406         if (error)
 2407                 return error;
 2408         if (cmd == AWI_CMD_GET_MIB) {
 2409                 awi_read_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size);
 2410 #ifdef AWI_DEBUG
 2411                 if (awi_verbose) {
 2412                         int i;
 2413 
 2414                         printf("awi_mib: #%d:", mib);
 2415                         for (i = 0; i < size; i++)
 2416                                 printf(" %02x", ptr[i]);
 2417                         printf("\n");
 2418                 }
 2419 #endif
 2420         }
 2421         return 0;
 2422 }
 2423 
 2424 static int
 2425 awi_cmd_scan(sc)
 2426         struct awi_softc *sc;
 2427 {
 2428         int error;
 2429         u_int8_t scan_mode;
 2430 
 2431         if (sc->sc_active_scan)
 2432                 scan_mode = AWI_SCAN_ACTIVE;
 2433         else
 2434                 scan_mode = AWI_SCAN_PASSIVE;
 2435         if (sc->sc_mib_mgt.aScan_Mode != scan_mode) {
 2436                 sc->sc_mib_mgt.aScan_Mode = scan_mode;
 2437                 error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT);
 2438                 return error;
 2439         }
 2440 
 2441         if (sc->sc_cmd_inprog) {
 2442                 error = awi_cmd_wait(sc);
 2443                 if (error)
 2444                         return error;
 2445         }
 2446         sc->sc_cmd_inprog = AWI_CMD_SCAN;
 2447         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_DURATION,
 2448             sc->sc_active_scan ? AWI_ASCAN_DURATION : AWI_PSCAN_DURATION);
 2449         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
 2450                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
 2451                     sc->sc_scan_set);
 2452                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN,
 2453                     sc->sc_scan_cur);
 2454                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 1);
 2455         } else {
 2456                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
 2457                     sc->sc_scan_cur);
 2458                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN, 0);
 2459                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 0);
 2460         }
 2461         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SUSP, 0);
 2462         return awi_cmd(sc, AWI_CMD_SCAN);
 2463 }
 2464 
 2465 static int
 2466 awi_cmd(sc, cmd)
 2467         struct awi_softc *sc;
 2468         u_int8_t cmd;
 2469 {
 2470         u_int8_t status;
 2471         int error = 0;
 2472 
 2473         sc->sc_cmd_inprog = cmd;
 2474         awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE);
 2475         awi_write_1(sc, AWI_CMD, cmd);
 2476         if (sc->sc_status != AWI_ST_INIT)
 2477                 return 0;
 2478         error = awi_cmd_wait(sc);
 2479         if (error)
 2480                 return error;
 2481         status = awi_read_1(sc, AWI_CMD_STATUS);
 2482         awi_write_1(sc, AWI_CMD, 0);
 2483         switch (status) {
 2484         case AWI_STAT_OK:
 2485                 break;
 2486         case AWI_STAT_BADPARM:
 2487                 return EINVAL;
 2488         default:
 2489                 printf("%s: command %d failed %x\n",
 2490                     sc->sc_dev.dv_xname, cmd, status);
 2491                 return ENXIO;
 2492         }
 2493         return 0;
 2494 }
 2495 
 2496 static void
 2497 awi_cmd_done(sc)
 2498         struct awi_softc *sc;
 2499 {
 2500         u_int8_t cmd, status;
 2501 
 2502         status = awi_read_1(sc, AWI_CMD_STATUS);
 2503         if (status == AWI_STAT_IDLE)
 2504                 return;         /* stray interrupt */
 2505 
 2506         cmd = sc->sc_cmd_inprog;
 2507         sc->sc_cmd_inprog = 0;
 2508         if (sc->sc_status == AWI_ST_INIT) {
 2509                 wakeup(sc);
 2510                 return;
 2511         }
 2512         awi_write_1(sc, AWI_CMD, 0);
 2513 
 2514         if (status != AWI_STAT_OK) {
 2515                 printf("%s: command %d failed %x\n",
 2516                     sc->sc_dev.dv_xname, cmd, status);
 2517                 return;
 2518         }
 2519         switch (sc->sc_status) {
 2520         case AWI_ST_SCAN:
 2521                 if (cmd == AWI_CMD_SET_MIB)
 2522                         awi_cmd_scan(sc);       /* retry */
 2523                 break;
 2524         case AWI_ST_SETSS:
 2525                 awi_try_sync(sc);
 2526                 break;
 2527         case AWI_ST_SYNC:
 2528                 awi_sync_done(sc);
 2529                 break;
 2530         default:
 2531                 break;
 2532         }
 2533 }
 2534 
 2535 static int
 2536 awi_next_txd(sc, len, framep, ntxdp)
 2537         struct awi_softc *sc;
 2538         int len;
 2539         u_int32_t *framep, *ntxdp;
 2540 {
 2541         u_int32_t txd, ntxd, frame;
 2542 
 2543         txd = sc->sc_txnext;
 2544         frame = txd + AWI_TXD_SIZE;
 2545         if (frame + len > sc->sc_txend)
 2546                 frame = sc->sc_txbase;
 2547         ntxd = frame + len;
 2548         if (ntxd + AWI_TXD_SIZE > sc->sc_txend)
 2549                 ntxd = sc->sc_txbase;
 2550         *framep = frame;
 2551         *ntxdp = ntxd;
 2552         /*
 2553          * Determine if there are any room in ring buffer.
 2554          *              --- send wait,  === new data,  +++ conflict (ENOBUFS)
 2555          *   base........................end
 2556          *         done----txd=====ntxd         OK
 2557          *       --txd=====done++++ntxd--       full
 2558          *       --txd=====ntxd    done--       OK
 2559          *       ==ntxd    done----txd===       OK
 2560          *       ==done++++ntxd----txd===       full
 2561          *       ++ntxd    txd=====done++       full
 2562          */
 2563         if (txd < ntxd) {
 2564                 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone)
 2565                         return ENOBUFS;
 2566         } else {
 2567                 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone)
 2568                         return ENOBUFS;
 2569         }
 2570         return 0;
 2571 }
 2572 
 2573 static int
 2574 awi_lock(sc)
 2575         struct awi_softc *sc;
 2576 {
 2577         int error = 0;
 2578 
 2579         if (curproc == NULL) {
 2580                 /*
 2581                  * XXX
 2582                  * Though driver ioctl should be called with context,
 2583                  * KAME ipv6 stack calls ioctl in interrupt for now.
 2584                  * We simply abort the request if there are other
 2585                  * ioctl requests in progress.
 2586                  */
 2587                 if (sc->sc_busy) {
 2588                         return EWOULDBLOCK;
 2589                         if (sc->sc_invalid)
 2590                                 return ENXIO;
 2591                 }
 2592                 sc->sc_busy = 1;
 2593                 sc->sc_cansleep = 0;
 2594                 return 0;
 2595         }
 2596         while (sc->sc_busy) {
 2597                 if (sc->sc_invalid)
 2598                         return ENXIO;
 2599                 sc->sc_sleep_cnt++;
 2600                 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0);
 2601                 sc->sc_sleep_cnt--;
 2602                 if (error)
 2603                         return error;
 2604         }
 2605         sc->sc_busy = 1;
 2606         sc->sc_cansleep = 1;
 2607         return 0;
 2608 }
 2609 
 2610 static void
 2611 awi_unlock(sc)
 2612         struct awi_softc *sc;
 2613 {
 2614         sc->sc_busy = 0;
 2615         sc->sc_cansleep = 0;
 2616         if (sc->sc_sleep_cnt)
 2617                 wakeup(sc);
 2618 }
 2619 
 2620 static int
 2621 awi_intr_lock(sc)
 2622         struct awi_softc *sc;
 2623 {
 2624         u_int8_t status;
 2625         int i, retry;
 2626 
 2627         status = 1;
 2628         for (retry = 0; retry < 10; retry++) {
 2629                 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) {
 2630                         status = awi_read_1(sc, AWI_LOCKOUT_HOST);
 2631                         if (status == 0)
 2632                                 break;
 2633                         DELAY(5);
 2634                 }
 2635                 if (status != 0)
 2636                         break;
 2637                 awi_write_1(sc, AWI_LOCKOUT_MAC, 1);
 2638                 status = awi_read_1(sc, AWI_LOCKOUT_HOST);
 2639                 if (status == 0)
 2640                         break;
 2641                 awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
 2642         }
 2643         if (status != 0) {
 2644                 printf("%s: failed to lock interrupt\n",
 2645                     sc->sc_dev.dv_xname);
 2646                 return ENXIO;
 2647         }
 2648         return 0;
 2649 }
 2650 
 2651 static void
 2652 awi_intr_unlock(sc)
 2653         struct awi_softc *sc;
 2654 {
 2655 
 2656         awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
 2657 }
 2658 
 2659 static int
 2660 awi_cmd_wait(sc)
 2661         struct awi_softc *sc;
 2662 {
 2663         int i, error = 0;
 2664 
 2665         i = 0;
 2666         while (sc->sc_cmd_inprog) {
 2667                 if (sc->sc_invalid)
 2668                         return ENXIO;
 2669                 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) {
 2670                         printf("%s: failed to access hardware\n",
 2671                             sc->sc_dev.dv_xname);
 2672                         sc->sc_invalid = 1;
 2673                         return ENXIO;
 2674                 }
 2675                 if (sc->sc_cansleep) {
 2676                         sc->sc_sleep_cnt++;
 2677                         error = tsleep(sc, PWAIT, "awicmd",
 2678                             AWI_CMD_TIMEOUT*hz/1000);
 2679                         sc->sc_sleep_cnt--;
 2680                 } else {
 2681                         if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) {
 2682                                 awi_cmd_done(sc);
 2683                                 break;
 2684                         }
 2685                         if (i++ >= AWI_CMD_TIMEOUT*1000/10)
 2686                                 error = EWOULDBLOCK;
 2687                         else
 2688                                 DELAY(10);
 2689                 }
 2690                 if (error)
 2691                         break;
 2692         }
 2693         return error;
 2694 }
 2695 
 2696 static void
 2697 awi_print_essid(essid)
 2698         u_int8_t *essid;
 2699 {
 2700         int i, len;
 2701         u_int8_t *p;
 2702 
 2703         len = essid[1];
 2704         if (len > IEEE80211_NWID_LEN)
 2705                 len = IEEE80211_NWID_LEN;       /*XXX*/
 2706         /* determine printable or not */
 2707         for (i = 0, p = essid + 2; i < len; i++, p++) {
 2708                 if (*p < ' ' || *p > 0x7e)
 2709                         break;
 2710         }
 2711         if (i == len) {
 2712                 printf("\"");
 2713                 for (i = 0, p = essid + 2; i < len; i++, p++)
 2714                         printf("%c", *p);
 2715                 printf("\"");
 2716         } else {
 2717                 printf("0x");
 2718                 for (i = 0, p = essid + 2; i < len; i++, p++)
 2719                         printf("%02x", *p);
 2720         }
 2721 }
 2722 
 2723 #ifdef AWI_DEBUG
 2724 static void
 2725 awi_dump_pkt(sc, m, rssi)
 2726         struct awi_softc *sc;
 2727         struct mbuf *m;
 2728         int rssi;
 2729 {
 2730         struct ieee80211_frame *wh;
 2731         int i, l;
 2732 
 2733         wh = mtod(m, struct ieee80211_frame *);
 2734 
 2735         if (awi_dump_mask != 0 &&
 2736             ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK)==IEEE80211_FC1_DIR_NODS) &&
 2737             ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_MGT)) {
 2738                 if ((AWI_DUMP_MASK(wh->i_fc[0]) & awi_dump_mask) != 0)
 2739                         return;
 2740         }
 2741         if (awi_dump_mask < 0 &&
 2742             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_DATA)
 2743                 return;
 2744 
 2745         if (rssi < 0)
 2746                 printf("tx: ");
 2747         else
 2748                 printf("rx: ");
 2749         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
 2750         case IEEE80211_FC1_DIR_NODS:
 2751                 printf("NODS %s", ether_sprintf(wh->i_addr2));
 2752                 printf("->%s", ether_sprintf(wh->i_addr1));
 2753                 printf("(%s)", ether_sprintf(wh->i_addr3));
 2754                 break;
 2755         case IEEE80211_FC1_DIR_TODS:
 2756                 printf("TODS %s", ether_sprintf(wh->i_addr2));
 2757                 printf("->%s", ether_sprintf(wh->i_addr3));
 2758                 printf("(%s)", ether_sprintf(wh->i_addr1));
 2759                 break;
 2760         case IEEE80211_FC1_DIR_FROMDS:
 2761                 printf("FRDS %s", ether_sprintf(wh->i_addr3));
 2762                 printf("->%s", ether_sprintf(wh->i_addr1));
 2763                 printf("(%s)", ether_sprintf(wh->i_addr2));
 2764                 break;
 2765         case IEEE80211_FC1_DIR_DSTODS:
 2766                 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
 2767                 printf("->%s", ether_sprintf(wh->i_addr3));
 2768                 printf("(%s", ether_sprintf(wh->i_addr2));
 2769                 printf("->%s)", ether_sprintf(wh->i_addr1));
 2770                 break;
 2771         }
 2772         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
 2773         case IEEE80211_FC0_TYPE_DATA:
 2774                 printf(" data");
 2775                 break;
 2776         case IEEE80211_FC0_TYPE_MGT:
 2777                 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
 2778                 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
 2779                         printf(" probe_req");
 2780                         break;
 2781                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 2782                         printf(" probe_resp");
 2783                         break;
 2784                 case IEEE80211_FC0_SUBTYPE_BEACON:
 2785                         printf(" beacon");
 2786                         break;
 2787                 case IEEE80211_FC0_SUBTYPE_AUTH:
 2788                         printf(" auth");
 2789                         break;
 2790                 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
 2791                         printf(" assoc_req");
 2792                         break;
 2793                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
 2794                         printf(" assoc_resp");
 2795                         break;
 2796                 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
 2797                         printf(" reassoc_req");
 2798                         break;
 2799                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
 2800                         printf(" reassoc_resp");
 2801                         break;
 2802                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
 2803                         printf(" deauth");
 2804                         break;
 2805                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
 2806                         printf(" disassoc");
 2807                         break;
 2808                 default:
 2809                         printf(" mgt#%d",
 2810                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 2811                         break;
 2812                 }
 2813                 break;
 2814         default:
 2815                 printf(" type#%d",
 2816                     wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
 2817                 break;
 2818         }
 2819         if (wh->i_fc[1] & IEEE80211_FC1_WEP)
 2820                 printf(" WEP");
 2821         if (rssi >= 0)
 2822                 printf(" +%d", rssi);
 2823         printf("\n");
 2824         if (awi_dump_len > 0) {
 2825                 l = m->m_len;
 2826                 if (l > awi_dump_len + sizeof(*wh))
 2827                         l = awi_dump_len + sizeof(*wh);
 2828                 i = sizeof(*wh);
 2829                 if (awi_dump_hdr)
 2830                         i = 0;
 2831                 for (; i < l; i++) {
 2832                         if ((i & 1) == 0)
 2833                                 printf(" ");
 2834                         printf("%02x", mtod(m, u_int8_t *)[i]);
 2835                 }
 2836                 printf("\n");
 2837         }
 2838 }
 2839 #endif

/* [<][>][^][v][top][bottom][index][help] */