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