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