1 /* $NetBSD: awi.c,v 1.30 2000/12/18 23:57:13 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 ifp->if_flags |= IFF_OACTIVE; 966 break; 967 } 968 IFQ_DEQUEUE(&ifp->if_snd, m0); 969 AWI_BPF_MTAP(sc, m0, AWI_BPF_NORM); 970 m0 = awi_fix_txhdr(sc, m0); 971 if (sc->sc_wep_algo != NULL && m0 != NULL) 972 m0 = awi_wep_encrypt(sc, m0, 1); 973 if (m0 == NULL) { 974 ifp->if_oerrors++; 975 continue; 976 } 977 ifp->if_opackets++; 978 } 979 #ifdef AWI_DEBUG 980 if (awi_dump) 981 awi_dump_pkt(sc, m0, -1); 982 #endif 983 AWI_BPF_MTAP(sc, m0, AWI_BPF_RAW); 984 len = 0; 985 for (m = m0; m != NULL; m = m->m_next) { 986 awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *), 987 m->m_len); 988 len += m->m_len; 989 } 990 m_freem(m0); 991 rate = sc->sc_tx_rate; /*XXX*/ 992 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0); 993 awi_write_4(sc, txd + AWI_TXD_START, frame); 994 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd); 995 awi_write_4(sc, txd + AWI_TXD_LENGTH, len); 996 awi_write_1(sc, txd + AWI_TXD_RATE, rate); 997 awi_write_4(sc, txd + AWI_TXD_NDA, 0); 998 awi_write_4(sc, txd + AWI_TXD_NRA, 0); 999 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN); 1000 sc->sc_txnext = ntxd; 1001 sent++; 1002 } 1003 if (sent) { 1004 if (sc->sc_tx_timer == 0) 1005 sc->sc_tx_timer = 5; 1006 ifp->if_timer = 1; 1007 #ifdef AWI_DEBUG 1008 if (awi_verbose) 1009 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); 1010 #endif 1011 } 1012 } 1013 1014 static void 1015 awi_txint(sc) 1016 struct awi_softc *sc; 1017 { 1018 struct ifnet *ifp = sc->sc_ifp; 1019 u_int8_t flags; 1020 1021 while (sc->sc_txdone != sc->sc_txnext) { 1022 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE); 1023 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE)) 1024 break; 1025 if (flags & AWI_TXD_ST_ERROR) 1026 ifp->if_oerrors++; 1027 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) & 1028 0x7fff; 1029 } 1030 sc->sc_tx_timer = 0; 1031 ifp->if_flags &= ~IFF_OACTIVE; 1032 #ifdef AWI_DEBUG 1033 if (awi_verbose) 1034 printf("awi_txint: txdone %d txnext %d txbase %d txend %d\n", 1035 sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend); 1036 #endif 1037 awi_start(ifp); 1038 } 1039 1040 static struct mbuf * 1041 awi_fix_txhdr(sc, m0) 1042 struct awi_softc *sc; 1043 struct mbuf *m0; 1044 { 1045 struct ether_header eh; 1046 struct ieee80211_frame *wh; 1047 struct llc *llc; 1048 1049 if (m0->m_len < sizeof(eh)) { 1050 m0 = m_pullup(m0, sizeof(eh)); 1051 if (m0 == NULL) 1052 return NULL; 1053 } 1054 memcpy(&eh, mtod(m0, caddr_t), sizeof(eh)); 1055 if (sc->sc_format_llc) { 1056 m_adj(m0, sizeof(struct ether_header) - sizeof(struct llc)); 1057 llc = mtod(m0, struct llc *); 1058 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 1059 llc->llc_control = LLC_UI; 1060 llc->llc_snap.org_code[0] = llc->llc_snap.org_code[1] = 1061 llc->llc_snap.org_code[2] = 0; 1062 llc->llc_snap.ether_type = eh.ether_type; 1063 } 1064 M_PREPEND(m0, sizeof(struct ieee80211_frame), M_DONTWAIT); 1065 if (m0 == NULL) 1066 return NULL; 1067 wh = mtod(m0, struct ieee80211_frame *); 1068 1069 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; 1070 LE_WRITE_2(wh->i_dur, 0); 1071 LE_WRITE_2(wh->i_seq, 0); 1072 if (sc->sc_mib_local.Network_Mode) { 1073 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; 1074 memcpy(wh->i_addr1, sc->sc_bss.bssid, ETHER_ADDR_LEN); 1075 memcpy(wh->i_addr2, eh.ether_shost, ETHER_ADDR_LEN); 1076 memcpy(wh->i_addr3, eh.ether_dhost, ETHER_ADDR_LEN); 1077 } else { 1078 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 1079 memcpy(wh->i_addr1, eh.ether_dhost, ETHER_ADDR_LEN); 1080 memcpy(wh->i_addr2, eh.ether_shost, ETHER_ADDR_LEN); 1081 memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN); 1082 } 1083 return m0; 1084 } 1085 1086 static struct mbuf * 1087 awi_fix_rxhdr(sc, m0) 1088 struct awi_softc *sc; 1089 struct mbuf *m0; 1090 { 1091 struct ieee80211_frame wh; 1092 struct ether_header *eh; 1093 struct llc *llc; 1094 1095 if (m0->m_len < sizeof(wh)) { 1096 m_freem(m0); 1097 return NULL; 1098 } 1099 llc = (struct llc *)(mtod(m0, caddr_t) + sizeof(wh)); 1100 if (llc->llc_dsap == LLC_SNAP_LSAP && 1101 llc->llc_ssap == LLC_SNAP_LSAP && 1102 llc->llc_control == LLC_UI && 1103 llc->llc_snap.org_code[0] == 0 && 1104 llc->llc_snap.org_code[1] == 0 && 1105 llc->llc_snap.org_code[2] == 0) { 1106 memcpy(&wh, mtod(m0, caddr_t), sizeof(wh)); 1107 m_adj(m0, sizeof(wh) + sizeof(*llc) - sizeof(*eh)); 1108 eh = mtod(m0, struct ether_header *); 1109 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { 1110 case IEEE80211_FC1_DIR_NODS: 1111 memcpy(eh->ether_dhost, wh.i_addr1, ETHER_ADDR_LEN); 1112 memcpy(eh->ether_shost, wh.i_addr2, ETHER_ADDR_LEN); 1113 break; 1114 case IEEE80211_FC1_DIR_TODS: 1115 memcpy(eh->ether_dhost, wh.i_addr3, ETHER_ADDR_LEN); 1116 memcpy(eh->ether_shost, wh.i_addr2, ETHER_ADDR_LEN); 1117 break; 1118 case IEEE80211_FC1_DIR_FROMDS: 1119 memcpy(eh->ether_dhost, wh.i_addr1, ETHER_ADDR_LEN); 1120 memcpy(eh->ether_shost, wh.i_addr3, ETHER_ADDR_LEN); 1121 break; 1122 case IEEE80211_FC1_DIR_DSTODS: 1123 m_freem(m0); 1124 return NULL; 1125 } 1126 } else { 1127 /* assuming ethernet encapsulation, just strip 802.11 header */ 1128 m_adj(m0, sizeof(wh)); 1129 } 1130 if (ALIGN(mtod(m0, caddr_t) + sizeof(struct ether_header)) != 1131 (u_int)(mtod(m0, caddr_t) + sizeof(struct ether_header))) { 1132 /* XXX: we loose to estimate the type of encapsulation */ 1133 struct mbuf *n, *n0, **np; 1134 caddr_t newdata; 1135 int off; 1136 1137 n0 = NULL; 1138 np = &n0; 1139 off = 0; 1140 while (m0->m_pkthdr.len > off) { 1141 if (n0 == NULL) { 1142 MGETHDR(n, M_DONTWAIT, MT_DATA); 1143 if (n == NULL) { 1144 m_freem(m0); 1145 return NULL; 1146 } 1147 M_COPY_PKTHDR(n, m0); 1148 n->m_len = MHLEN; 1149 } else { 1150 MGET(n, M_DONTWAIT, MT_DATA); 1151 if (n == NULL) { 1152 m_freem(m0); 1153 m_freem(n0); 1154 return NULL; 1155 } 1156 n->m_len = MLEN; 1157 } 1158 if (m0->m_pkthdr.len - off >= MINCLSIZE) { 1159 MCLGET(n, M_DONTWAIT); 1160 if (n->m_flags & M_EXT) 1161 n->m_len = n->m_ext.ext_size; 1162 } 1163 if (n0 == NULL) { 1164 newdata = (caddr_t) 1165 ALIGN(n->m_data 1166 + sizeof(struct ether_header)) 1167 - sizeof(struct ether_header); 1168 n->m_len -= newdata - n->m_data; 1169 n->m_data = newdata; 1170 } 1171 if (n->m_len > m0->m_pkthdr.len - off) 1172 n->m_len = m0->m_pkthdr.len - off; 1173 m_copydata(m0, off, n->m_len, mtod(n, caddr_t)); 1174 off += n->m_len; 1175 *np = n; 1176 np = &n->m_next; 1177 } 1178 m_freem(m0); 1179 m0 = n0; 1180 } 1181 return m0; 1182 } 1183 1184 static void 1185 awi_input(sc, m, rxts, rssi) 1186 struct awi_softc *sc; 1187 struct mbuf *m; 1188 u_int32_t rxts; 1189 u_int8_t rssi; 1190 { 1191 struct ifnet *ifp = sc->sc_ifp; 1192 struct ieee80211_frame *wh; 1193 #ifndef __NetBSD__ 1194 struct ether_header *eh; 1195 #endif 1196 1197 /* trim CRC here for WEP can find its own CRC at the end of packet. */ 1198 m_adj(m, -ETHER_CRC_LEN); 1199 AWI_BPF_MTAP(sc, m, AWI_BPF_RAW); 1200 wh = mtod(m, struct ieee80211_frame *); 1201 if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != 1202 IEEE80211_FC0_VERSION_0) { 1203 printf("%s; receive packet with wrong version: %x\n", 1204 sc->sc_dev.dv_xname, wh->i_fc[0]); 1205 m_freem(m); 1206 ifp->if_ierrors++; 1207 return; 1208 } 1209 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1210 m = awi_wep_encrypt(sc, m, 0); 1211 if (m == NULL) { 1212 ifp->if_ierrors++; 1213 return; 1214 } 1215 wh = mtod(m, struct ieee80211_frame *); 1216 } 1217 #ifdef AWI_DEBUG 1218 if (awi_dump) 1219 awi_dump_pkt(sc, m, rssi); 1220 #endif 1221 1222 if ((sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid) && 1223 sc->sc_status == AWI_ST_RUNNING) { 1224 if (memcmp(wh->i_addr2, sc->sc_bss.bssid, ETHER_ADDR_LEN) == 0) { 1225 sc->sc_rx_timer = 10; 1226 sc->sc_bss.rssi = rssi; 1227 } 1228 } 1229 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 1230 case IEEE80211_FC0_TYPE_DATA: 1231 if (sc->sc_mib_local.Network_Mode) { 1232 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != 1233 IEEE80211_FC1_DIR_FROMDS) { 1234 m_freem(m); 1235 return; 1236 } 1237 } else { 1238 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != 1239 IEEE80211_FC1_DIR_NODS) { 1240 m_freem(m); 1241 return; 1242 } 1243 } 1244 m = awi_fix_rxhdr(sc, m); 1245 if (m == NULL) { 1246 ifp->if_ierrors++; 1247 break; 1248 } 1249 ifp->if_ipackets++; 1250 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 4) 1251 AWI_BPF_MTAP(sc, m, AWI_BPF_NORM); 1252 #endif 1253 #ifdef __NetBSD__ 1254 (*ifp->if_input)(ifp, m); 1255 #else 1256 eh = mtod(m, struct ether_header *); 1257 m_adj(m, sizeof(*eh)); 1258 ether_input(ifp, eh, m); 1259 #endif 1260 break; 1261 case IEEE80211_FC0_TYPE_MGT: 1262 if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != 1263 IEEE80211_FC1_DIR_NODS) { 1264 m_freem(m); 1265 return; 1266 } 1267 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 1268 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 1269 case IEEE80211_FC0_SUBTYPE_BEACON: 1270 awi_recv_beacon(sc, m, rxts, rssi); 1271 break; 1272 case IEEE80211_FC0_SUBTYPE_AUTH: 1273 awi_recv_auth(sc, m); 1274 break; 1275 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 1276 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 1277 awi_recv_asresp(sc, m); 1278 break; 1279 case IEEE80211_FC0_SUBTYPE_DEAUTH: 1280 if (sc->sc_mib_local.Network_Mode) 1281 awi_send_auth(sc, 1); 1282 break; 1283 case IEEE80211_FC0_SUBTYPE_DISASSOC: 1284 if (sc->sc_mib_local.Network_Mode) 1285 awi_send_asreq(sc, 1); 1286 break; 1287 } 1288 m_freem(m); 1289 break; 1290 case IEEE80211_FC0_TYPE_CTL: 1291 default: 1292 /* should not come here */ 1293 m_freem(m); 1294 break; 1295 } 1296 } 1297 1298 static void 1299 awi_rxint(sc) 1300 struct awi_softc *sc; 1301 { 1302 u_int8_t state, rate, rssi; 1303 u_int16_t len; 1304 u_int32_t frame, next, rxts, rxoff; 1305 struct mbuf *m; 1306 1307 rxoff = sc->sc_rxdoff; 1308 for (;;) { 1309 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE); 1310 if (state & AWI_RXD_ST_OWN) 1311 break; 1312 if (!(state & AWI_RXD_ST_CONSUMED)) { 1313 if (state & AWI_RXD_ST_RXERROR) 1314 sc->sc_ifp->if_ierrors++; 1315 else { 1316 len = awi_read_2(sc, rxoff + AWI_RXD_LEN); 1317 rate = awi_read_1(sc, rxoff + AWI_RXD_RATE); 1318 rssi = awi_read_1(sc, rxoff + AWI_RXD_RSSI); 1319 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) & 0x7fff; 1320 rxts = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME); 1321 m = awi_devget(sc, frame, len); 1322 if (state & AWI_RXD_ST_LF) 1323 awi_input(sc, m, rxts, rssi); 1324 else 1325 sc->sc_rxpend = m; 1326 } 1327 state |= AWI_RXD_ST_CONSUMED; 1328 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1329 } 1330 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT); 1331 if (next & AWI_RXD_NEXT_LAST) 1332 break; 1333 /* make sure the next pointer is correct */ 1334 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT)) 1335 break; 1336 state |= AWI_RXD_ST_OWN; 1337 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1338 rxoff = next & 0x7fff; 1339 } 1340 sc->sc_rxdoff = rxoff; 1341 } 1342 1343 static struct mbuf * 1344 awi_devget(sc, off, len) 1345 struct awi_softc *sc; 1346 u_int32_t off; 1347 u_int16_t len; 1348 { 1349 struct mbuf *m; 1350 struct mbuf *top, **mp; 1351 u_int tlen; 1352 1353 top = sc->sc_rxpend; 1354 mp = ⊤ 1355 if (top != NULL) { 1356 sc->sc_rxpend = NULL; 1357 top->m_pkthdr.len += len; 1358 m = top; 1359 while (*mp != NULL) { 1360 m = *mp; 1361 mp = &m->m_next; 1362 } 1363 if (m->m_flags & M_EXT) 1364 tlen = m->m_ext.ext_size; 1365 else if (m->m_flags & M_PKTHDR) 1366 tlen = MHLEN; 1367 else 1368 tlen = MLEN; 1369 tlen -= m->m_len; 1370 if (tlen > len) 1371 tlen = len; 1372 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen); 1373 off += tlen; 1374 len -= tlen; 1375 } 1376 1377 while (len > 0) { 1378 if (top == NULL) { 1379 MGETHDR(m, M_DONTWAIT, MT_DATA); 1380 if (m == NULL) 1381 return NULL; 1382 m->m_pkthdr.rcvif = sc->sc_ifp; 1383 m->m_pkthdr.len = len; 1384 m->m_len = MHLEN; 1385 } else { 1386 MGET(m, M_DONTWAIT, MT_DATA); 1387 if (m == NULL) { 1388 m_freem(top); 1389 return NULL; 1390 } 1391 m->m_len = MLEN; 1392 } 1393 if (len >= MINCLSIZE) { 1394 MCLGET(m, M_DONTWAIT); 1395 if (m->m_flags & M_EXT) 1396 m->m_len = m->m_ext.ext_size; 1397 } 1398 if (top == NULL) { 1399 int hdrlen = sizeof(struct ieee80211_frame) + 1400 (sc->sc_format_llc ? sizeof(struct llc) : 1401 sizeof(struct ether_header)); 1402 caddr_t newdata = (caddr_t) 1403 ALIGN(m->m_data + hdrlen) - hdrlen; 1404 m->m_len -= newdata - m->m_data; 1405 m->m_data = newdata; 1406 } 1407 if (m->m_len > len) 1408 m->m_len = len; 1409 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len); 1410 off += m->m_len; 1411 len -= m->m_len; 1412 *mp = m; 1413 mp = &m->m_next; 1414 } 1415 return top; 1416 } 1417 1418 /* 1419 * Initialize hardware and start firmware to accept commands. 1420 * Called everytime after power on firmware. 1421 */ 1422 1423 static int 1424 awi_init_hw(sc) 1425 struct awi_softc *sc; 1426 { 1427 u_int8_t status; 1428 u_int16_t intmask; 1429 int i, error; 1430 1431 sc->sc_enab_intr = 0; 1432 sc->sc_invalid = 0; /* XXX: really? */ 1433 awi_drvstate(sc, AWI_DRV_RESET); 1434 1435 /* reset firmware */ 1436 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1437 DELAY(100); 1438 awi_write_1(sc, AWI_SELFTEST, 0); 1439 awi_write_1(sc, AWI_CMD, 0); 1440 awi_write_1(sc, AWI_BANNER, 0); 1441 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1442 DELAY(100); 1443 1444 /* wait for selftest completion */ 1445 for (i = 0; ; i++) { 1446 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) { 1447 printf("%s: failed to complete selftest (timeout)\n", 1448 sc->sc_dev.dv_xname); 1449 return ENXIO; 1450 } 1451 status = awi_read_1(sc, AWI_SELFTEST); 1452 if ((status & 0xf0) == 0xf0) 1453 break; 1454 if (sc->sc_cansleep) { 1455 sc->sc_sleep_cnt++; 1456 (void)tsleep(sc, PWAIT, "awitst", 1); 1457 sc->sc_sleep_cnt--; 1458 } else { 1459 DELAY(1000*1000/hz); 1460 } 1461 } 1462 if (status != AWI_SELFTEST_PASSED) { 1463 printf("%s: failed to complete selftest (code %x)\n", 1464 sc->sc_dev.dv_xname, status); 1465 return ENXIO; 1466 } 1467 1468 /* check banner to confirm firmware write it */ 1469 awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN); 1470 if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) { 1471 printf("%s: failed to complete selftest (bad banner)\n", 1472 sc->sc_dev.dv_xname); 1473 for (i = 0; i < AWI_BANNER_LEN; i++) 1474 printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]); 1475 printf("\n"); 1476 return ENXIO; 1477 } 1478 1479 /* initializing interrupt */ 1480 sc->sc_enab_intr = 1; 1481 error = awi_intr_lock(sc); 1482 if (error) 1483 return error; 1484 intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT | 1485 AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD; 1486 awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff); 1487 awi_write_1(sc, AWI_INTMASK2, 0); 1488 awi_write_1(sc, AWI_INTSTAT, 0); 1489 awi_write_1(sc, AWI_INTSTAT2, 0); 1490 awi_intr_unlock(sc); 1491 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT); 1492 1493 /* issueing interface test command */ 1494 error = awi_cmd(sc, AWI_CMD_NOP); 1495 if (error) { 1496 printf("%s: failed to complete selftest", sc->sc_dev.dv_xname); 1497 if (error == ENXIO) 1498 printf(" (no hardware)\n"); 1499 else if (error != EWOULDBLOCK) 1500 printf(" (error %d)\n", error); 1501 else if (sc->sc_cansleep) 1502 printf(" (lost interrupt)\n"); 1503 else 1504 printf(" (command timeout)\n"); 1505 } 1506 return error; 1507 } 1508 1509 /* 1510 * Extract the factory default MIB value from firmware and assign the driver 1511 * default value. 1512 * Called once at attaching the interface. 1513 */ 1514 1515 static int 1516 awi_init_mibs(sc) 1517 struct awi_softc *sc; 1518 { 1519 int i, error; 1520 u_int8_t *rate; 1521 1522 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL)) != 0 || 1523 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR)) != 0 || 1524 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC)) != 0 || 1525 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT)) != 0 || 1526 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY)) != 0) { 1527 printf("%s: failed to get default mib value (error %d)\n", 1528 sc->sc_dev.dv_xname, error); 1529 return error; 1530 } 1531 1532 rate = sc->sc_mib_phy.aSuprt_Data_Rates; 1533 sc->sc_tx_rate = AWI_RATE_1MBIT; 1534 for (i = 0; i < rate[1]; i++) { 1535 if (AWI_80211_RATE(rate[2 + i]) > sc->sc_tx_rate) 1536 sc->sc_tx_rate = AWI_80211_RATE(rate[2 + i]); 1537 } 1538 awi_init_region(sc); 1539 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE); 1540 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID; 1541 sc->sc_mib_local.Fragmentation_Dis = 1; 1542 sc->sc_mib_local.Accept_All_Multicast_Dis = 1; 1543 sc->sc_mib_local.Power_Saving_Mode_Dis = 1; 1544 1545 /* allocate buffers */ 1546 sc->sc_txbase = AWI_BUFFERS; 1547 sc->sc_txend = sc->sc_txbase + 1548 (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) + 1549 sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS; 1550 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase); 1551 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size, 1552 sc->sc_txend - sc->sc_txbase); 1553 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend); 1554 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size, 1555 AWI_BUFFERS_END - sc->sc_txend); 1556 sc->sc_mib_local.Network_Mode = 1; 1557 sc->sc_mib_local.Acting_as_AP = 0; 1558 return 0; 1559 } 1560 1561 /* 1562 * Start transmitter and receiver of firmware 1563 * Called after awi_init_hw() to start operation. 1564 */ 1565 1566 static int 1567 awi_init_txrx(sc) 1568 struct awi_softc *sc; 1569 { 1570 int error; 1571 1572 /* start transmitter */ 1573 sc->sc_txdone = sc->sc_txnext = sc->sc_txbase; 1574 awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0); 1575 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0); 1576 awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0); 1577 awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0); 1578 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0); 1579 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0); 1580 awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0); 1581 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_DATA, sc->sc_txbase); 1582 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_MGT, 0); 1583 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_BCAST, 0); 1584 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_PS, 0); 1585 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_TX_CF, 0); 1586 error = awi_cmd(sc, AWI_CMD_INIT_TX); 1587 if (error) 1588 return error; 1589 1590 /* start receiver */ 1591 if (sc->sc_rxpend) { 1592 m_freem(sc->sc_rxpend); 1593 sc->sc_rxpend = NULL; 1594 } 1595 error = awi_cmd(sc, AWI_CMD_INIT_RX); 1596 if (error) 1597 return error; 1598 sc->sc_rxdoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_DATA_DESC); 1599 sc->sc_rxmoff = awi_read_4(sc, AWI_CMD_PARAMS+AWI_CA_IRX_PS_DESC); 1600 return 0; 1601 } 1602 1603 static void 1604 awi_stop_txrx(sc) 1605 struct awi_softc *sc; 1606 { 1607 1608 if (sc->sc_cmd_inprog) 1609 (void)awi_cmd_wait(sc); 1610 (void)awi_cmd(sc, AWI_CMD_KILL_RX); 1611 (void)awi_cmd_wait(sc); 1612 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX; 1613 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_DATA, 1); 1614 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_MGT, 0); 1615 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_BCAST, 0); 1616 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_PS, 0); 1617 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_FTX_CF, 0); 1618 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX); 1619 (void)awi_cmd_wait(sc); 1620 } 1621 1622 int 1623 awi_init_region(sc) 1624 struct awi_softc *sc; 1625 { 1626 1627 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1628 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) { 1629 case AWI_REG_DOMAIN_US: 1630 case AWI_REG_DOMAIN_CA: 1631 case AWI_REG_DOMAIN_EU: 1632 sc->sc_scan_min = 0; 1633 sc->sc_scan_max = 77; 1634 break; 1635 case AWI_REG_DOMAIN_ES: 1636 sc->sc_scan_min = 0; 1637 sc->sc_scan_max = 26; 1638 break; 1639 case AWI_REG_DOMAIN_FR: 1640 sc->sc_scan_min = 0; 1641 sc->sc_scan_max = 32; 1642 break; 1643 case AWI_REG_DOMAIN_JP: 1644 sc->sc_scan_min = 6; 1645 sc->sc_scan_max = 17; 1646 break; 1647 default: 1648 return EINVAL; 1649 } 1650 sc->sc_scan_set = sc->sc_scan_cur % 3 + 1; 1651 } else { 1652 switch (sc->sc_mib_phy.aCurrent_Reg_Domain) { 1653 case AWI_REG_DOMAIN_US: 1654 case AWI_REG_DOMAIN_CA: 1655 sc->sc_scan_min = 1; 1656 sc->sc_scan_max = 11; 1657 sc->sc_scan_cur = 3; 1658 break; 1659 case AWI_REG_DOMAIN_EU: 1660 sc->sc_scan_min = 1; 1661 sc->sc_scan_max = 13; 1662 sc->sc_scan_cur = 3; 1663 break; 1664 case AWI_REG_DOMAIN_ES: 1665 sc->sc_scan_min = 10; 1666 sc->sc_scan_max = 11; 1667 sc->sc_scan_cur = 10; 1668 break; 1669 case AWI_REG_DOMAIN_FR: 1670 sc->sc_scan_min = 10; 1671 sc->sc_scan_max = 13; 1672 sc->sc_scan_cur = 10; 1673 break; 1674 case AWI_REG_DOMAIN_JP: 1675 sc->sc_scan_min = 14; 1676 sc->sc_scan_max = 14; 1677 sc->sc_scan_cur = 14; 1678 break; 1679 default: 1680 return EINVAL; 1681 } 1682 } 1683 sc->sc_ownch = sc->sc_scan_cur; 1684 return 0; 1685 } 1686 1687 static int 1688 awi_start_scan(sc) 1689 struct awi_softc *sc; 1690 { 1691 int error = 0; 1692 struct awi_bss *bp; 1693 1694 while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) { 1695 TAILQ_REMOVE(&sc->sc_scan, bp, list); 1696 free(bp, M_DEVBUF); 1697 } 1698 if (!sc->sc_mib_local.Network_Mode && sc->sc_no_bssid) { 1699 memset(&sc->sc_bss, 0, sizeof(sc->sc_bss)); 1700 sc->sc_bss.essid[0] = IEEE80211_ELEMID_SSID; 1701 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1702 sc->sc_bss.chanset = sc->sc_ownch % 3 + 1; 1703 sc->sc_bss.pattern = sc->sc_ownch; 1704 sc->sc_bss.index = 1; 1705 sc->sc_bss.dwell_time = 200; /*XXX*/ 1706 } else 1707 sc->sc_bss.chanset = sc->sc_ownch; 1708 sc->sc_status = AWI_ST_SETSS; 1709 error = awi_set_ss(sc); 1710 } else { 1711 if (sc->sc_mib_local.Network_Mode) 1712 awi_drvstate(sc, AWI_DRV_INFSC); 1713 else 1714 awi_drvstate(sc, AWI_DRV_ADHSC); 1715 sc->sc_start_bss = 0; 1716 sc->sc_active_scan = 1; 1717 sc->sc_mgt_timer = AWI_ASCAN_WAIT / 1000; 1718 sc->sc_ifp->if_timer = 1; 1719 sc->sc_status = AWI_ST_SCAN; 1720 error = awi_cmd_scan(sc); 1721 } 1722 return error; 1723 } 1724 1725 static int 1726 awi_next_scan(sc) 1727 struct awi_softc *sc; 1728 { 1729 int error; 1730 1731 for (;;) { 1732 /* 1733 * The pattern parameter for FH phy should be incremented 1734 * by 3. But BayStack 650 Access Points apparently always 1735 * assign hop pattern set parameter to 1 for any pattern. 1736 * So we try all combinations of pattern/set parameters. 1737 * Since this causes no error, it may be a bug of 1738 * PCnetMobile firmware. 1739 */ 1740 sc->sc_scan_cur++; 1741 if (sc->sc_scan_cur > sc->sc_scan_max) { 1742 sc->sc_scan_cur = sc->sc_scan_min; 1743 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 1744 sc->sc_scan_set = sc->sc_scan_set % 3 + 1; 1745 } 1746 error = awi_cmd_scan(sc); 1747 if (error != EINVAL) 1748 break; 1749 } 1750 return error; 1751 } 1752 1753 static void 1754 awi_stop_scan(sc) 1755 struct awi_softc *sc; 1756 { 1757 struct ifnet *ifp = sc->sc_ifp; 1758 struct awi_bss *bp, *sbp; 1759 int fail; 1760 1761 bp = TAILQ_FIRST(&sc->sc_scan); 1762 if (bp == NULL) { 1763 notfound: 1764 if (sc->sc_active_scan) { 1765 if (ifp->if_flags & IFF_DEBUG) 1766 printf("%s: entering passive scan mode\n", 1767 sc->sc_dev.dv_xname); 1768 sc->sc_active_scan = 0; 1769 } 1770 sc->sc_mgt_timer = AWI_PSCAN_WAIT / 1000; 1771 ifp->if_timer = 1; 1772 (void)awi_next_scan(sc); 1773 return; 1774 } 1775 sbp = NULL; 1776 if (ifp->if_flags & IFF_DEBUG) 1777 printf("%s:\tmacaddr ch/pat sig flag wep essid\n", 1778 sc->sc_dev.dv_xname); 1779 for (; bp != NULL; bp = TAILQ_NEXT(bp, list)) { 1780 if (bp->fails) { 1781 /* 1782 * The configuration of the access points may change 1783 * during my scan. So we retries to associate with 1784 * it unless there are any suitable AP. 1785 */ 1786 if (bp->fails++ < 3) 1787 continue; 1788 bp->fails = 0; 1789 } 1790 fail = 0; 1791 /* 1792 * Since the firmware apparently scans not only the specified 1793 * channel of SCAN command but all available channel within 1794 * the region, we should filter out unnecessary responses here. 1795 */ 1796 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1797 if (bp->pattern < sc->sc_scan_min || 1798 bp->pattern > sc->sc_scan_max) 1799 fail |= 0x01; 1800 } else { 1801 if (bp->chanset < sc->sc_scan_min || 1802 bp->chanset > sc->sc_scan_max) 1803 fail |= 0x01; 1804 } 1805 if (sc->sc_mib_local.Network_Mode) { 1806 if (!(bp->capinfo & IEEE80211_CAPINFO_ESS) || 1807 (bp->capinfo & IEEE80211_CAPINFO_IBSS)) 1808 fail |= 0x02; 1809 } else { 1810 if ((bp->capinfo & IEEE80211_CAPINFO_ESS) || 1811 !(bp->capinfo & IEEE80211_CAPINFO_IBSS)) 1812 fail |= 0x02; 1813 } 1814 if (sc->sc_wep_algo == NULL) { 1815 if (bp->capinfo & IEEE80211_CAPINFO_PRIVACY) 1816 fail |= 0x04; 1817 } else { 1818 if (!(bp->capinfo & IEEE80211_CAPINFO_PRIVACY)) 1819 fail |= 0x04; 1820 } 1821 if (sc->sc_mib_mac.aDesired_ESS_ID[1] != 0 && 1822 memcmp(&sc->sc_mib_mac.aDesired_ESS_ID, bp->essid, 1823 sizeof(bp->essid)) != 0) 1824 fail |= 0x08; 1825 if (ifp->if_flags & IFF_DEBUG) { 1826 printf(" %c %s", fail ? '-' : '+', 1827 ether_sprintf(bp->esrc)); 1828 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 1829 printf(" %2d/%d%c", bp->pattern, bp->chanset, 1830 fail & 0x01 ? '!' : ' '); 1831 else 1832 printf(" %4d%c", bp->chanset, 1833 fail & 0x01 ? '!' : ' '); 1834 printf(" %+4d", bp->rssi); 1835 printf(" %4s%c", 1836 (bp->capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : 1837 (bp->capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : 1838 "????", 1839 fail & 0x02 ? '!' : ' '); 1840 printf(" %3s%c ", 1841 (bp->capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" : 1842 "no", 1843 fail & 0x04 ? '!' : ' '); 1844 awi_print_essid(bp->essid); 1845 printf("%s\n", fail & 0x08 ? "!" : ""); 1846 } 1847 if (!fail) { 1848 if (sbp == NULL || bp->rssi > sbp->rssi) 1849 sbp = bp; 1850 } 1851 } 1852 if (sbp == NULL) 1853 goto notfound; 1854 sc->sc_bss = *sbp; 1855 (void)awi_set_ss(sc); 1856 } 1857 1858 static void 1859 awi_recv_beacon(sc, m0, rxts, rssi) 1860 struct awi_softc *sc; 1861 struct mbuf *m0; 1862 u_int32_t rxts; 1863 u_int8_t rssi; 1864 { 1865 struct ieee80211_frame *wh; 1866 struct awi_bss *bp; 1867 u_int8_t *frame, *eframe; 1868 u_int8_t *tstamp, *bintval, *capinfo, *ssid, *rates, *parms; 1869 1870 if (sc->sc_status != AWI_ST_SCAN) 1871 return; 1872 wh = mtod(m0, struct ieee80211_frame *); 1873 1874 frame = (u_int8_t *)&wh[1]; 1875 eframe = mtod(m0, u_int8_t *) + m0->m_len; 1876 /* 1877 * XXX: 1878 * timestamp [8] 1879 * beacon interval [2] 1880 * capability information [2] 1881 * ssid [tlv] 1882 * supported rates [tlv] 1883 * parameter set [tlv] 1884 * ... 1885 */ 1886 if (frame + 12 > eframe) { 1887 #ifdef AWI_DEBUG 1888 if (awi_verbose) 1889 printf("awi_recv_beacon: frame too short \n"); 1890 #endif 1891 return; 1892 } 1893 tstamp = frame; 1894 frame += 8; 1895 bintval = frame; 1896 frame += 2; 1897 capinfo = frame; 1898 frame += 2; 1899 1900 ssid = rates = parms = NULL; 1901 while (frame < eframe) { 1902 switch (*frame) { 1903 case IEEE80211_ELEMID_SSID: 1904 ssid = frame; 1905 break; 1906 case IEEE80211_ELEMID_RATES: 1907 rates = frame; 1908 break; 1909 case IEEE80211_ELEMID_FHPARMS: 1910 case IEEE80211_ELEMID_DSPARMS: 1911 parms = frame; 1912 break; 1913 } 1914 frame += frame[1] + 2; 1915 } 1916 if (ssid == NULL || rates == NULL || parms == NULL) { 1917 #ifdef AWI_DEBUG 1918 if (awi_verbose) 1919 printf("awi_recv_beacon: ssid=%p, rates=%p, parms=%p\n", 1920 ssid, rates, parms); 1921 #endif 1922 return; 1923 } 1924 if (ssid[1] > IEEE80211_NWID_LEN) { 1925 #ifdef AWI_DEBUG 1926 if (awi_verbose) 1927 printf("awi_recv_beacon: bad ssid len: %d from %s\n", 1928 ssid[1], ether_sprintf(wh->i_addr2)); 1929 #endif 1930 return; 1931 } 1932 1933 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL; 1934 bp = TAILQ_NEXT(bp, list)) { 1935 if (memcmp(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN) == 0 && 1936 memcmp(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN) == 0) 1937 break; 1938 } 1939 if (bp == NULL) { 1940 bp = malloc(sizeof(struct awi_bss), M_DEVBUF, M_NOWAIT); 1941 if (bp == NULL) 1942 return; 1943 TAILQ_INSERT_TAIL(&sc->sc_scan, bp, list); 1944 memcpy(bp->esrc, wh->i_addr2, ETHER_ADDR_LEN); 1945 memcpy(bp->bssid, wh->i_addr3, ETHER_ADDR_LEN); 1946 memset(bp->essid, 0, sizeof(bp->essid)); 1947 memcpy(bp->essid, ssid, 2 + ssid[1]); 1948 } 1949 bp->rssi = rssi; 1950 bp->rxtime = rxts; 1951 memcpy(bp->timestamp, tstamp, sizeof(bp->timestamp)); 1952 bp->interval = LE_READ_2(bintval); 1953 bp->capinfo = LE_READ_2(capinfo); 1954 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1955 bp->chanset = parms[4]; 1956 bp->pattern = parms[5]; 1957 bp->index = parms[6]; 1958 bp->dwell_time = LE_READ_2(parms + 2); 1959 } else { 1960 bp->chanset = parms[2]; 1961 bp->pattern = 0; 1962 bp->index = 0; 1963 bp->dwell_time = 0; 1964 } 1965 if (sc->sc_mgt_timer == 0) 1966 awi_stop_scan(sc); 1967 } 1968 1969 static int 1970 awi_set_ss(sc) 1971 struct awi_softc *sc; 1972 { 1973 struct ifnet *ifp = sc->sc_ifp; 1974 struct awi_bss *bp; 1975 int error; 1976 1977 sc->sc_status = AWI_ST_SETSS; 1978 bp = &sc->sc_bss; 1979 if (ifp->if_flags & IFF_DEBUG) { 1980 printf("%s: ch %d pat %d id %d dw %d iv %d bss %s ssid ", 1981 sc->sc_dev.dv_xname, bp->chanset, 1982 bp->pattern, bp->index, bp->dwell_time, bp->interval, 1983 ether_sprintf(bp->bssid)); 1984 awi_print_essid(bp->essid); 1985 printf("\n"); 1986 } 1987 memcpy(&sc->sc_mib_mgt.aCurrent_BSS_ID, bp->bssid, ETHER_ADDR_LEN); 1988 memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID, bp->essid, 1989 AWI_ESS_ID_SIZE); 1990 LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, bp->interval); 1991 error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT); 1992 return error; 1993 } 1994 1995 static void 1996 awi_try_sync(sc) 1997 struct awi_softc *sc; 1998 { 1999 struct awi_bss *bp; 2000 2001 sc->sc_status = AWI_ST_SYNC; 2002 bp = &sc->sc_bss; 2003 2004 if (sc->sc_cmd_inprog) { 2005 if (awi_cmd_wait(sc)) 2006 return; 2007 } 2008 sc->sc_cmd_inprog = AWI_CMD_SYNC; 2009 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_SET, bp->chanset); 2010 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_PATTERN, bp->pattern); 2011 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_IDX, bp->index); 2012 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_STARTBSS, 2013 sc->sc_start_bss ? 1 : 0); 2014 awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_DWELL, bp->dwell_time); 2015 awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_MBZ, 0); 2016 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_TIMESTAMP, 2017 bp->timestamp, 8); 2018 awi_write_4(sc, AWI_CMD_PARAMS+AWI_CA_SYNC_REFTIME, bp->rxtime); 2019 (void)awi_cmd(sc, AWI_CMD_SYNC); 2020 } 2021 2022 static void 2023 awi_sync_done(sc) 2024 struct awi_softc *sc; 2025 { 2026 struct ifnet *ifp = sc->sc_ifp; 2027 2028 if (sc->sc_mib_local.Network_Mode) { 2029 awi_drvstate(sc, AWI_DRV_INFSY); 2030 awi_send_auth(sc, 1); 2031 } else { 2032 if (ifp->if_flags & IFF_DEBUG) { 2033 printf("%s: synced with", sc->sc_dev.dv_xname); 2034 if (sc->sc_no_bssid) 2035 printf(" no-bssid"); 2036 else { 2037 printf(" %s ssid ", 2038 ether_sprintf(sc->sc_bss.bssid)); 2039 awi_print_essid(sc->sc_bss.essid); 2040 } 2041 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 2042 printf(" at chanset %d pattern %d\n", 2043 sc->sc_bss.chanset, sc->sc_bss.pattern); 2044 else 2045 printf(" at channel %d\n", sc->sc_bss.chanset); 2046 } 2047 awi_drvstate(sc, AWI_DRV_ADHSY); 2048 sc->sc_status = AWI_ST_RUNNING; 2049 ifp->if_flags |= IFF_RUNNING; 2050 awi_start(ifp); 2051 } 2052 } 2053 2054 static void 2055 awi_send_deauth(sc) 2056 struct awi_softc *sc; 2057 { 2058 struct ifnet *ifp = sc->sc_ifp; 2059 struct mbuf *m; 2060 struct ieee80211_frame *wh; 2061 u_int8_t *deauth; 2062 2063 MGETHDR(m, M_DONTWAIT, MT_DATA); 2064 if (m == NULL) 2065 return; 2066 if (ifp->if_flags & IFF_DEBUG) 2067 printf("%s: sending deauth to %s\n", sc->sc_dev.dv_xname, 2068 ether_sprintf(sc->sc_bss.bssid)); 2069 2070 wh = mtod(m, struct ieee80211_frame *); 2071 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 2072 IEEE80211_FC0_SUBTYPE_AUTH; 2073 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2074 LE_WRITE_2(wh->i_dur, 0); 2075 LE_WRITE_2(wh->i_seq, 0); 2076 memcpy(wh->i_addr1, sc->sc_bss.bssid, ETHER_ADDR_LEN); 2077 memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN); 2078 memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN); 2079 2080 deauth = (u_int8_t *)&wh[1]; 2081 LE_WRITE_2(deauth, IEEE80211_REASON_AUTH_LEAVE); 2082 deauth += 2; 2083 2084 m->m_pkthdr.len = m->m_len = deauth - mtod(m, u_int8_t *); 2085 IF_ENQUEUE(&sc->sc_mgtq, m); 2086 awi_start(ifp); 2087 awi_drvstate(sc, AWI_DRV_INFTOSS); 2088 } 2089 2090 static void 2091 awi_send_auth(sc, seq) 2092 struct awi_softc *sc; 2093 int seq; 2094 { 2095 struct ifnet *ifp = sc->sc_ifp; 2096 struct mbuf *m; 2097 struct ieee80211_frame *wh; 2098 u_int8_t *auth; 2099 2100 MGETHDR(m, M_DONTWAIT, MT_DATA); 2101 if (m == NULL) 2102 return; 2103 sc->sc_status = AWI_ST_AUTH; 2104 if (ifp->if_flags & IFF_DEBUG) 2105 printf("%s: sending auth to %s\n", sc->sc_dev.dv_xname, 2106 ether_sprintf(sc->sc_bss.bssid)); 2107 2108 wh = mtod(m, struct ieee80211_frame *); 2109 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 2110 IEEE80211_FC0_SUBTYPE_AUTH; 2111 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2112 LE_WRITE_2(wh->i_dur, 0); 2113 LE_WRITE_2(wh->i_seq, 0); 2114 memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN); 2115 memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN); 2116 memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN); 2117 2118 auth = (u_int8_t *)&wh[1]; 2119 /* algorithm number */ 2120 LE_WRITE_2(auth, IEEE80211_AUTH_ALG_OPEN); 2121 auth += 2; 2122 /* sequence number */ 2123 LE_WRITE_2(auth, seq); 2124 auth += 2; 2125 /* status */ 2126 LE_WRITE_2(auth, 0); 2127 auth += 2; 2128 2129 m->m_pkthdr.len = m->m_len = auth - mtod(m, u_int8_t *); 2130 IF_ENQUEUE(&sc->sc_mgtq, m); 2131 awi_start(ifp); 2132 2133 sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000; 2134 ifp->if_timer = 1; 2135 } 2136 2137 static void 2138 awi_recv_auth(sc, m0) 2139 struct awi_softc *sc; 2140 struct mbuf *m0; 2141 { 2142 struct ieee80211_frame *wh; 2143 u_int8_t *auth, *eframe; 2144 struct awi_bss *bp; 2145 u_int16_t status; 2146 2147 wh = mtod(m0, struct ieee80211_frame *); 2148 auth = (u_int8_t *)&wh[1]; 2149 eframe = mtod(m0, u_int8_t *) + m0->m_len; 2150 if (sc->sc_ifp->if_flags & IFF_DEBUG) 2151 printf("%s: receive auth from %s\n", sc->sc_dev.dv_xname, 2152 ether_sprintf(wh->i_addr2)); 2153 2154 /* algorithm number */ 2155 if (LE_READ_2(auth) != IEEE80211_AUTH_ALG_OPEN) 2156 return; 2157 auth += 2; 2158 if (!sc->sc_mib_local.Network_Mode) { 2159 if (sc->sc_status != AWI_ST_RUNNING) 2160 return; 2161 if (LE_READ_2(auth) == 1) 2162 awi_send_auth(sc, 2); 2163 return; 2164 } 2165 if (sc->sc_status != AWI_ST_AUTH) 2166 return; 2167 /* sequence number */ 2168 if (LE_READ_2(auth) != 2) 2169 return; 2170 auth += 2; 2171 /* status */ 2172 status = LE_READ_2(auth); 2173 if (status != 0) { 2174 printf("%s: authentication failed (reason %d)\n", 2175 sc->sc_dev.dv_xname, status); 2176 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL; 2177 bp = TAILQ_NEXT(bp, list)) { 2178 if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN) 2179 == 0) { 2180 bp->fails++; 2181 break; 2182 } 2183 } 2184 return; 2185 } 2186 sc->sc_mgt_timer = 0; 2187 awi_drvstate(sc, AWI_DRV_INFAUTH); 2188 awi_send_asreq(sc, 0); 2189 } 2190 2191 static void 2192 awi_send_asreq(sc, reassoc) 2193 struct awi_softc *sc; 2194 int reassoc; 2195 { 2196 struct ifnet *ifp = sc->sc_ifp; 2197 struct mbuf *m; 2198 struct ieee80211_frame *wh; 2199 u_int16_t lintval; 2200 u_int8_t *asreq; 2201 2202 MGETHDR(m, M_DONTWAIT, MT_DATA); 2203 if (m == NULL) 2204 return; 2205 sc->sc_status = AWI_ST_ASSOC; 2206 if (ifp->if_flags & IFF_DEBUG) 2207 printf("%s: sending %sassoc req to %s\n", sc->sc_dev.dv_xname, 2208 reassoc ? "re" : "", 2209 ether_sprintf(sc->sc_bss.bssid)); 2210 2211 wh = mtod(m, struct ieee80211_frame *); 2212 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT; 2213 if (reassoc) 2214 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_REASSOC_REQ; 2215 else 2216 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 2217 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 2218 LE_WRITE_2(wh->i_dur, 0); 2219 LE_WRITE_2(wh->i_seq, 0); 2220 memcpy(wh->i_addr1, sc->sc_bss.esrc, ETHER_ADDR_LEN); 2221 memcpy(wh->i_addr2, sc->sc_mib_addr.aMAC_Address, ETHER_ADDR_LEN); 2222 memcpy(wh->i_addr3, sc->sc_bss.bssid, ETHER_ADDR_LEN); 2223 2224 asreq = (u_int8_t *)&wh[1]; 2225 2226 /* capability info */ 2227 if (sc->sc_wep_algo == NULL) 2228 LE_WRITE_2(asreq, IEEE80211_CAPINFO_CF_POLLABLE); 2229 else 2230 LE_WRITE_2(asreq, 2231 IEEE80211_CAPINFO_CF_POLLABLE | IEEE80211_CAPINFO_PRIVACY); 2232 asreq += 2; 2233 /* listen interval */ 2234 lintval = LE_READ_2(&sc->sc_mib_mgt.aListen_Interval); 2235 LE_WRITE_2(asreq, lintval); 2236 asreq += 2; 2237 if (reassoc) { 2238 /* current AP address */ 2239 memcpy(asreq, sc->sc_bss.bssid, ETHER_ADDR_LEN); 2240 asreq += ETHER_ADDR_LEN; 2241 } 2242 /* ssid */ 2243 memcpy(asreq, sc->sc_bss.essid, 2 + sc->sc_bss.essid[1]); 2244 asreq += 2 + asreq[1]; 2245 /* supported rates */ 2246 memcpy(asreq, &sc->sc_mib_phy.aSuprt_Data_Rates, 4); 2247 asreq += 2 + asreq[1]; 2248 2249 m->m_pkthdr.len = m->m_len = asreq - mtod(m, u_int8_t *); 2250 IF_ENQUEUE(&sc->sc_mgtq, m); 2251 awi_start(ifp); 2252 2253 sc->sc_mgt_timer = AWI_TRANS_TIMEOUT / 1000; 2254 ifp->if_timer = 1; 2255 } 2256 2257 static void 2258 awi_recv_asresp(sc, m0) 2259 struct awi_softc *sc; 2260 struct mbuf *m0; 2261 { 2262 struct ieee80211_frame *wh; 2263 u_int8_t *asresp, *eframe; 2264 u_int16_t status; 2265 u_int8_t rate, *phy_rates; 2266 struct awi_bss *bp; 2267 int i, j; 2268 2269 wh = mtod(m0, struct ieee80211_frame *); 2270 asresp = (u_int8_t *)&wh[1]; 2271 eframe = mtod(m0, u_int8_t *) + m0->m_len; 2272 if (sc->sc_ifp->if_flags & IFF_DEBUG) 2273 printf("%s: receive assoc resp from %s\n", sc->sc_dev.dv_xname, 2274 ether_sprintf(wh->i_addr2)); 2275 2276 if (!sc->sc_mib_local.Network_Mode) 2277 return; 2278 2279 if (sc->sc_status != AWI_ST_ASSOC) 2280 return; 2281 /* capability info */ 2282 asresp += 2; 2283 /* status */ 2284 status = LE_READ_2(asresp); 2285 if (status != 0) { 2286 printf("%s: association failed (reason %d)\n", 2287 sc->sc_dev.dv_xname, status); 2288 for (bp = TAILQ_FIRST(&sc->sc_scan); bp != NULL; 2289 bp = TAILQ_NEXT(bp, list)) { 2290 if (memcmp(bp->esrc, sc->sc_bss.esrc, ETHER_ADDR_LEN) 2291 == 0) { 2292 bp->fails++; 2293 break; 2294 } 2295 } 2296 return; 2297 } 2298 asresp += 2; 2299 /* association id */ 2300 asresp += 2; 2301 /* supported rates */ 2302 rate = AWI_RATE_1MBIT; 2303 for (i = 0; i < asresp[1]; i++) { 2304 if (AWI_80211_RATE(asresp[2 + i]) <= rate) 2305 continue; 2306 phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates; 2307 for (j = 0; j < phy_rates[1]; j++) { 2308 if (AWI_80211_RATE(asresp[2 + i]) == 2309 AWI_80211_RATE(phy_rates[2 + j])) 2310 rate = AWI_80211_RATE(asresp[2 + i]); 2311 } 2312 } 2313 if (sc->sc_ifp->if_flags & IFF_DEBUG) { 2314 printf("%s: associated with %s ssid ", 2315 sc->sc_dev.dv_xname, ether_sprintf(sc->sc_bss.bssid)); 2316 awi_print_essid(sc->sc_bss.essid); 2317 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 2318 printf(" chanset %d pattern %d\n", 2319 sc->sc_bss.chanset, sc->sc_bss.pattern); 2320 else 2321 printf(" channel %d\n", sc->sc_bss.chanset); 2322 } 2323 sc->sc_tx_rate = rate; 2324 sc->sc_mgt_timer = 0; 2325 sc->sc_rx_timer = 10; 2326 sc->sc_ifp->if_timer = 1; 2327 sc->sc_status = AWI_ST_RUNNING; 2328 sc->sc_ifp->if_flags |= IFF_RUNNING; 2329 awi_drvstate(sc, AWI_DRV_INFASSOC); 2330 awi_start(sc->sc_ifp); 2331 } 2332 2333 static int 2334 awi_mib(sc, cmd, mib) 2335 struct awi_softc *sc; 2336 u_int8_t cmd; 2337 u_int8_t mib; 2338 { 2339 int error; 2340 u_int8_t size, *ptr; 2341 2342 switch (mib) { 2343 case AWI_MIB_LOCAL: 2344 ptr = (u_int8_t *)&sc->sc_mib_local; 2345 size = sizeof(sc->sc_mib_local); 2346 break; 2347 case AWI_MIB_ADDR: 2348 ptr = (u_int8_t *)&sc->sc_mib_addr; 2349 size = sizeof(sc->sc_mib_addr); 2350 break; 2351 case AWI_MIB_MAC: 2352 ptr = (u_int8_t *)&sc->sc_mib_mac; 2353 size = sizeof(sc->sc_mib_mac); 2354 break; 2355 case AWI_MIB_STAT: 2356 ptr = (u_int8_t *)&sc->sc_mib_stat; 2357 size = sizeof(sc->sc_mib_stat); 2358 break; 2359 case AWI_MIB_MGT: 2360 ptr = (u_int8_t *)&sc->sc_mib_mgt; 2361 size = sizeof(sc->sc_mib_mgt); 2362 break; 2363 case AWI_MIB_PHY: 2364 ptr = (u_int8_t *)&sc->sc_mib_phy; 2365 size = sizeof(sc->sc_mib_phy); 2366 break; 2367 default: 2368 return EINVAL; 2369 } 2370 if (sc->sc_cmd_inprog) { 2371 error = awi_cmd_wait(sc); 2372 if (error) { 2373 if (error == EWOULDBLOCK) 2374 printf("awi_mib: cmd %d inprog", 2375 sc->sc_cmd_inprog); 2376 return error; 2377 } 2378 } 2379 sc->sc_cmd_inprog = cmd; 2380 if (cmd == AWI_CMD_SET_MIB) 2381 awi_write_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size); 2382 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_TYPE, mib); 2383 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_SIZE, size); 2384 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_MIB_INDEX, 0); 2385 error = awi_cmd(sc, cmd); 2386 if (error) 2387 return error; 2388 if (cmd == AWI_CMD_GET_MIB) { 2389 awi_read_bytes(sc, AWI_CMD_PARAMS+AWI_CA_MIB_DATA, ptr, size); 2390 #ifdef AWI_DEBUG 2391 if (awi_verbose) { 2392 int i; 2393 2394 printf("awi_mib: #%d:", mib); 2395 for (i = 0; i < size; i++) 2396 printf(" %02x", ptr[i]); 2397 printf("\n"); 2398 } 2399 #endif 2400 } 2401 return 0; 2402 } 2403 2404 static int 2405 awi_cmd_scan(sc) 2406 struct awi_softc *sc; 2407 { 2408 int error; 2409 u_int8_t scan_mode; 2410 2411 if (sc->sc_active_scan) 2412 scan_mode = AWI_SCAN_ACTIVE; 2413 else 2414 scan_mode = AWI_SCAN_PASSIVE; 2415 if (sc->sc_mib_mgt.aScan_Mode != scan_mode) { 2416 sc->sc_mib_mgt.aScan_Mode = scan_mode; 2417 error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT); 2418 return error; 2419 } 2420 2421 if (sc->sc_cmd_inprog) { 2422 error = awi_cmd_wait(sc); 2423 if (error) 2424 return error; 2425 } 2426 sc->sc_cmd_inprog = AWI_CMD_SCAN; 2427 awi_write_2(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_DURATION, 2428 sc->sc_active_scan ? AWI_ASCAN_DURATION : AWI_PSCAN_DURATION); 2429 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 2430 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET, 2431 sc->sc_scan_set); 2432 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN, 2433 sc->sc_scan_cur); 2434 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 1); 2435 } else { 2436 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SET, 2437 sc->sc_scan_cur); 2438 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_PATTERN, 0); 2439 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_IDX, 0); 2440 } 2441 awi_write_1(sc, AWI_CMD_PARAMS+AWI_CA_SCAN_SUSP, 0); 2442 return awi_cmd(sc, AWI_CMD_SCAN); 2443 } 2444 2445 static int 2446 awi_cmd(sc, cmd) 2447 struct awi_softc *sc; 2448 u_int8_t cmd; 2449 { 2450 u_int8_t status; 2451 int error = 0; 2452 2453 sc->sc_cmd_inprog = cmd; 2454 awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE); 2455 awi_write_1(sc, AWI_CMD, cmd); 2456 if (sc->sc_status != AWI_ST_INIT) 2457 return 0; 2458 error = awi_cmd_wait(sc); 2459 if (error) 2460 return error; 2461 status = awi_read_1(sc, AWI_CMD_STATUS); 2462 awi_write_1(sc, AWI_CMD, 0); 2463 switch (status) { 2464 case AWI_STAT_OK: 2465 break; 2466 case AWI_STAT_BADPARM: 2467 return EINVAL; 2468 default: 2469 printf("%s: command %d failed %x\n", 2470 sc->sc_dev.dv_xname, cmd, status); 2471 return ENXIO; 2472 } 2473 return 0; 2474 } 2475 2476 static void 2477 awi_cmd_done(sc) 2478 struct awi_softc *sc; 2479 { 2480 u_int8_t cmd, status; 2481 2482 status = awi_read_1(sc, AWI_CMD_STATUS); 2483 if (status == AWI_STAT_IDLE) 2484 return; /* stray interrupt */ 2485 2486 cmd = sc->sc_cmd_inprog; 2487 sc->sc_cmd_inprog = 0; 2488 if (sc->sc_status == AWI_ST_INIT) { 2489 wakeup(sc); 2490 return; 2491 } 2492 awi_write_1(sc, AWI_CMD, 0); 2493 2494 if (status != AWI_STAT_OK) { 2495 printf("%s: command %d failed %x\n", 2496 sc->sc_dev.dv_xname, cmd, status); 2497 return; 2498 } 2499 switch (sc->sc_status) { 2500 case AWI_ST_SCAN: 2501 if (cmd == AWI_CMD_SET_MIB) 2502 awi_cmd_scan(sc); /* retry */ 2503 break; 2504 case AWI_ST_SETSS: 2505 awi_try_sync(sc); 2506 break; 2507 case AWI_ST_SYNC: 2508 awi_sync_done(sc); 2509 break; 2510 default: 2511 break; 2512 } 2513 } 2514 2515 static int 2516 awi_next_txd(sc, len, framep, ntxdp) 2517 struct awi_softc *sc; 2518 int len; 2519 u_int32_t *framep, *ntxdp; 2520 { 2521 u_int32_t txd, ntxd, frame; 2522 2523 txd = sc->sc_txnext; 2524 frame = txd + AWI_TXD_SIZE; 2525 if (frame + len > sc->sc_txend) 2526 frame = sc->sc_txbase; 2527 ntxd = frame + len; 2528 if (ntxd + AWI_TXD_SIZE > sc->sc_txend) 2529 ntxd = sc->sc_txbase; 2530 *framep = frame; 2531 *ntxdp = ntxd; 2532 /* 2533 * Determine if there are any room in ring buffer. 2534 * --- send wait, === new data, +++ conflict (ENOBUFS) 2535 * base........................end 2536 * done----txd=====ntxd OK 2537 * --txd=====done++++ntxd-- full 2538 * --txd=====ntxd done-- OK 2539 * ==ntxd done----txd=== OK 2540 * ==done++++ntxd----txd=== full 2541 * ++ntxd txd=====done++ full 2542 */ 2543 if (txd < ntxd) { 2544 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone) 2545 return ENOBUFS; 2546 } else { 2547 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone) 2548 return ENOBUFS; 2549 } 2550 return 0; 2551 } 2552 2553 static int 2554 awi_lock(sc) 2555 struct awi_softc *sc; 2556 { 2557 int error = 0; 2558 2559 if (curproc == NULL) { 2560 /* 2561 * XXX 2562 * Though driver ioctl should be called with context, 2563 * KAME ipv6 stack calls ioctl in interrupt for now. 2564 * We simply abort the request if there are other 2565 * ioctl requests in progress. 2566 */ 2567 if (sc->sc_busy) { 2568 return EWOULDBLOCK; 2569 if (sc->sc_invalid) 2570 return ENXIO; 2571 } 2572 sc->sc_busy = 1; 2573 sc->sc_cansleep = 0; 2574 return 0; 2575 } 2576 while (sc->sc_busy) { 2577 if (sc->sc_invalid) 2578 return ENXIO; 2579 sc->sc_sleep_cnt++; 2580 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0); 2581 sc->sc_sleep_cnt--; 2582 if (error) 2583 return error; 2584 } 2585 sc->sc_busy = 1; 2586 sc->sc_cansleep = 1; 2587 return 0; 2588 } 2589 2590 static void 2591 awi_unlock(sc) 2592 struct awi_softc *sc; 2593 { 2594 sc->sc_busy = 0; 2595 sc->sc_cansleep = 0; 2596 if (sc->sc_sleep_cnt) 2597 wakeup(sc); 2598 } 2599 2600 static int 2601 awi_intr_lock(sc) 2602 struct awi_softc *sc; 2603 { 2604 u_int8_t status; 2605 int i, retry; 2606 2607 status = 1; 2608 for (retry = 0; retry < 10; retry++) { 2609 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) { 2610 status = awi_read_1(sc, AWI_LOCKOUT_HOST); 2611 if (status == 0) 2612 break; 2613 DELAY(5); 2614 } 2615 if (status != 0) 2616 break; 2617 awi_write_1(sc, AWI_LOCKOUT_MAC, 1); 2618 status = awi_read_1(sc, AWI_LOCKOUT_HOST); 2619 if (status == 0) 2620 break; 2621 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 2622 } 2623 if (status != 0) { 2624 printf("%s: failed to lock interrupt\n", 2625 sc->sc_dev.dv_xname); 2626 return ENXIO; 2627 } 2628 return 0; 2629 } 2630 2631 static void 2632 awi_intr_unlock(sc) 2633 struct awi_softc *sc; 2634 { 2635 2636 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 2637 } 2638 2639 static int 2640 awi_cmd_wait(sc) 2641 struct awi_softc *sc; 2642 { 2643 int i, error = 0; 2644 2645 i = 0; 2646 while (sc->sc_cmd_inprog) { 2647 if (sc->sc_invalid) 2648 return ENXIO; 2649 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) { 2650 printf("%s: failed to access hardware\n", 2651 sc->sc_dev.dv_xname); 2652 sc->sc_invalid = 1; 2653 return ENXIO; 2654 } 2655 if (sc->sc_cansleep) { 2656 sc->sc_sleep_cnt++; 2657 error = tsleep(sc, PWAIT, "awicmd", 2658 AWI_CMD_TIMEOUT*hz/1000); 2659 sc->sc_sleep_cnt--; 2660 } else { 2661 if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) { 2662 awi_cmd_done(sc); 2663 break; 2664 } 2665 if (i++ >= AWI_CMD_TIMEOUT*1000/10) 2666 error = EWOULDBLOCK; 2667 else 2668 DELAY(10); 2669 } 2670 if (error) 2671 break; 2672 } 2673 return error; 2674 } 2675 2676 static void 2677 awi_print_essid(essid) 2678 u_int8_t *essid; 2679 { 2680 int i, len; 2681 u_int8_t *p; 2682 2683 len = essid[1]; 2684 if (len > IEEE80211_NWID_LEN) 2685 len = IEEE80211_NWID_LEN; /*XXX*/ 2686 /* determine printable or not */ 2687 for (i = 0, p = essid + 2; i < len; i++, p++) { 2688 if (*p < ' ' || *p > 0x7e) 2689 break; 2690 } 2691 if (i == len) { 2692 printf("\""); 2693 for (i = 0, p = essid + 2; i < len; i++, p++) 2694 printf("%c", *p); 2695 printf("\""); 2696 } else { 2697 printf("0x"); 2698 for (i = 0, p = essid + 2; i < len; i++, p++) 2699 printf("%02x", *p); 2700 } 2701 } 2702 2703 #ifdef AWI_DEBUG 2704 static void 2705 awi_dump_pkt(sc, m, rssi) 2706 struct awi_softc *sc; 2707 struct mbuf *m; 2708 int rssi; 2709 { 2710 struct ieee80211_frame *wh; 2711 int i, l; 2712 2713 wh = mtod(m, struct ieee80211_frame *); 2714 2715 if (awi_dump_mask != 0 && 2716 ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK)==IEEE80211_FC1_DIR_NODS) && 2717 ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_MGT)) { 2718 if ((AWI_DUMP_MASK(wh->i_fc[0]) & awi_dump_mask) != 0) 2719 return; 2720 } 2721 if (awi_dump_mask < 0 && 2722 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)==IEEE80211_FC0_TYPE_DATA) 2723 return; 2724 2725 if (rssi < 0) 2726 printf("tx: "); 2727 else 2728 printf("rx: "); 2729 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 2730 case IEEE80211_FC1_DIR_NODS: 2731 printf("NODS %s", ether_sprintf(wh->i_addr2)); 2732 printf("->%s", ether_sprintf(wh->i_addr1)); 2733 printf("(%s)", ether_sprintf(wh->i_addr3)); 2734 break; 2735 case IEEE80211_FC1_DIR_TODS: 2736 printf("TODS %s", ether_sprintf(wh->i_addr2)); 2737 printf("->%s", ether_sprintf(wh->i_addr3)); 2738 printf("(%s)", ether_sprintf(wh->i_addr1)); 2739 break; 2740 case IEEE80211_FC1_DIR_FROMDS: 2741 printf("FRDS %s", ether_sprintf(wh->i_addr3)); 2742 printf("->%s", ether_sprintf(wh->i_addr1)); 2743 printf("(%s)", ether_sprintf(wh->i_addr2)); 2744 break; 2745 case IEEE80211_FC1_DIR_DSTODS: 2746 printf("DSDS %s", ether_sprintf((u_int8_t *)&wh[1])); 2747 printf("->%s", ether_sprintf(wh->i_addr3)); 2748 printf("(%s", ether_sprintf(wh->i_addr2)); 2749 printf("->%s)", ether_sprintf(wh->i_addr1)); 2750 break; 2751 } 2752 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 2753 case IEEE80211_FC0_TYPE_DATA: 2754 printf(" data"); 2755 break; 2756 case IEEE80211_FC0_TYPE_MGT: 2757 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 2758 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 2759 printf(" probe_req"); 2760 break; 2761 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 2762 printf(" probe_resp"); 2763 break; 2764 case IEEE80211_FC0_SUBTYPE_BEACON: 2765 printf(" beacon"); 2766 break; 2767 case IEEE80211_FC0_SUBTYPE_AUTH: 2768 printf(" auth"); 2769 break; 2770 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 2771 printf(" assoc_req"); 2772 break; 2773 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 2774 printf(" assoc_resp"); 2775 break; 2776 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: 2777 printf(" reassoc_req"); 2778 break; 2779 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 2780 printf(" reassoc_resp"); 2781 break; 2782 case IEEE80211_FC0_SUBTYPE_DEAUTH: 2783 printf(" deauth"); 2784 break; 2785 case IEEE80211_FC0_SUBTYPE_DISASSOC: 2786 printf(" disassoc"); 2787 break; 2788 default: 2789 printf(" mgt#%d", 2790 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 2791 break; 2792 } 2793 break; 2794 default: 2795 printf(" type#%d", 2796 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 2797 break; 2798 } 2799 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 2800 printf(" WEP"); 2801 if (rssi >= 0) 2802 printf(" +%d", rssi); 2803 printf("\n"); 2804 if (awi_dump_len > 0) { 2805 l = m->m_len; 2806 if (l > awi_dump_len + sizeof(*wh)) 2807 l = awi_dump_len + sizeof(*wh); 2808 i = sizeof(*wh); 2809 if (awi_dump_hdr) 2810 i = 0; 2811 for (; i < l; i++) { 2812 if ((i & 1) == 0) 2813 printf(" "); 2814 printf("%02x", mtod(m, u_int8_t *)[i]); 2815 } 2816 printf("\n"); 2817 } 2818 } 2819 #endif 2820