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