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