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