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