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