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