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