44ebf72d0e0557ab68701f815b5394a723057b36
[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.14 2004/07/02 17:42:16 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 <net/if_ieee80211.h>
125
126 #ifdef INET
127 #include <netinet/in.h>
128 #include <netinet/in_systm.h>
129 #include <netinet/in_var.h>
130 #include <netinet/ip.h>
131 #ifdef __NetBSD__
132 #include <netinet/if_inarp.h>
133 #else
134 #include <netinet/if_ether.h>
135 #endif
136 #endif
137
138 #if NBPFILTER > 0
139 #include <net/bpf.h>
140 #include <net/bpfdesc.h>
141 #endif
142
143 #include <machine/cpu.h>
144 #include <machine/bus.h>
145 #ifdef __NetBSD__
146 #include <machine/intr.h>
147 #endif
148 #if defined(__DragonFly__) || defined(__FreeBSD__)
149 #include <machine/clock.h>
150 #endif
151
152 #ifdef __NetBSD__
153 #include <dev/ic/am79c930reg.h>
154 #include <dev/ic/am79c930var.h>
155 #include <dev/ic/awireg.h>
156 #include <dev/ic/awivar.h>
157 #endif
158 #if defined(__DragonFly__) || defined(__FreeBSD__)
159 #include "am79c930reg.h"
160 #include "am79c930var.h"
161 #include "awireg.h"
162 #include "awivar.h"
163 #endif
164
165 static int awi_ioctl (struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *);
166 #ifdef IFM_IEEE80211
167 static int awi_media_rate2opt (struct awi_softc *sc, int rate);
168 static int awi_media_opt2rate (struct awi_softc *sc, int opt);
169 static int awi_media_change (struct ifnet *ifp);
170 static void awi_media_status (struct ifnet *ifp, struct ifmediareq *imr);
171 #endif
172 static void awi_watchdog (struct ifnet *ifp);
173 static void awi_start (struct ifnet *ifp);
174 static void awi_txint (struct awi_softc *sc);
175 static struct mbuf * awi_fix_txhdr (struct awi_softc *sc, struct mbuf *m0);
176 static struct mbuf * awi_fix_rxhdr (struct awi_softc *sc, struct mbuf *m0);
177 static void awi_input (struct awi_softc *sc, struct mbuf *m, u_int32_t rxts, u_int8_t rssi);
178 static void awi_rxint (struct awi_softc *sc);
179 static struct mbuf * awi_devget (struct awi_softc *sc, u_int32_t off, u_int16_t len);
180 static int awi_init_hw (struct awi_softc *sc);
181 static int awi_init_mibs (struct awi_softc *sc);
182 static int awi_init_txrx (struct awi_softc *sc);
183 static void awi_stop_txrx (struct awi_softc *sc);
184 static int awi_start_scan (struct awi_softc *sc);
185 static int awi_next_scan (struct awi_softc *sc);
186 static void awi_stop_scan (struct awi_softc *sc);
187 static void awi_recv_beacon (struct awi_softc *sc, struct mbuf *m0, u_int32_t rxts, u_int8_t rssi);
188 static int awi_set_ss (struct awi_softc *sc);
189 static void awi_try_sync (struct awi_softc *sc);
190 static void awi_sync_done (struct awi_softc *sc);
191 static void awi_send_deauth (struct awi_softc *sc);
192 static void awi_send_auth (struct awi_softc *sc, int seq);
193 static void awi_recv_auth (struct awi_softc *sc, struct mbuf *m0);
194 static void awi_send_asreq (struct awi_softc *sc, int reassoc);
195 static void awi_recv_asresp (struct awi_softc *sc, struct mbuf *m0);
196 static int awi_mib (struct awi_softc *sc, u_int8_t cmd, u_int8_t mib);
197 static int awi_cmd_scan (struct awi_softc *sc);
198 static int awi_cmd (struct awi_softc *sc, u_int8_t cmd);
199 static void awi_cmd_done (struct awi_softc *sc);
200 static int awi_next_txd (struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t*ntxdp);
201 static int awi_lock (struct awi_softc *sc);
202 static void awi_unlock (struct awi_softc *sc);
203 static int awi_intr_lock (struct awi_softc *sc);
204 static void awi_intr_unlock (struct awi_softc *sc);
205 static int awi_cmd_wait (struct awi_softc *sc);
206 static void awi_print_essid (u_int8_t *essid);
207
208 DECLARE_DUMMY_MODULE(if_awi);
209
210 #ifdef AWI_DEBUG
211 static void awi_dump_pkt (struct awi_softc *sc, struct mbuf *m, int rssi);
212 int awi_verbose = 0;
213 int awi_dump = 0;
214 #define AWI_DUMP_MASK(fc0)  (1 << (((fc0) & IEEE80211_FC0_SUBTYPE_MASK) >> 4))
215 int awi_dump_mask = AWI_DUMP_MASK(IEEE80211_FC0_SUBTYPE_BEACON);
216 int awi_dump_hdr = 0;
217 int awi_dump_len = 28;
218 #endif
219
220 #if NBPFILTER > 0
221 #define AWI_BPF_NORM    0
222 #define AWI_BPF_RAW     1
223 #if defined(__DragonFly__) || defined(__FreeBSD__)
224 #define AWI_BPF_MTAP(sc, m, raw) do {                                   \
225         if ((sc)->sc_ifp->if_bpf && (sc)->sc_rawbpf == (raw))           \
226                 bpf_mtap((sc)->sc_ifp, (m));                            \
227 } while (0);
228 #else
229 #define AWI_BPF_MTAP(sc, m, raw) do {                                   \
230         if ((sc)->sc_ifp->if_bpf && (sc)->sc_rawbpf == (raw))           \
231                 bpf_mtap((sc)->sc_ifp->if_bpf, (m));                    \
232 } while (0);
233 #endif
234 #else
235 #define AWI_BPF_MTAP(sc, m, raw)
236 #endif
237
238 #ifndef llc_snap
239 #define llc_snap              llc_un.type_snap
240 #endif
241
242 devclass_t awi_devclass;
243
244 int
245 awi_attach(sc)
246         struct awi_softc *sc;
247 {
248         struct ifnet *ifp = sc->sc_ifp;
249         int s;
250         int error;
251 #ifdef IFM_IEEE80211
252         int i;
253         u_int8_t *phy_rates;
254         int mword;
255         struct ifmediareq imr;
256 #endif
257
258         s = splnet();
259         /*
260          * Even if we can sleep in initialization state,
261          * all other processes (e.g. ifconfig) have to wait for
262          * completion of attaching interface.
263          */
264         sc->sc_busy = 1;
265         sc->sc_status = AWI_ST_INIT;
266         TAILQ_INIT(&sc->sc_scan);
267         error = awi_init_hw(sc);
268         if (error) {
269                 sc->sc_invalid = 1;
270                 splx(s);
271                 return error;
272         }
273         error = awi_init_mibs(sc);
274         splx(s);
275         if (error) {
276                 sc->sc_invalid = 1;
277                 return error;
278         }
279
280         ifp->if_softc = sc;
281         ifp->if_start = awi_start;
282         ifp->if_ioctl = awi_ioctl;
283         ifp->if_watchdog = awi_watchdog;
284         ifp->if_mtu = ETHERMTU;
285         ifp->if_hdrlen = sizeof(struct ieee80211_frame) +
286             sizeof(struct ether_header);
287         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
288 #ifdef IFF_NOTRAILERS
289         ifp->if_flags |= IFF_NOTRAILERS;
290 #endif
291 #ifdef __NetBSD__
292         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
293 #endif
294 #if defined(__DragonFly__) || defined(__FreeBSD__)
295         ifp->if_output = ether_output;
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 #ifndef __NetBSD__
1185         struct ether_header *eh;
1186 #endif
1187
1188         /* trim CRC here for WEP can find its own CRC at the end of packet. */
1189         m_adj(m, -ETHER_CRC_LEN);
1190         AWI_BPF_MTAP(sc, m, AWI_BPF_RAW);
1191         wh = mtod(m, struct ieee80211_frame *);
1192         if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
1193             IEEE80211_FC0_VERSION_0) {
1194                 printf("%s; receive packet with wrong version: %x\n",
1195                     sc->sc_dev.dv_xname, wh->i_fc[0]);
1196                 m_freem(m);
1197                 ifp->if_ierrors++;
1198                 return;
1199         }
1200         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1201                 m = awi_wep_encrypt(sc, m, 0);
1202                 if (m == NULL) {
1203                         ifp->if_ierrors++;
1204                         return;
1205                 }
1206                 wh = mtod(m, struct ieee80211_frame *);
1207         }
1208 #ifdef AWI_DEBUG
1209         if (awi_dump)
1210                 awi_dump_pkt(sc, m, rssi);
1211 #endif
1212
1213         if ((sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid) &&
1214             sc->sc_status == AWI_ST_RUNNING) {
1215                 if (memcmp(wh->i_addr2, sc->sc_bss.bssid, ETHER_ADDR_LEN) == 0) {
1216                         sc->sc_rx_timer = 10;
1217                         sc->sc_bss.rssi = rssi;
1218                 }
1219         }
1220         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1221         case IEEE80211_FC0_TYPE_DATA:
1222                 if (sc->sc_mib_local.Network_Mode) {
1223                         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
1224                             IEEE80211_FC1_DIR_FROMDS) {
1225                                 m_freem(m);
1226                                 return;
1227                         }
1228                 } else {
1229                         if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
1230                             IEEE80211_FC1_DIR_NODS) {
1231                                 m_freem(m);
1232                                 return;
1233                         }
1234                 }
1235                 m = awi_fix_rxhdr(sc, m);
1236                 if (m == NULL) {
1237                         ifp->if_ierrors++;
1238                         break;
1239                 }
1240                 ifp->if_ipackets++;
1241 #if !(defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 4))
1242                 AWI_BPF_MTAP(sc, m, AWI_BPF_NORM);
1243 #endif
1244 #ifdef __NetBSD__
1245                 (*ifp->if_input)(ifp, m);
1246 #else
1247                 eh = mtod(m, struct ether_header *);
1248                 m_adj(m, sizeof(*eh));
1249                 ether_input(ifp, eh, m);
1250 #endif
1251                 break;
1252         case IEEE80211_FC0_TYPE_MGT:
1253                 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) !=
1254                    IEEE80211_FC1_DIR_NODS) {
1255                         m_freem(m);
1256                         return;
1257                 }
1258                 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
1259                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
1260                 case IEEE80211_FC0_SUBTYPE_BEACON:
1261                         awi_recv_beacon(sc, m, rxts, rssi);
1262                         break;
1263                 case IEEE80211_FC0_SUBTYPE_AUTH:
1264                         awi_recv_auth(sc, m);
1265                         break;
1266                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1267                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
1268                         awi_recv_asresp(sc, m);
1269                         break;
1270                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
1271                         if (sc->sc_mib_local.Network_Mode)
1272                                 awi_send_auth(sc, 1);
1273                         break;
1274                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
1275                         if (sc->sc_mib_local.Network_Mode)
1276                                 awi_send_asreq(sc, 1);
1277                         break;
1278                 }
1279                 m_freem(m);
1280                 break;
1281         case IEEE80211_FC0_TYPE_CTL:
1282         default:
1283                 /* should not come here */
1284                 m_freem(m);
1285                 break;
1286         }
1287 }
1288
1289 static void
1290 awi_rxint(sc)
1291         struct awi_softc *sc;
1292 {
1293         u_int8_t state, rate, rssi;
1294         u_int16_t len;
1295         u_int32_t frame, next, rxts, rxoff;
1296         struct mbuf *m;
1297
1298         rxoff = sc->sc_rxdoff;
1299         for (;;) {
1300                 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE);
1301                 if (state & AWI_RXD_ST_OWN)
1302                         break;
1303                 if (!(state & AWI_RXD_ST_CONSUMED)) {
1304                         if (state & AWI_RXD_ST_RXERROR)
1305                                 sc->sc_ifp->if_ierrors++;
1306                         else {
1307                                 len   = awi_read_2(sc, rxoff + AWI_RXD_LEN);
1308                                 rate  = awi_read_1(sc, rxoff + AWI_RXD_RATE);
1309                                 rssi  = awi_read_1(sc, rxoff + AWI_RXD_RSSI);
1310                                 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) & 0x7fff;
1311                                 rxts  = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME);
1312                                 m = awi_devget(sc, frame, len);
1313                                 if (state & AWI_RXD_ST_LF)
1314                                         awi_input(sc, m, rxts, rssi);
1315                                 else
1316                                         sc->sc_rxpend = m;
1317                         }
1318                         state |= AWI_RXD_ST_CONSUMED;
1319                         awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
1320                 }
1321                 next  = awi_read_4(sc, rxoff + AWI_RXD_NEXT);
1322                 if (next & AWI_RXD_NEXT_LAST)
1323                         break;
1324                 /* make sure the next pointer is correct */
1325                 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT))
1326                         break;
1327                 state |= AWI_RXD_ST_OWN;
1328                 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state);
1329                 rxoff = next & 0x7fff;
1330         }
1331         sc->sc_rxdoff = rxoff;
1332 }
1333
1334 static struct mbuf *
1335 awi_devget(sc, off, len)
1336         struct awi_softc *sc;
1337         u_int32_t off;
1338         u_int16_t len;
1339 {
1340         struct mbuf *m;
1341         struct mbuf *top, **mp;
1342         u_int tlen;
1343
1344         top = sc->sc_rxpend;
1345         mp = &top;
1346         if (top != NULL) {
1347                 sc->sc_rxpend = NULL;
1348                 top->m_pkthdr.len += len;
1349                 m = top;
1350                 while (*mp != NULL) {
1351                         m = *mp;
1352                         mp = &m->m_next;
1353                 }
1354                 if (m->m_flags & M_EXT)
1355                         tlen = m->m_ext.ext_size;
1356                 else if (m->m_flags & M_PKTHDR)
1357                         tlen = MHLEN;
1358                 else
1359                         tlen = MLEN;
1360                 tlen -= m->m_len;
1361                 if (tlen > len)
1362                         tlen = len;
1363                 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen);
1364                 off += tlen;
1365                 len -= tlen;
1366         }
1367
1368         while (len > 0) {
1369                 if (top == NULL) {
1370                         MGETHDR(m, MB_DONTWAIT, MT_DATA);
1371                         if (m == NULL)
1372                                 return NULL;
1373                         m->m_pkthdr.rcvif = sc->sc_ifp;
1374                         m->m_pkthdr.len = len;
1375                         m->m_len = MHLEN;
1376                 } else {
1377                         MGET(m, MB_DONTWAIT, MT_DATA);
1378                         if (m == NULL) {
1379                                 m_freem(top);
1380                                 return NULL;
1381                         }
1382                         m->m_len = MLEN;
1383                 }
1384                 if (len >= MINCLSIZE) {
1385                         MCLGET(m, MB_DONTWAIT);
1386                         if (m->m_flags & M_EXT)
1387                                 m->m_len = m->m_ext.ext_size;
1388                 }
1389                 if (top == NULL) {
1390                         int hdrlen = sizeof(struct ieee80211_frame) +
1391                             (sc->sc_format_llc ? sizeof(struct llc) :
1392                             sizeof(struct ether_header));
1393                         caddr_t newdata = (caddr_t)
1394                             ALIGN(m->m_data + hdrlen) - hdrlen;
1395                         m->m_len -= newdata - m->m_data;
1396                         m->m_data = newdata;
1397                 }
1398                 if (m->m_len > len)
1399                         m->m_len = len;
1400                 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len);
1401                 off += m->m_len;
1402                 len -= m->m_len;
1403                 *mp = m;
1404                 mp = &m->m_next;
1405         }
1406         return top;
1407 }
1408
1409 /*
1410  * Initialize hardware and start firmware to accept commands.
1411  * Called everytime after power on firmware.
1412  */
1413
1414 static int
1415 awi_init_hw(sc)
1416         struct awi_softc *sc;
1417 {
1418         struct ifnet *ifp = sc->sc_ifp;
1419         u_int8_t status;
1420         u_int16_t intmask;
1421         int i, error;
1422
1423         sc->sc_enab_intr = 0;
1424         sc->sc_invalid = 0;     /* XXX: really? */
1425         awi_drvstate(sc, AWI_DRV_RESET);
1426
1427         /* reset firmware */
1428         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET);
1429         DELAY(100);
1430         awi_write_1(sc, AWI_SELFTEST, 0);
1431         awi_write_1(sc, AWI_CMD, 0);
1432         awi_write_1(sc, AWI_BANNER, 0);
1433         am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET);
1434         DELAY(100);
1435
1436         /* wait for selftest completion */
1437         for (i = 0; ; i++) {
1438                 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) {
1439                         if_printf(ifp, "failed to complete selftest (timeout)\n");
1440                         return ENXIO;
1441                 }
1442                 status = awi_read_1(sc, AWI_SELFTEST);
1443                 if ((status & 0xf0) == 0xf0)
1444                         break;
1445                 if (sc->sc_cansleep) {
1446                         sc->sc_sleep_cnt++;
1447                         (void)tsleep(sc, 0, "awitst", 1);
1448                         sc->sc_sleep_cnt--;
1449                 } else {
1450                         DELAY(1000*1000/hz);
1451                 }
1452         }
1453         if (status != AWI_SELFTEST_PASSED) {
1454                 if_printf(ifp, "failed to complete selftest (code %x)\n",
1455                           status);
1456                 return ENXIO;
1457         }
1458
1459         /* check banner to confirm firmware write it */
1460         awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
1461         if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
1462                 if_printf(ifp, "failed to complete selftest (bad banner)\n");
1463                 for (i = 0; i < AWI_BANNER_LEN; i++)
1464                         printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
1465                 printf("\n");
1466                 return ENXIO;
1467         }
1468
1469         /* initializing interrupt */
1470         sc->sc_enab_intr = 1;
1471         error = awi_intr_lock(sc);
1472         if (error)
1473                 return error;
1474         intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT |
1475             AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD;
1476         awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff);
1477         awi_write_1(sc, AWI_INTMASK2, 0);
1478         awi_write_1(sc, AWI_INTSTAT, 0);
1479         awi_write_1(sc, AWI_INTSTAT2, 0);
1480         awi_intr_unlock(sc);
1481         am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT);
1482
1483         /* issueing interface test command */
1484         error = awi_cmd(sc, AWI_CMD_NOP);
1485         if (error) {
1486                 if_printf(ifp, "failed to complete selftest");
1487                 if (error == ENXIO)
1488                         printf(" (no hardware)\n");
1489                 else if (error != EWOULDBLOCK)
1490                         printf(" (error %d)\n", error);
1491                 else if (sc->sc_cansleep)
1492                         printf(" (lost interrupt)\n");
1493                 else
1494                         printf(" (command timeout)\n");
1495         }
1496         return error;
1497 }
1498
1499 /*
1500  * Extract the factory default MIB value from firmware and assign the driver
1501  * default value.
1502  * Called once at attaching the interface.
1503  */
1504
1505 static int
1506 awi_init_mibs(sc)
1507         struct awi_softc *sc;
1508 {
1509         int i, error;
1510         u_int8_t *rate;
1511
1512         if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL)) != 0 ||
1513             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR)) != 0 ||
1514             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC)) != 0 ||
1515             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT)) != 0 ||
1516             (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY)) != 0) {
1517                 if_printf(sc->sc_ifp,
1518                           "failed to get default mib value (error %d)\n",
1519                           error);
1520                 return error;
1521         }
1522
1523         rate = sc->sc_mib_phy.aSuprt_Data_Rates;
1524         sc->sc_tx_rate = AWI_RATE_1MBIT;
1525         for (i = 0; i < rate[1]; i++) {
1526                 if (AWI_80211_RATE(rate[2 + i]) > sc->sc_tx_rate)
1527                         sc->sc_tx_rate = AWI_80211_RATE(rate[2 + i]);
1528         }
1529         awi_init_region(sc);
1530         memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
1531         sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
1532         sc->sc_mib_local.Fragmentation_Dis = 1;
1533         sc->sc_mib_local.Accept_All_Multicast_Dis = 1;
1534         sc->sc_mib_local.Power_Saving_Mode_Dis = 1;
1535
1536         /* allocate buffers */
1537         sc->sc_txbase = AWI_BUFFERS;
1538         sc->sc_txend = sc->sc_txbase +
1539             (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) +
1540             sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS;
1541         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase);
1542         LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size,
1543             sc->sc_txend - sc->sc_txbase);
1544         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend);
1545         LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size,
1546             AWI_BUFFERS_END - sc->sc_txend);
1547         sc->sc_mib_local.Network_Mode = 1;
1548         sc->sc_mib_local.Acting_as_AP = 0;
1549         return 0;
1550 }
1551
1552 /*
1553  * Start transmitter and receiver of firmware
1554  * Called after awi_init_hw() to start operation.
1555  */
1556
1557 static int
1558 awi_init_txrx(sc)
1559         struct awi_softc *sc;
1560 {
1561         int error;
1562
1563         /* start transmitter */
1564         sc->sc_txdone = sc->sc_txnext = sc->sc_txbase;
1565         awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0);
1566         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0);
1567         awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0);
1568         awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0);
1569         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0);
1570         awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0);
1571         awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0);
1572         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_DATA, sc->sc_txbase);
1573         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_MGT, 0);
1574         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_BCAST, 0);
1575         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_PS, 0);
1576         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_CF, 0);
1577         error = awi_cmd(sc, AWI_CMD_INIT_TX);
1578         if (error)
1579                 return error;
1580
1581         /* start receiver */
1582         if (sc->sc_rxpend) {
1583                 m_freem(sc->sc_rxpend);
1584                 sc->sc_rxpend = NULL;
1585         }
1586         error = awi_cmd(sc, AWI_CMD_INIT_RX);
1587         if (error)
1588                 return error;
1589         sc->sc_rxdoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_DATA_DESC);
1590         sc->sc_rxmoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_PS_DESC);
1591         return 0;
1592 }
1593
1594 static void
1595 awi_stop_txrx(sc)
1596         struct awi_softc *sc;
1597 {
1598
1599         if (sc->sc_cmd_inprog)
1600                 (void)awi_cmd_wait(sc);
1601         (void)awi_cmd(sc, AWI_CMD_KILL_RX);
1602         (void)awi_cmd_wait(sc);
1603         sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX;
1604         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_DATA, 1);
1605         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_MGT, 0);
1606         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_BCAST, 0);
1607         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_PS, 0);
1608         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_CF, 0);
1609         (void)awi_cmd(sc, AWI_CMD_FLUSH_TX);
1610         (void)awi_cmd_wait(sc);
1611 }
1612
1613 int
1614 awi_init_region(sc)
1615         struct awi_softc *sc;
1616 {
1617
1618         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1619                 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
1620                 case AWI_REG_DOMAIN_US:
1621                 case AWI_REG_DOMAIN_CA:
1622                 case AWI_REG_DOMAIN_EU:
1623                         sc->sc_scan_min = 0;
1624                         sc->sc_scan_max = 77;
1625                         break;
1626                 case AWI_REG_DOMAIN_ES:
1627                         sc->sc_scan_min = 0;
1628                         sc->sc_scan_max = 26;
1629                         break;
1630                 case AWI_REG_DOMAIN_FR:
1631                         sc->sc_scan_min = 0;
1632                         sc->sc_scan_max = 32;
1633                         break;
1634                 case AWI_REG_DOMAIN_JP:
1635                         sc->sc_scan_min = 6;
1636                         sc->sc_scan_max = 17;
1637                         break;
1638                 default:
1639                         return EINVAL;
1640                 }
1641                 sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
1642         } else {
1643                 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
1644                 case AWI_REG_DOMAIN_US:
1645                 case AWI_REG_DOMAIN_CA:
1646                         sc->sc_scan_min = 1;
1647                         sc->sc_scan_max = 11;
1648                         sc->sc_scan_cur = 3;
1649                         break;
1650                 case AWI_REG_DOMAIN_EU:
1651                         sc->sc_scan_min = 1;
1652                         sc->sc_scan_max = 13;
1653                         sc->sc_scan_cur = 3;
1654                         break;
1655                 case AWI_REG_DOMAIN_ES:
1656                         sc->sc_scan_min = 10;
1657                         sc->sc_scan_max = 11;
1658                         sc->sc_scan_cur = 10;
1659                         break;
1660                 case AWI_REG_DOMAIN_FR:
1661                         sc->sc_scan_min = 10;
1662                         sc->sc_scan_max = 13;
1663                         sc->sc_scan_cur = 10;
1664                         break;
1665                 case AWI_REG_DOMAIN_JP:
1666                         sc->sc_scan_min = 14;
1667                         sc->sc_scan_max = 14;
1668                         sc->sc_scan_cur = 14;
1669                         break;
1670                 default:
1671                         return EINVAL;
1672                 }
1673         }
1674         sc->sc_ownch = sc->sc_scan_cur;
1675         return 0;
1676 }
1677
1678 static int
1679 awi_start_scan(sc)
1680         struct awi_softc *sc;
1681 {
1682         int error = 0;
1683         struct awi_bss *bp;
1684
1685         while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
1686                 TAILQ_REMOVE(&sc->sc_scan, bp, list);
1687                 free(bp, M_DEVBUF);
1688         }
1689         if (!sc->sc_mib_local.Network_Mode && sc->sc_no_bssid) {
1690                 memset(&sc->sc_bss, 0, sizeof(sc->sc_bss));
1691                 sc->sc_bss.essid[0] = IEEE80211_ELEMID_SSID;
1692                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1693                         sc->sc_bss.chanset = sc->sc_ownch % 3 + 1;
1694                         sc->sc_bss.pattern = sc->sc_ownch;
1695                         sc->sc_bss.index = 1;
1696                         sc->sc_bss.dwell_time = 200;    /*XXX*/
1697                 } else
1698                         sc->sc_bss.chanset = sc->sc_ownch;
1699                 sc->sc_status = AWI_ST_SETSS;
1700                 error = awi_set_ss(sc);
1701         } else {
1702                 if (sc->sc_mib_local.Network_Mode)
1703                         awi_drvstate(sc, AWI_DRV_INFSC);
1704                 else
1705                         awi_drvstate(sc, AWI_DRV_ADHSC);
1706                 sc->sc_start_bss = 0;
1707                 sc->sc_active_scan = 1;
1708                 sc->sc_mgt_timer = AWI_ASCAN_WAIT / 1000;
1709                 sc->sc_ifp->if_timer = 1;
1710                 sc->sc_status = AWI_ST_SCAN;
1711                 error = awi_cmd_scan(sc);
1712         }
1713         return error;
1714 }
1715
1716 static int
1717 awi_next_scan(sc)
1718         struct awi_softc *sc;
1719 {
1720         int error;
1721
1722         for (;;) {
1723                 /*
1724                  * The pattern parameter for FH phy should be incremented
1725                  * by 3.  But BayStack 650 Access Points apparently always
1726                  * assign hop pattern set parameter to 1 for any pattern.
1727                  * So we try all combinations of pattern/set parameters.
1728                  * Since this causes no error, it may be a bug of
1729                  * PCnetMobile firmware.
1730                  */
1731                 sc->sc_scan_cur++;
1732                 if (sc->sc_scan_cur > sc->sc_scan_max) {
1733                         sc->sc_scan_cur = sc->sc_scan_min;
1734                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
1735                                 sc->sc_scan_set = sc->sc_scan_set % 3 + 1;
1736                 }
1737                 error = awi_cmd_scan(sc);
1738                 if (error != EINVAL)
1739                         break;
1740         }
1741         return error;
1742 }
1743
1744 static void
1745 awi_stop_scan(sc)
1746         struct awi_softc *sc;
1747 {
1748         struct ifnet *ifp = sc->sc_ifp;
1749         struct awi_bss *bp, *sbp;
1750         int fail;
1751
1752         bp = TAILQ_FIRST(&sc->sc_scan);
1753         if (bp == NULL) {
1754   notfound:
1755                 if (sc->sc_active_scan) {
1756                         if (ifp->if_flags & IFF_DEBUG)
1757                                 if_printf(ifp, "entering passive scan mode\n");
1758                         sc->sc_active_scan = 0;
1759                 }
1760                 sc->sc_mgt_timer = AWI_PSCAN_WAIT / 1000;
1761                 ifp->if_timer = 1;
1762                 (void)awi_next_scan(sc);
1763                 return;
1764         }
1765         sbp = NULL;
1766         if (ifp->if_flags & IFF_DEBUG)
1767                 if_printf(ifp, "\tmacaddr     ch/pat   sig flag  wep  essid\n");
1768         for (; bp != NULL; bp = TAILQ_NEXT(bp, list)) {
1769                 if (bp->fails) {
1770                         /*
1771                          * The configuration of the access points may change
1772                          * during my scan.  So we retries to associate with
1773                          * it unless there are any suitable AP.
1774                          */
1775                         if (bp->fails++ < 3)
1776                                 continue;
1777                         bp->fails = 0;
1778                 }
1779                 fail = 0;
1780                 /*
1781                  * Since the firmware apparently scans not only the specified
1782                  * channel of SCAN command but all available channel within
1783                  * the region, we should filter out unnecessary responses here.
1784                  */
1785                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1786                         if (bp->pattern < sc->sc_scan_min ||
1787                             bp->pattern > sc->sc_scan_max)
1788                                 fail |= 0x01;
1789                 } else {
1790                         if (bp->chanset < sc->sc_scan_min ||
1791                             bp->chanset > sc->sc_scan_max)
1792                                 fail |= 0x01;
1793                 }
1794                 if (sc->sc_mib_local.Network_Mode) {
1795                         if (!(bp->capinfo & IEEE80211_CAPINFO_ESS) ||
1796                             (bp->capinfo & IEEE80211_CAPINFO_IBSS))
1797                                 fail |= 0x02;
1798                 } else {
1799                         if ((bp->capinfo & IEEE80211_CAPINFO_ESS) ||
1800                             !(bp->capinfo & IEEE80211_CAPINFO_IBSS))
1801                                 fail |= 0x02;
1802                 }
1803                 if (sc->sc_wep_algo == NULL) {
1804                         if (bp->capinfo & IEEE80211_CAPINFO_PRIVACY)
1805                                 fail |= 0x04;
1806                 } else {
1807                         if (!(bp->capinfo & IEEE80211_CAPINFO_PRIVACY))
1808                                 fail |= 0x04;
1809                 }
1810                 if (sc->sc_mib_mac.aDesired_ESS_ID[1] != 0 &&
1811                     memcmp(&sc->sc_mib_mac.aDesired_ESS_ID, bp->essid,
1812                     sizeof(bp->essid)) != 0)
1813                         fail |= 0x08;
1814                 if (ifp->if_flags & IFF_DEBUG) {
1815                         printf(" %c %6D", fail ? '-' : '+', bp->esrc, ":");
1816                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
1817                                 printf("  %2d/%d%c", bp->pattern, bp->chanset,
1818                                     fail & 0x01 ? '!' : ' ');
1819                         else
1820                                 printf("  %4d%c", bp->chanset,
1821                                     fail & 0x01 ? '!' : ' ');
1822                         printf(" %+4d", bp->rssi);
1823                         printf(" %4s%c",
1824                             (bp->capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
1825                             (bp->capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
1826                             "????",
1827                             fail & 0x02 ? '!' : ' ');
1828                         printf(" %3s%c ",
1829                             (bp->capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" :
1830                             "no",
1831                             fail & 0x04 ? '!' : ' ');
1832                         awi_print_essid(bp->essid);
1833                         printf("%s\n", fail & 0x08 ? "!" : "");
1834                 }
1835                 if (!fail) {
1836                         if (sbp == NULL || bp->rssi > sbp->rssi)
1837                                 sbp = bp;
1838                 }
1839         }
1840         if (sbp == NULL)
1841                 goto notfound;
1842         sc->sc_bss = *sbp;
1843         (void)awi_set_ss(sc);
1844 }
1845
1846 static void
1847 awi_recv_beacon(sc, m0, rxts, rssi)
1848         struct awi_softc *sc;
1849         struct mbuf *m0;
1850         u_int32_t rxts;
1851         u_int8_t rssi;
1852 {
1853         struct ieee80211_frame *wh;
1854         struct awi_bss *bp;
1855         u_int8_t *frame, *eframe;
1856         u_int8_t *tstamp, *bintval, *capinfo, *ssid, *rates, *parms;
1857
1858         if (sc->sc_status != AWI_ST_SCAN)
1859                 return;
1860         wh = mtod(m0, struct ieee80211_frame *);
1861
1862         frame = (u_int8_t *)&wh[1];
1863         eframe = mtod(m0, u_int8_t *) + m0->m_len;
1864         /*
1865          * XXX:
1866          *      timestamp [8]
1867          *      beacon interval [2]
1868          *      capability information [2]
1869          *      ssid [tlv]
1870          *      supported rates [tlv]
1871          *      parameter set [tlv]
1872          *      ...
1873          */
1874         if (frame + 12 > eframe) {
1875 #ifdef AWI_DEBUG
1876                 if (awi_verbose)
1877                         printf("awi_recv_beacon: frame too short \n");
1878 #endif
1879                 return;
1880         }
1881         tstamp = frame;
1882         frame += 8;
1883         bintval = frame;
1884         frame += 2;
1885         capinfo = frame;
1886         frame += 2;
1887
1888         ssid = rates = parms = NULL;
1889         while (frame < eframe) {
1890                 switch (*frame) {
1891                 case IEEE80211_ELEMID_SSID:
1892                         ssid = frame;
1893                         break;
1894                 case IEEE80211_ELEMID_RATES:
1895                         rates = frame;
1896                         break;
1897                 case IEEE80211_ELEMID_FHPARMS:
1898                 case IEEE80211_ELEMID_DSPARMS:
1899                         parms = frame;
1900                         break;
1901                 }
1902                 frame += frame[1] + 2;
1903         }
1904         if (ssid == NULL || rates == NULL || parms == NULL) {
1905 #ifdef AWI_DEBUG
1906                 if (awi_verbose)
1907                         printf("awi_recv_beacon: ssid=%p, rates=%p, parms=%p\n",
1908                             ssid, rates, parms);
1909 #endif
1910                 return;
1911         }
1912         if (ssid[1] > IEEE80211_NWID_LEN) {
1913 #ifdef AWI_DEBUG
1914                 if (awi_verbose)
1915                         printf("awi_recv_beacon: bad ssid len: %d from %6D\n",
1916                             ssid[1], wh->i_addr2, ":");
1917 #endif
1918                 return;
1919         }
1920
1921         for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
1922             bp = TAILQ_NEXT(bp, list)) {
1923                 if (memcmp(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN) == 0 &&
1924                     memcmp(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN) == 0)
1925                         break;
1926         }
1927         if (bp == NULL) {
1928                 bp = malloc(sizeof(struct awi_bss), M_DEVBUF, M_INTWAIT);
1929                 if (bp == NULL)
1930                         return;
1931                 TAILQ_INSERT_TAIL(&sc->sc_scan, bp, list);
1932                 memcpy(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN);
1933                 memcpy(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN);
1934                 memset(bp->essid, 0, sizeof(bp->essid));
1935                 memcpy(bp->essid, ssid, 2 + ssid[1]);
1936         }
1937         bp->rssi = rssi;
1938         bp->rxtime = rxts;
1939         memcpy(bp->timestamp, tstamp, sizeof(bp->timestamp));
1940         bp->interval = LE_READ_2(bintval);
1941         bp->capinfo = LE_READ_2(capinfo);
1942         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
1943                 bp->chanset = parms[4];
1944                 bp->pattern = parms[5];
1945                 bp->index = parms[6];
1946                 bp->dwell_time = LE_READ_2(parms + 2);
1947         } else {
1948                 bp->chanset = parms[2];
1949                 bp->pattern = 0;
1950                 bp->index = 0;
1951                 bp->dwell_time = 0;
1952         }
1953         if (sc->sc_mgt_timer == 0)
1954                 awi_stop_scan(sc);
1955 }
1956
1957 static int
1958 awi_set_ss(sc)
1959         struct awi_softc *sc;
1960 {
1961         struct ifnet *ifp = sc->sc_ifp;
1962         struct awi_bss *bp;
1963         int error;
1964
1965         sc->sc_status = AWI_ST_SETSS;
1966         bp = &sc->sc_bss;
1967         if (ifp->if_flags & IFF_DEBUG) {
1968                 if_printf(ifp, "ch %d pat %d id %d dw %d iv %d bss %6D ssid ",
1969                           bp->chanset, bp->pattern, bp->index, bp->dwell_time,
1970                           bp->interval, bp->bssid, ":");
1971                 awi_print_essid(bp->essid);
1972                 printf("\n");
1973         }
1974         memcpy(&sc->sc_mib_mgt.aCurrent_BSS_ID, bp->bssid, ETHER_ADDR_LEN);
1975         memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID, bp->essid,
1976             AWI_ESS_ID_SIZE);
1977         LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, bp->interval);
1978         error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT);
1979         return error;
1980 }
1981
1982 static void
1983 awi_try_sync(sc)
1984         struct awi_softc *sc;
1985 {
1986         struct awi_bss *bp;
1987
1988         sc->sc_status = AWI_ST_SYNC;
1989         bp = &sc->sc_bss;
1990
1991         if (sc->sc_cmd_inprog) {
1992                 if (awi_cmd_wait(sc))
1993                         return;
1994         }
1995         sc->sc_cmd_inprog = AWI_CMD_SYNC;
1996         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_SET, bp->chanset);
1997         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_PATTERN, bp->pattern);
1998         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_IDX, bp->index);
1999         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_STARTBSS,
2000             sc->sc_start_bss ? 1 : 0); 
2001         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_DWELL, bp->dwell_time);
2002         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_MBZ, 0);
2003         awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_TIMESTAMP,
2004             bp->timestamp, 8);
2005         awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_REFTIME, bp->rxtime);
2006         (void)awi_cmd(sc, AWI_CMD_SYNC);
2007 }
2008
2009 static void
2010 awi_sync_done(sc)
2011         struct awi_softc *sc;
2012 {
2013         struct ifnet *ifp = sc->sc_ifp;
2014
2015         if (sc->sc_mib_local.Network_Mode) {
2016                 awi_drvstate(sc, AWI_DRV_INFSY);
2017                 awi_send_auth(sc, 1);
2018         } else {
2019                 if (ifp->if_flags & IFF_DEBUG) {
2020                         if_printf(ifp, "synced with");
2021                         if (sc->sc_no_bssid)
2022                                 printf(" no-bssid");
2023                         else {
2024                                 printf(" %6D ssid ", sc->sc_bss.bssid, ":");
2025                                 awi_print_essid(sc->sc_bss.essid);
2026                         }
2027                         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
2028                                 printf(" at chanset %d pattern %d\n",
2029                                     sc->sc_bss.chanset, sc->sc_bss.pattern);
2030                         else
2031                                 printf(" at channel %d\n", sc->sc_bss.chanset);
2032                 }
2033                 awi_drvstate(sc, AWI_DRV_ADHSY);
2034                 sc->sc_status = AWI_ST_RUNNING;
2035                 ifp->if_flags |= IFF_RUNNING;
2036                 awi_start(ifp);
2037         }
2038 }
2039
2040 static void
2041 awi_send_deauth(sc)
2042         struct awi_softc *sc;
2043 {
2044         struct ifnet *ifp = sc->sc_ifp;
2045         struct mbuf *m;
2046         struct ieee80211_frame *wh;
2047         u_int8_t *deauth;
2048
2049         MGETHDR(m, MB_DONTWAIT, MT_DATA);
2050         if (m == NULL)
2051                 return;
2052         if (ifp->if_flags & IFF_DEBUG)
2053                 if_printf(ifp, "sending deauth to %6D\n",
2054                           sc->sc_bss.bssid, ":");
2055
2056         wh = mtod(m, struct ieee80211_frame *);
2057         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
2058             IEEE80211_FC0_SUBTYPE_AUTH;
2059         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2060         LE_WRITE_2(wh->i_dur, 0);
2061         LE_WRITE_2(wh->i_seq, 0);
2062         memcpy(wh->i_addr1, sc->sc_bss.bssid, ETHER_ADDR_LEN);
2063         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
2064         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
2065
2066         deauth = (u_int8_t *)&wh[1];
2067         LE_WRITE_2(deauth, IEEE80211_REASON_AUTH_LEAVE);
2068         deauth += 2;
2069
2070         m->m_pkthdr.len = m->m_len = deauth - mtod(m, u_int8_t *);
2071         IF_ENQUEUE(&sc->sc_mgtq, m);
2072         awi_start(ifp);
2073         awi_drvstate(sc, AWI_DRV_INFTOSS);
2074 }
2075
2076 static void
2077 awi_send_auth(sc, seq)
2078         struct awi_softc *sc;
2079         int seq;
2080 {
2081         struct ifnet *ifp = sc->sc_ifp;
2082         struct mbuf *m;
2083         struct ieee80211_frame *wh;
2084         u_int8_t *auth;
2085
2086         MGETHDR(m, MB_DONTWAIT, MT_DATA);
2087         if (m == NULL)
2088                 return;
2089         sc->sc_status = AWI_ST_AUTH;
2090         if (ifp->if_flags & IFF_DEBUG)
2091                 if_printf(ifp, "sending auth to %6D\n",
2092                           sc->sc_bss.bssid, ":");
2093
2094         wh = mtod(m, struct ieee80211_frame *);
2095         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
2096             IEEE80211_FC0_SUBTYPE_AUTH;
2097         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2098         LE_WRITE_2(wh->i_dur, 0);
2099         LE_WRITE_2(wh->i_seq, 0);
2100         memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN);
2101         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
2102         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
2103
2104         auth = (u_int8_t *)&wh[1];
2105         /* algorithm number */
2106         LE_WRITE_2(auth, IEEE80211_AUTH_ALG_OPEN);
2107         auth += 2;
2108         /* sequence number */
2109         LE_WRITE_2(auth, seq);
2110         auth += 2;
2111         /* status */
2112         LE_WRITE_2(auth, 0);
2113         auth += 2;
2114
2115         m->m_pkthdr.len = m->m_len = auth - mtod(m, u_int8_t *);
2116         IF_ENQUEUE(&sc->sc_mgtq, m);
2117         awi_start(ifp);
2118
2119         sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000;
2120         ifp->if_timer = 1;
2121 }
2122
2123 static void
2124 awi_recv_auth(sc, m0)
2125         struct awi_softc *sc;
2126         struct mbuf *m0;
2127 {
2128         struct ifnet *ifp = sc->sc_ifp;
2129         struct ieee80211_frame *wh;
2130         u_int8_t *auth, *eframe;
2131         struct awi_bss *bp;
2132         u_int16_t status;
2133
2134         wh = mtod(m0, struct ieee80211_frame *);
2135         auth = (u_int8_t *)&wh[1];
2136         eframe = mtod(m0, u_int8_t *) + m0->m_len;
2137         if (ifp->if_flags & IFF_DEBUG)
2138                 if_printf(ifp, "receive auth from %6D\n", wh->i_addr2, ":");
2139
2140         /* algorithm number */
2141         if (LE_READ_2(auth) != IEEE80211_AUTH_ALG_OPEN)
2142                 return;
2143         auth += 2;
2144         if (!sc->sc_mib_local.Network_Mode) {
2145                 if (sc->sc_status != AWI_ST_RUNNING)
2146                         return;
2147                 if (LE_READ_2(auth) == 1)
2148                         awi_send_auth(sc, 2);
2149                 return;
2150         }
2151         if (sc->sc_status != AWI_ST_AUTH)
2152                 return;
2153         /* sequence number */
2154         if (LE_READ_2(auth) != 2)
2155                 return;
2156         auth += 2;
2157         /* status */
2158         status = LE_READ_2(auth);
2159         if (status != 0) {
2160                 if_printf(ifp, "authentication failed (reason %d)\n", status);
2161                 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
2162                     bp = TAILQ_NEXT(bp, list)) {
2163                         if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN)
2164                             == 0) {
2165                                 bp->fails++;
2166                                 break;
2167                         }
2168                 }
2169                 return;
2170         }
2171         sc->sc_mgt_timer = 0;
2172         awi_drvstate(sc, AWI_DRV_INFAUTH);
2173         awi_send_asreq(sc, 0);
2174 }
2175
2176 static void
2177 awi_send_asreq(sc, reassoc)
2178         struct awi_softc *sc;
2179         int reassoc;
2180 {
2181         struct ifnet *ifp = sc->sc_ifp;
2182         struct mbuf *m;
2183         struct ieee80211_frame *wh;
2184         u_int16_t lintval;
2185         u_int8_t *asreq;
2186
2187         MGETHDR(m, MB_DONTWAIT, MT_DATA);
2188         if (m == NULL)
2189                 return;
2190         sc->sc_status = AWI_ST_ASSOC;
2191         if (ifp->if_flags & IFF_DEBUG)
2192                 if_printf(ifp, "sending %sassoc req to %6D\n",
2193                     reassoc ? "re" : "", sc->sc_bss.bssid, ":");
2194
2195         wh = mtod(m, struct ieee80211_frame *);
2196         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT;
2197         if (reassoc)
2198                 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
2199         else
2200                 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
2201         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
2202         LE_WRITE_2(wh->i_dur, 0);
2203         LE_WRITE_2(wh->i_seq, 0);
2204         memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN);
2205         memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN);
2206         memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN);
2207
2208         asreq = (u_int8_t *)&wh[1];
2209
2210         /* capability info */
2211         if (sc->sc_wep_algo == NULL)
2212                 LE_WRITE_2(asreq, IEEE80211_CAPINFO_CF_POLLABLE);
2213         else
2214                 LE_WRITE_2(asreq,
2215                     IEEE80211_CAPINFO_CF_POLLABLE | IEEE80211_CAPINFO_PRIVACY);
2216         asreq += 2;
2217         /* listen interval */
2218         lintval = LE_READ_2(&sc->sc_mib_mgt.aListen_Interval);
2219         LE_WRITE_2(asreq, lintval);
2220         asreq += 2;
2221         if (reassoc) {
2222                 /* current AP address */
2223                 memcpy(asreq, sc->sc_bss.bssid, ETHER_ADDR_LEN);
2224                 asreq += ETHER_ADDR_LEN;
2225         }
2226         /* ssid */
2227         memcpy(asreq, sc->sc_bss.essid, 2 + sc->sc_bss.essid[1]);
2228         asreq += 2 + asreq[1];
2229         /* supported rates */
2230         memcpy(asreq, &sc->sc_mib_phy.aSuprt_Data_Rates, 4);
2231         asreq += 2 + asreq[1];
2232
2233         m->m_pkthdr.len = m->m_len = asreq - mtod(m, u_int8_t *);
2234         IF_ENQUEUE(&sc->sc_mgtq, m);
2235         awi_start(ifp);
2236
2237         sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000;
2238         ifp->if_timer = 1;
2239 }
2240
2241 static void
2242 awi_recv_asresp(sc, m0)
2243         struct awi_softc *sc;
2244         struct mbuf *m0;
2245 {
2246         struct ifnet *ifp = sc->sc_ifp;
2247         struct ieee80211_frame *wh;
2248         u_int8_t *asresp, *eframe;
2249         u_int16_t status;
2250         u_int8_t rate, *phy_rates;
2251         struct awi_bss *bp;
2252         int i, j;
2253
2254         wh = mtod(m0, struct ieee80211_frame *);
2255         asresp = (u_int8_t *)&wh[1];
2256         eframe = mtod(m0, u_int8_t *) + m0->m_len;
2257         if (ifp->if_flags & IFF_DEBUG)
2258                 if_printf(ifp, "receive assoc resp from %6D\n",
2259                           wh->i_addr2, ":");
2260
2261         if (!sc->sc_mib_local.Network_Mode)
2262                 return;
2263
2264         if (sc->sc_status != AWI_ST_ASSOC)
2265                 return;
2266         /* capability info */
2267         asresp += 2;
2268         /* status */
2269         status = LE_READ_2(asresp);
2270         if (status != 0) {
2271                 if_printf(ifp, "association failed (reason %d)\n", status);
2272                 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL;
2273                     bp = TAILQ_NEXT(bp, list)) {
2274                         if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN)
2275                             == 0) {
2276                                 bp->fails++;
2277                                 break;
2278                         }
2279                 }
2280                 return;
2281         }
2282         asresp += 2;
2283         /* association id */
2284         asresp += 2;
2285         /* supported rates */
2286         rate = AWI_RATE_1MBIT;
2287         for (i = 0; i < asresp[1]; i++) {
2288                 if (AWI_80211_RATE(asresp[2 + i]) <= rate)
2289                         continue;
2290                 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
2291                 for (j = 0; j < phy_rates[1]; j++) {
2292                         if (AWI_80211_RATE(asresp[2 + i]) ==
2293                             AWI_80211_RATE(phy_rates[2 + j]))
2294                                 rate = AWI_80211_RATE(asresp[2 + i]);
2295                 }
2296         }
2297         if (ifp->if_flags & IFF_DEBUG) {
2298                 if_printf(ifp, "associated with %6D ssid ",
2299                           sc->sc_bss.bssid, ":");
2300                 awi_print_essid(sc->sc_bss.essid);
2301                 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
2302                         printf(" chanset %d pattern %d\n",
2303                             sc->sc_bss.chanset, sc->sc_bss.pattern);
2304                 else
2305                         printf(" channel %d\n", sc->sc_bss.chanset);
2306         }
2307         sc->sc_tx_rate = rate;
2308         sc->sc_mgt_timer = 0;
2309         sc->sc_rx_timer = 10;
2310         ifp->if_timer = 1;
2311         sc->sc_status = AWI_ST_RUNNING;
2312         ifp->if_flags |= IFF_RUNNING;
2313         awi_drvstate(sc, AWI_DRV_INFASSOC);
2314         awi_start(ifp);
2315 }
2316
2317 static int
2318 awi_mib(sc, cmd, mib)
2319         struct awi_softc *sc;
2320         u_int8_t cmd;
2321         u_int8_t mib;
2322 {
2323         int error;
2324         u_int8_t size, *ptr;
2325
2326         switch (mib) {
2327         case AWI_MIB_LOCAL:
2328                 ptr = (u_int8_t *)&sc->sc_mib_local;
2329                 size = sizeof(sc->sc_mib_local);
2330                 break;
2331         case AWI_MIB_ADDR:
2332                 ptr = (u_int8_t *)&sc->sc_mib_addr;
2333                 size = sizeof(sc->sc_mib_addr);
2334                 break;
2335         case AWI_MIB_MAC:
2336                 ptr = (u_int8_t *)&sc->sc_mib_mac;
2337                 size = sizeof(sc->sc_mib_mac);
2338                 break;
2339         case AWI_MIB_STAT:
2340                 ptr = (u_int8_t *)&sc->sc_mib_stat;
2341                 size = sizeof(sc->sc_mib_stat);
2342                 break;
2343         case AWI_MIB_MGT:
2344                 ptr = (u_int8_t *)&sc->sc_mib_mgt;
2345                 size = sizeof(sc->sc_mib_mgt);
2346                 break;
2347         case AWI_MIB_PHY:
2348                 ptr = (u_int8_t *)&sc->sc_mib_phy;
2349                 size = sizeof(sc->sc_mib_phy);
2350                 break;
2351         default:
2352                 return EINVAL;
2353         }
2354         if (sc->sc_cmd_inprog) {
2355                 error = awi_cmd_wait(sc);
2356                 if (error) {
2357                         if (error == EWOULDBLOCK)
2358                                 printf("awi_mib: cmd %d inprog",
2359                                     sc->sc_cmd_inprog);
2360                         return error;
2361                 }
2362         }
2363         sc->sc_cmd_inprog = cmd;
2364         if (cmd == AWI_CMD_SET_MIB)
2365                 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size);
2366         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, mib);
2367         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, size);
2368         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX, 0);
2369         error = awi_cmd(sc, cmd);
2370         if (error)
2371                 return error;
2372         if (cmd == AWI_CMD_GET_MIB) {
2373                 awi_read_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size);
2374 #ifdef AWI_DEBUG
2375                 if (awi_verbose) {
2376                         int i;
2377
2378                         printf("awi_mib: #%d:", mib);
2379                         for (i = 0; i < size; i++)
2380                                 printf(" %02x", ptr[i]);
2381                         printf("\n");
2382                 }
2383 #endif
2384         }
2385         return 0;
2386 }
2387
2388 static int
2389 awi_cmd_scan(sc)
2390         struct awi_softc *sc;
2391 {
2392         int error;
2393         u_int8_t scan_mode;
2394
2395         if (sc->sc_active_scan)
2396                 scan_mode = AWI_SCAN_ACTIVE;
2397         else
2398                 scan_mode = AWI_SCAN_PASSIVE;
2399         if (sc->sc_mib_mgt.aScan_Mode != scan_mode) {
2400                 sc->sc_mib_mgt.aScan_Mode = scan_mode;
2401                 error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT);
2402                 return error;
2403         }
2404
2405         if (sc->sc_cmd_inprog) {
2406                 error = awi_cmd_wait(sc);
2407                 if (error)
2408                         return error;
2409         }
2410         sc->sc_cmd_inprog = AWI_CMD_SCAN;
2411         awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_DURATION,
2412             sc->sc_active_scan ? AWI_ASCAN_DURATION : AWI_PSCAN_DURATION);
2413         if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
2414                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
2415                     sc->sc_scan_set);
2416                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN,
2417                     sc->sc_scan_cur);
2418                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 1);
2419         } else {
2420                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET,
2421                     sc->sc_scan_cur);
2422                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN, 0);
2423                 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 0);
2424         }
2425         awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SUSP, 0);
2426         return awi_cmd(sc, AWI_CMD_SCAN);
2427 }
2428
2429 static int
2430 awi_cmd(sc, cmd)
2431         struct awi_softc *sc;
2432         u_int8_t cmd;
2433 {
2434         u_int8_t status;
2435         int error = 0;
2436
2437         sc->sc_cmd_inprog = cmd;
2438         awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE);
2439         awi_write_1(sc, AWI_CMD, cmd);
2440         if (sc->sc_status != AWI_ST_INIT)
2441                 return 0;
2442         error = awi_cmd_wait(sc);
2443         if (error)
2444                 return error;
2445         status = awi_read_1(sc, AWI_CMD_STATUS);
2446         awi_write_1(sc, AWI_CMD, 0);
2447         switch (status) {
2448         case AWI_STAT_OK:
2449                 break;
2450         case AWI_STAT_BADPARM:
2451                 return EINVAL;
2452         default:
2453                 if_printf(sc->sc_ifp, "command %d failed %x\n", cmd, status);
2454                 return ENXIO;
2455         }
2456         return 0;
2457 }
2458
2459 static void
2460 awi_cmd_done(sc)
2461         struct awi_softc *sc;
2462 {
2463         u_int8_t cmd, status;
2464
2465         status = awi_read_1(sc, AWI_CMD_STATUS);
2466         if (status == AWI_STAT_IDLE)
2467                 return;         /* stray interrupt */
2468
2469         cmd = sc->sc_cmd_inprog;
2470         sc->sc_cmd_inprog = 0;
2471         if (sc->sc_status == AWI_ST_INIT) {
2472                 wakeup(sc);
2473                 return;
2474         }
2475         awi_write_1(sc, AWI_CMD, 0);
2476
2477         if (status != AWI_STAT_OK) {
2478                 if_printf(sc->sc_ifp, "command %d failed %x\n", cmd, status);
2479                 return;
2480         }
2481         switch (sc->sc_status) {
2482         case AWI_ST_SCAN:
2483                 if (cmd == AWI_CMD_SET_MIB)
2484                         awi_cmd_scan(sc);       /* retry */
2485                 break;
2486         case AWI_ST_SETSS:
2487                 awi_try_sync(sc);
2488                 break;
2489         case AWI_ST_SYNC:
2490                 awi_sync_done(sc);
2491                 break;
2492         default:
2493                 break;
2494         }
2495 }
2496
2497 static int
2498 awi_next_txd(sc, len, framep, ntxdp)
2499         struct awi_softc *sc;
2500         int len;
2501         u_int32_t *framep, *ntxdp;
2502 {
2503         u_int32_t txd, ntxd, frame;
2504
2505         txd = sc->sc_txnext;
2506         frame = txd + AWI_TXD_SIZE;
2507         if (frame + len > sc->sc_txend)
2508                 frame = sc->sc_txbase;
2509         ntxd = frame + len;
2510         if (ntxd + AWI_TXD_SIZE > sc->sc_txend)
2511                 ntxd = sc->sc_txbase;
2512         *framep = frame;
2513         *ntxdp = ntxd;
2514         /*
2515          * Determine if there are any room in ring buffer.
2516          *              --- send wait,  === new data,  +++ conflict (ENOBUFS)
2517          *   base........................end
2518          *         done----txd=====ntxd         OK
2519          *       --txd=====done++++ntxd--       full
2520          *       --txd=====ntxd    done--       OK
2521          *       ==ntxd    done----txd===       OK
2522          *       ==done++++ntxd----txd===       full
2523          *       ++ntxd    txd=====done++       full
2524          */
2525         if (txd < ntxd) {
2526                 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone)
2527                         return ENOBUFS;
2528         } else {
2529                 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone)
2530                         return ENOBUFS;
2531         }
2532         return 0;
2533 }
2534
2535 static int
2536 awi_lock(sc)
2537         struct awi_softc *sc;
2538 {
2539         int error = 0;
2540
2541         if (curproc == NULL) {
2542                 /*
2543                  * XXX
2544                  * Though driver ioctl should be called with context,
2545                  * KAME ipv6 stack calls ioctl in interrupt for now.
2546                  * We simply abort the request if there are other
2547                  * ioctl requests in progress.
2548                  */
2549                 if (sc->sc_busy) {
2550                         return EWOULDBLOCK;
2551                         if (sc->sc_invalid)
2552                                 return ENXIO;
2553                 }
2554                 sc->sc_busy = 1;
2555                 sc->sc_cansleep = 0;
2556                 return 0;
2557         }
2558         while (sc->sc_busy) {
2559                 if (sc->sc_invalid)
2560                         return ENXIO;
2561                 sc->sc_sleep_cnt++;
2562                 error = tsleep(sc, PCATCH, "awilck", 0);
2563                 sc->sc_sleep_cnt--;
2564                 if (error)
2565                         return error;
2566         }
2567         sc->sc_busy = 1;
2568         sc->sc_cansleep = 1;
2569         return 0;
2570 }
2571
2572 static void
2573 awi_unlock(sc)
2574         struct awi_softc *sc;
2575 {
2576         sc->sc_busy = 0;
2577         sc->sc_cansleep = 0;
2578         if (sc->sc_sleep_cnt)
2579                 wakeup(sc);
2580 }
2581
2582 static int
2583 awi_intr_lock(sc)
2584         struct awi_softc *sc;
2585 {
2586         u_int8_t status;
2587         int i, retry;
2588
2589         status = 1;
2590         for (retry = 0; retry < 10; retry++) {
2591                 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) {
2592                         status = awi_read_1(sc, AWI_LOCKOUT_HOST);
2593                         if (status == 0)
2594                                 break;
2595                         DELAY(5);
2596                 }
2597                 if (status != 0)
2598                         break;
2599                 awi_write_1(sc, AWI_LOCKOUT_MAC, 1);
2600                 status = awi_read_1(sc, AWI_LOCKOUT_HOST);
2601                 if (status == 0)
2602                         break;
2603                 awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
2604         }
2605         if (status != 0) {
2606                 if_printf(sc->sc_ifp, "failed to lock interrupt\n");
2607                 return ENXIO;
2608         }
2609         return 0;
2610 }
2611
2612 static void
2613 awi_intr_unlock(sc)
2614         struct awi_softc *sc;
2615 {
2616
2617         awi_write_1(sc, AWI_LOCKOUT_MAC, 0);
2618 }
2619
2620 static int
2621 awi_cmd_wait(sc)
2622         struct awi_softc *sc;
2623 {
2624         int i, error = 0;
2625
2626         i = 0;
2627         while (sc->sc_cmd_inprog) {
2628                 if (sc->sc_invalid)
2629                         return ENXIO;
2630                 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) {
2631                         if_printf(sc->sc_ifp, "failed to access hardware\n");
2632                         sc->sc_invalid = 1;
2633                         return ENXIO;
2634                 }
2635                 if (sc->sc_cansleep) {
2636                         sc->sc_sleep_cnt++;
2637                         error = tsleep(sc, 0, "awicmd",
2638                             AWI_CMD_TIMEOUT*hz/1000);
2639                         sc->sc_sleep_cnt--;
2640                 } else {
2641                         if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) {
2642                                 awi_cmd_done(sc);
2643                                 break;
2644                         }
2645                         if (i++ >= AWI_CMD_TIMEOUT*1000/10)
2646                                 error = EWOULDBLOCK;
2647                         else
2648                                 DELAY(10);
2649                 }
2650                 if (error)
2651                         break;
2652         }
2653         return error;
2654 }
2655
2656 static void
2657 awi_print_essid(essid)
2658         u_int8_t *essid;
2659 {
2660         int i, len;
2661         u_int8_t *p;
2662
2663         len = essid[1];
2664         if (len > IEEE80211_NWID_LEN)
2665                 len = IEEE80211_NWID_LEN;       /*XXX*/
2666         /* determine printable or not */
2667         for (i = 0, p = essid + 2; i < len; i++, p++) {
2668                 if (*p < ' ' || *p > 0x7e)
2669                         break;
2670         }
2671         if (i == len) {
2672                 printf("\"");
2673                 for (i = 0, p = essid + 2; i < len; i++, p++)
2674                         printf("%c", *p);
2675                 printf("\"");
2676         } else {
2677                 printf("0x");
2678                 for (i = 0, p = essid + 2; i < len; i++, p++)
2679                         printf("%02x", *p);
2680         }
2681 }
2682
2683 #ifdef AWI_DEBUG
2684 static void
2685 awi_dump_pkt(sc, m, rssi)
2686         struct awi_softc *sc;
2687         struct mbuf *m;
2688         int rssi;
2689 {
2690         struct ieee80211_frame *wh;
2691         int i, l;
2692
2693         wh = mtod(m, struct ieee80211_frame *);
2694
2695         if (awi_dump_mask != 0 &&
2696             ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK)==IEEE80211_FC1_DIR_NODS) &&
2697             ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_MGT)) {
2698                 if ((AWI_DUMP_MASK(wh->i_fc[0]) & awi_dump_mask) != 0)
2699                         return;
2700         }
2701         if (awi_dump_mask < 0 &&
2702             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_DATA)
2703                 return;
2704
2705         if (rssi < 0)
2706                 printf("tx: ");
2707         else
2708                 printf("rx: ");
2709         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
2710         case IEEE80211_FC1_DIR_NODS:
2711                 printf("NODS %6D->%6D(%6D)", wh->i_addr2, ":",
2712                        wh->i_addr1, ":", wh->i_addr3, ":");
2713                 break;
2714         case IEEE80211_FC1_DIR_TODS:
2715                 printf("TODS %6D->%6D(%6D)", wh->i_addr2, ":",
2716                        wh->i_addr3, ":", wh->i_addr1, ":");
2717                 break;
2718         case IEEE80211_FC1_DIR_FROMDS:
2719                 printf("FRDS %6D->%6D(%6D)", wh->i_addr3, ":",
2720                        wh->i_addr1, ":", wh->i_addr2, ":");
2721                 break;
2722         case IEEE80211_FC1_DIR_DSTODS:
2723                 printf("DSDS %6D->%6D(%6D->%6D)", (u_int8_t *)&wh[1], ":",
2724                        wh->i_addr3, ":", wh->i_addr2, ":", wh->i_addr1, ":");
2725                 break;
2726         }
2727         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
2728         case IEEE80211_FC0_TYPE_DATA:
2729                 printf(" data");
2730                 break;
2731         case IEEE80211_FC0_TYPE_MGT:
2732                 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
2733                 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
2734                         printf(" probe_req");
2735                         break;
2736                 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2737                         printf(" probe_resp");
2738                         break;
2739                 case IEEE80211_FC0_SUBTYPE_BEACON:
2740                         printf(" beacon");
2741                         break;
2742                 case IEEE80211_FC0_SUBTYPE_AUTH:
2743                         printf(" auth");
2744                         break;
2745                 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
2746                         printf(" assoc_req");
2747                         break;
2748                 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
2749                         printf(" assoc_resp");
2750                         break;
2751                 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
2752                         printf(" reassoc_req");
2753                         break;
2754                 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
2755                         printf(" reassoc_resp");
2756                         break;
2757                 case IEEE80211_FC0_SUBTYPE_DEAUTH:
2758                         printf(" deauth");
2759                         break;
2760                 case IEEE80211_FC0_SUBTYPE_DISASSOC:
2761                         printf(" disassoc");
2762                         break;
2763                 default:
2764                         printf(" mgt#%d",
2765                             wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
2766                         break;
2767                 }
2768                 break;
2769         default:
2770                 printf(" type#%d",
2771                     wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
2772                 break;
2773         }
2774         if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2775                 printf(" WEP");
2776         if (rssi >= 0)
2777                 printf(" +%d", rssi);
2778         printf("\n");
2779         if (awi_dump_len > 0) {
2780                 l = m->m_len;
2781                 if (l > awi_dump_len + sizeof(*wh))
2782                         l = awi_dump_len + sizeof(*wh);
2783                 i = sizeof(*wh);
2784                 if (awi_dump_hdr)
2785                         i = 0;
2786                 for (; i < l; i++) {
2787                         if ((i & 1) == 0)
2788                                 printf(" ");
2789                         printf("%02x", mtod(m, u_int8_t *)[i]);
2790                 }
2791                 printf("\n");
2792         }
2793 }
2794 #endif