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