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