1 /* $NetBSD: awi.c,v 1.41 2001/11/13 13:14:35 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1999,2000,2001 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 <sys/cdefs.h> 88 __KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.41 2001/11/13 13:14:35 lukem Exp $"); 89 90 #include "opt_inet.h" 91 #include "bpfilter.h" 92 93 #include <sys/param.h> 94 #include <sys/systm.h> 95 #include <sys/kernel.h> 96 #include <sys/mbuf.h> 97 #include <sys/malloc.h> 98 #include <sys/proc.h> 99 #include <sys/socket.h> 100 #include <sys/sockio.h> 101 #include <sys/errno.h> 102 #include <sys/device.h> 103 104 #include <net/if.h> 105 #include <net/if_dl.h> 106 #include <net/if_ether.h> 107 #include <net/if_media.h> 108 #include <net/if_llc.h> 109 #include <net/if_ieee80211.h> 110 111 #ifdef INET 112 #include <netinet/in.h> 113 #include <netinet/in_systm.h> 114 #ifdef __NetBSD__ 115 #include <netinet/if_inarp.h> 116 #else 117 #include <netinet/if_ether.h> 118 #endif 119 #endif 120 121 #if NBPFILTER > 0 122 #include <net/bpf.h> 123 #endif 124 125 #include <machine/cpu.h> 126 #include <machine/bus.h> 127 #include <machine/intr.h> 128 129 #include <dev/ic/am79c930reg.h> 130 #include <dev/ic/am79c930var.h> 131 #include <dev/ic/awireg.h> 132 #include <dev/ic/awivar.h> 133 134 static int awi_init(struct ifnet *); 135 static void awi_stop(struct ifnet *, int); 136 static void awi_start(struct ifnet *); 137 static void awi_watchdog(struct ifnet *); 138 static int awi_ioctl(struct ifnet *, u_long, caddr_t); 139 static int awi_media_change(struct ifnet *); 140 static void awi_media_status(struct ifnet *, struct ifmediareq *); 141 static int awi_mode_init(struct awi_softc *); 142 static int awi_media_rate2opt(struct awi_softc *, int); 143 static int awi_media_opt2rate(struct awi_softc *, int); 144 static void awi_rx_int(struct awi_softc *); 145 static void awi_tx_int(struct awi_softc *); 146 static struct mbuf *awi_devget(struct awi_softc *, u_int32_t, u_int16_t); 147 static int awi_hw_init(struct awi_softc *); 148 static int awi_init_mibs(struct awi_softc *); 149 static int awi_chan_check(void *, u_char *); 150 static int awi_mib(struct awi_softc *, u_int8_t, u_int8_t, int); 151 static int awi_cmd(struct awi_softc *, u_int8_t, int); 152 static int awi_cmd_wait(struct awi_softc *); 153 static void awi_cmd_done(struct awi_softc *); 154 static int awi_next_txd(struct awi_softc *, int, u_int32_t *, u_int32_t *); 155 static int awi_lock(struct awi_softc *); 156 static void awi_unlock(struct awi_softc *); 157 static int awi_intr_lock(struct awi_softc *); 158 static void awi_intr_unlock(struct awi_softc *); 159 static int awi_newstate(void *, enum ieee80211_state); 160 static struct mbuf *awi_ether_encap(struct awi_softc *, struct mbuf *); 161 static struct mbuf *awi_ether_modcap(struct awi_softc *, struct mbuf *); 162 163 /* unalligned little endian access */ 164 #define LE_READ_2(p) \ 165 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8)) 166 #define LE_READ_4(p) \ 167 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ 168 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)) 169 #define LE_WRITE_2(p, v) \ 170 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \ 171 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff))) 172 #define LE_WRITE_4(p, v) \ 173 ((((u_int8_t *)(p))[0] = (((u_int32_t)(v) ) & 0xff)), \ 174 (((u_int8_t *)(p))[1] = (((u_int32_t)(v) >> 8) & 0xff)), \ 175 (((u_int8_t *)(p))[2] = (((u_int32_t)(v) >> 16) & 0xff)), \ 176 (((u_int8_t *)(p))[3] = (((u_int32_t)(v) >> 24) & 0xff))) 177 178 struct awi_chanset awi_chanset[] = { 179 /* PHY type domain min max def */ 180 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_JP, 6, 17, 6 }, 181 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_ES, 0, 26, 1 }, 182 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_FR, 0, 32, 1 }, 183 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_US, 0, 77, 1 }, 184 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_CA, 0, 77, 1 }, 185 { AWI_PHY_TYPE_FH, AWI_REG_DOMAIN_EU, 0, 77, 1 }, 186 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_JP, 14, 14, 14 }, 187 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_ES, 10, 11, 10 }, 188 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_FR, 10, 13, 10 }, 189 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_US, 1, 11, 3 }, 190 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_CA, 1, 11, 3 }, 191 { AWI_PHY_TYPE_DS, AWI_REG_DOMAIN_EU, 1, 13, 3 }, 192 { 0, 0 } 193 }; 194 195 #ifdef AWI_DEBUG 196 int awi_debug; 197 198 #define DPRINTF(X) if (awi_debug) printf X 199 #define DPRINTF2(X) if (awi_debug > 1) printf X 200 #else 201 #define DPRINTF(X) 202 #define DPRINTF2(X) 203 #endif 204 205 int 206 awi_attach(struct awi_softc *sc) 207 { 208 struct ieee80211com *ic = &sc->sc_ic; 209 struct ifnet *ifp = &ic->ic_if; 210 int s, i, error, nrate; 211 int mword; 212 struct ifmediareq imr; 213 214 s = splnet(); 215 sc->sc_busy = 1; 216 ic->ic_state = IEEE80211_S_INIT; 217 sc->sc_substate = AWI_ST_NONE; 218 if ((error = awi_hw_init(sc)) != 0) { 219 sc->sc_invalid = 1; 220 splx(s); 221 return error; 222 } 223 error = awi_init_mibs(sc); 224 if (error != 0) { 225 sc->sc_invalid = 1; 226 splx(s); 227 return error; 228 } 229 ifp->if_softc = sc; 230 ifp->if_flags = 231 IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS; 232 ifp->if_ioctl = awi_ioctl; 233 ifp->if_start = awi_start; 234 ifp->if_init = awi_init; 235 ifp->if_stop = awi_stop; 236 ifp->if_watchdog = awi_watchdog; 237 IFQ_SET_READY(&ifp->if_snd); 238 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 239 240 ic->ic_flags = IEEE80211_F_HASWEP | IEEE80211_F_HASIBSS; 241 ic->ic_newstate = awi_newstate; 242 ic->ic_chancheck = awi_chan_check; 243 nrate = sc->sc_mib_phy.aSuprt_Data_Rates[1]; 244 memcpy(ic->ic_sup_rates, sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate); 245 memcpy(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address, IEEE80211_ADDR_LEN); 246 247 printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n", 248 sc->sc_dev.dv_xname, 249 sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH ? "FH" : "DS", 250 (ic->ic_sup_rates[nrate - 1] & IEEE80211_RATE_VAL) / 2, 251 sc->sc_banner); 252 printf("%s: 802.11 address: %s\n", sc->sc_dev.dv_xname, 253 ether_sprintf(ic->ic_myaddr)); 254 255 if_attach(ifp); 256 ieee80211_ifattach(ifp); 257 258 ifmedia_init(&sc->sc_media, 0, awi_media_change, awi_media_status); 259 mword = IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0); 260 ifmedia_add(&sc->sc_media, mword, 0, NULL); 261 ifmedia_add(&sc->sc_media, mword | IFM_FLAG0, 0, NULL); 262 mword |= IFM_IEEE80211_ADHOC; 263 ifmedia_add(&sc->sc_media, mword, 0, NULL); 264 ifmedia_add(&sc->sc_media, mword | IFM_FLAG0, 0, NULL); 265 for (i = 0; i < nrate; i++) { 266 mword = awi_media_rate2opt(sc, ic->ic_sup_rates[i]); 267 if (mword == 0) 268 continue; 269 mword |= IFM_IEEE80211; 270 ifmedia_add(&sc->sc_media, mword, 0, NULL); 271 ifmedia_add(&sc->sc_media, mword | IFM_FLAG0, 0, NULL); 272 mword |= IFM_IEEE80211_ADHOC; 273 ifmedia_add(&sc->sc_media, mword, 0, NULL); 274 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH) 275 ifmedia_add(&sc->sc_media, mword | IFM_FLAG0, 0, NULL); 276 } 277 awi_media_status(ifp, &imr); 278 ifmedia_set(&sc->sc_media, imr.ifm_active); 279 280 if ((sc->sc_sdhook = shutdownhook_establish(awi_shutdown, sc)) == NULL) 281 printf("%s: WARNING: unable to establish shutdown hook\n", 282 sc->sc_dev.dv_xname); 283 if ((sc->sc_powerhook = powerhook_establish(awi_power, sc)) == NULL) 284 printf("%s: WARNING: unable to establish power hook\n", 285 sc->sc_dev.dv_xname); 286 sc->sc_attached = 1; 287 splx(s); 288 289 /* ready to accept ioctl */ 290 awi_unlock(sc); 291 292 return 0; 293 } 294 295 int 296 awi_detach(struct awi_softc *sc) 297 { 298 struct ifnet *ifp = &sc->sc_ic.ic_if; 299 int s; 300 301 if (!sc->sc_attached) 302 return 0; 303 304 s = splnet(); 305 sc->sc_invalid = 1; 306 awi_stop(ifp, 1); 307 while (sc->sc_sleep_cnt > 0) { 308 wakeup(sc); 309 (void)tsleep(sc, PWAIT, "awidet", 1); 310 } 311 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 312 ieee80211_ifdetach(ifp); 313 if_detach(ifp); 314 shutdownhook_disestablish(sc->sc_sdhook); 315 powerhook_disestablish(sc->sc_powerhook); 316 splx(s); 317 return 0; 318 } 319 320 int 321 awi_activate(struct device *self, enum devact act) 322 { 323 struct awi_softc *sc = (struct awi_softc *)self; 324 struct ifnet *ifp = &sc->sc_ic.ic_if; 325 int s, error = 0; 326 327 s = splnet(); 328 switch (act) { 329 case DVACT_ACTIVATE: 330 error = EOPNOTSUPP; 331 break; 332 case DVACT_DEACTIVATE: 333 sc->sc_invalid = 1; 334 if_deactivate(ifp); 335 break; 336 } 337 splx(s); 338 return error; 339 } 340 341 void 342 awi_power(int why, void *arg) 343 { 344 struct awi_softc *sc = arg; 345 struct ifnet *ifp = &sc->sc_ic.ic_if; 346 int s; 347 int ocansleep; 348 349 DPRINTF(("awi_power: %d\n", why)); 350 s = splnet(); 351 ocansleep = sc->sc_cansleep; 352 sc->sc_cansleep = 0; 353 switch (why) { 354 case PWR_SUSPEND: 355 case PWR_STANDBY: 356 awi_stop(ifp, 1); 357 break; 358 case PWR_RESUME: 359 if (ifp->if_flags & IFF_UP) { 360 awi_init(ifp); 361 (void)awi_intr(sc); /* make sure */ 362 } 363 break; 364 case PWR_SOFTSUSPEND: 365 case PWR_SOFTSTANDBY: 366 case PWR_SOFTRESUME: 367 break; 368 } 369 sc->sc_cansleep = ocansleep; 370 splx(s); 371 } 372 373 void 374 awi_shutdown(void *arg) 375 { 376 struct awi_softc *sc = arg; 377 struct ifnet *ifp = &sc->sc_ic.ic_if; 378 379 if (sc->sc_attached) 380 awi_stop(ifp, 1); 381 } 382 383 int 384 awi_intr(void *arg) 385 { 386 struct awi_softc *sc = arg; 387 u_int16_t status; 388 int error, handled = 0, ocansleep; 389 #ifdef AWI_DEBUG 390 static const char *intname[] = { 391 "CMD", "RX", "TX", "SCAN_CMPLT", 392 "CFP_START", "DTIM", "CFP_ENDING", "GROGGY", 393 "TXDATA", "TXBCAST", "TXPS", "TXCF", 394 "TXMGT", "#13", "RXDATA", "RXMGT" 395 }; 396 #endif 397 398 if (!sc->sc_enabled || !sc->sc_enab_intr || sc->sc_invalid) 399 return 0; 400 401 am79c930_gcr_setbits(&sc->sc_chip, 402 AM79C930_GCR_DISPWDN | AM79C930_GCR_ECINT); 403 awi_write_1(sc, AWI_DIS_PWRDN, 1); 404 ocansleep = sc->sc_cansleep; 405 sc->sc_cansleep = 0; 406 407 for (;;) { 408 if ((error = awi_intr_lock(sc)) != 0) 409 break; 410 status = awi_read_1(sc, AWI_INTSTAT); 411 awi_write_1(sc, AWI_INTSTAT, 0); 412 awi_write_1(sc, AWI_INTSTAT, 0); 413 status |= awi_read_1(sc, AWI_INTSTAT2) << 8; 414 awi_write_1(sc, AWI_INTSTAT2, 0); 415 DELAY(10); 416 awi_intr_unlock(sc); 417 if (!sc->sc_cmd_inprog) 418 status &= ~AWI_INT_CMD; /* make sure */ 419 if (status == 0) 420 break; 421 #ifdef AWI_DEBUG 422 if (awi_debug > 1) { 423 int i; 424 425 printf("awi_intr: status 0x%04x", status); 426 for (i = 0; i < sizeof(intname)/sizeof(intname[0]); 427 i++) { 428 if (status & (1 << i)) 429 printf(" %s", intname[i]); 430 } 431 printf("\n"); 432 } 433 #endif 434 handled = 1; 435 if (status & AWI_INT_RX) 436 awi_rx_int(sc); 437 if (status & AWI_INT_TX) 438 awi_tx_int(sc); 439 if (status & AWI_INT_CMD) 440 awi_cmd_done(sc); 441 if (status & AWI_INT_SCAN_CMPLT) { 442 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN) 443 ieee80211_next_scan(&sc->sc_ic.ic_if); 444 } 445 } 446 sc->sc_cansleep = ocansleep; 447 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_DISPWDN); 448 awi_write_1(sc, AWI_DIS_PWRDN, 0); 449 return handled; 450 } 451 452 static int 453 awi_init(struct ifnet *ifp) 454 { 455 struct awi_softc *sc = ifp->if_softc; 456 struct ieee80211com *ic = &sc->sc_ic; 457 struct ieee80211_bss *bs = &ic->ic_bss; 458 int i, error; 459 460 DPRINTF(("awi_init: enabled=%d\n", sc->sc_enabled)); 461 if (sc->sc_enabled) { 462 awi_stop(ifp, 0); 463 } else { 464 if (sc->sc_enable) 465 (*sc->sc_enable)(sc); 466 sc->sc_enabled = 1; 467 if ((error = awi_hw_init(sc)) != 0) { 468 awi_stop(ifp, 1); 469 return error; 470 } 471 } 472 ic->ic_state = IEEE80211_S_INIT; 473 474 sc->sc_mib_local.Network_Mode = 475 (ic->ic_flags & IEEE80211_F_ADHOC) ? 0 : 1; 476 477 if ((error = awi_mode_init(sc)) != 0) { 478 DPRINTF(("awi_init: awi_mode_init failed %d\n", error)); 479 awi_stop(ifp, 1); 480 return error; 481 } 482 483 /* start transmitter */ 484 sc->sc_txdone = sc->sc_txnext = sc->sc_txbase; 485 awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0); 486 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0); 487 awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0); 488 awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0); 489 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0); 490 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0); 491 awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0); 492 awi_write_4(sc, AWI_CA_TX_DATA, sc->sc_txbase); 493 awi_write_4(sc, AWI_CA_TX_MGT, 0); 494 awi_write_4(sc, AWI_CA_TX_BCAST, 0); 495 awi_write_4(sc, AWI_CA_TX_PS, 0); 496 awi_write_4(sc, AWI_CA_TX_CF, 0); 497 if ((error = awi_cmd(sc, AWI_CMD_INIT_TX, AWI_WAIT)) != 0) { 498 DPRINTF(("awi_init: failed to start transmitter: %d\n", error)); 499 awi_stop(ifp, 1); 500 return error; 501 } 502 503 /* start receiver */ 504 if ((error = awi_cmd(sc, AWI_CMD_INIT_RX, AWI_WAIT)) != 0) { 505 DPRINTF(("awi_init: failed to start receiver: %d\n", error)); 506 awi_stop(ifp, 1); 507 return error; 508 } 509 sc->sc_rxdoff = awi_read_4(sc, AWI_CA_IRX_DATA_DESC); 510 sc->sc_rxmoff = awi_read_4(sc, AWI_CA_IRX_PS_DESC); 511 512 ifp->if_flags |= IFF_RUNNING; 513 ifp->if_flags &= ~IFF_OACTIVE; 514 515 if ((sc->sc_ic.ic_flags & IEEE80211_F_ADHOC) && sc->sc_no_bssid) { 516 bs->bs_chan = ic->ic_ibss_chan; 517 bs->bs_intval = ic->ic_lintval; 518 bs->bs_nrate = 0; 519 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 520 if (ic->ic_sup_rates[i]) 521 bs->bs_rates[bs->bs_nrate++] = 522 ic->ic_sup_rates[i]; 523 } 524 memcpy(bs->bs_macaddr, ic->ic_myaddr, IEEE80211_ADDR_LEN); 525 memset(bs->bs_bssid, 0, IEEE80211_ADDR_LEN); 526 bs->bs_esslen = 0; 527 ic->ic_flags |= IEEE80211_F_SIBSS; 528 ic->ic_state = IEEE80211_S_SCAN; /*XXX*/ 529 sc->sc_substate = AWI_ST_NONE; 530 ieee80211_new_state(&ic->ic_if, IEEE80211_S_RUN, -1); 531 } else { 532 bs->bs_chan = sc->sc_cur_chan; 533 ieee80211_new_state(&ic->ic_if, IEEE80211_S_SCAN, -1); 534 } 535 return 0; 536 } 537 538 static void 539 awi_stop(struct ifnet *ifp, int disable) 540 { 541 struct awi_softc *sc = ifp->if_softc; 542 543 if (!sc->sc_enabled) 544 return; 545 546 DPRINTF(("awi_stop(%d)\n", disable)); 547 548 ieee80211_new_state(&sc->sc_ic.ic_if, IEEE80211_S_INIT, -1); 549 550 if (!sc->sc_invalid) { 551 if (sc->sc_cmd_inprog) 552 (void)awi_cmd_wait(sc); 553 (void)awi_cmd(sc, AWI_CMD_KILL_RX, AWI_WAIT); 554 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX; 555 awi_write_1(sc, AWI_CA_FTX_DATA, 1); 556 awi_write_1(sc, AWI_CA_FTX_MGT, 0); 557 awi_write_1(sc, AWI_CA_FTX_BCAST, 0); 558 awi_write_1(sc, AWI_CA_FTX_PS, 0); 559 awi_write_1(sc, AWI_CA_FTX_CF, 0); 560 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX, AWI_WAIT); 561 } 562 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 563 ifp->if_timer = 0; 564 sc->sc_tx_timer = sc->sc_rx_timer = 0; 565 if (sc->sc_rxpend != NULL) { 566 m_freem(sc->sc_rxpend); 567 sc->sc_rxpend = NULL; 568 } 569 IFQ_PURGE(&ifp->if_snd); 570 571 if (disable) { 572 if (sc->sc_disable) 573 (*sc->sc_disable)(sc); 574 sc->sc_enabled = 0; 575 } 576 } 577 578 static void 579 awi_start(struct ifnet *ifp) 580 { 581 struct awi_softc *sc = ifp->if_softc; 582 struct ieee80211com *ic = &sc->sc_ic; 583 struct mbuf *m, *m0; 584 int len; 585 u_int32_t txd, frame, ntxd; 586 u_int8_t rate; 587 588 if (!sc->sc_enabled || sc->sc_invalid) 589 return; 590 591 for (;;) { 592 txd = sc->sc_txnext; 593 IF_POLL(&ic->ic_mgtq, m0); 594 if (m0 != NULL) { 595 if (awi_next_txd(sc, m0->m_pkthdr.len, &frame, &ntxd)) { 596 ifp->if_flags |= IFF_OACTIVE; 597 break; 598 } 599 IF_DEQUEUE(&ic->ic_mgtq, m0); 600 } else { 601 if (ic->ic_state != IEEE80211_S_RUN) 602 break; 603 IFQ_POLL(&ifp->if_snd, m0); 604 if (m0 == NULL) 605 break; 606 /* 607 * Need to calculate the real length to determine 608 * if the transmit buffer has a room for the packet. 609 */ 610 len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame); 611 if (!(ifp->if_flags & IFF_LINK0) && !sc->sc_adhoc_ap) 612 len += sizeof(struct llc) - 613 sizeof(struct ether_header); 614 if (ic->ic_flags & IEEE80211_F_WEPON) 615 len += IEEE80211_WEP_IVLEN + 616 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; 617 if (awi_next_txd(sc, len, &frame, &ntxd)) { 618 ifp->if_flags |= IFF_OACTIVE; 619 break; 620 } 621 IFQ_DEQUEUE(&ifp->if_snd, m0); 622 ifp->if_opackets++; 623 #if NBPFILTER > 0 624 if (ifp->if_bpf) 625 bpf_mtap(ifp->if_bpf, m0); 626 #endif 627 if ((ifp->if_flags & IFF_LINK0) || sc->sc_adhoc_ap) 628 m0 = awi_ether_encap(sc, m0); 629 else 630 m0 = ieee80211_encap(ifp, m0); 631 if ((ic->ic_flags & IEEE80211_F_WEPON) && m0 != NULL) 632 m0 = ieee80211_wep_crypt(ifp, m0, 1); 633 if (m0 == NULL) { 634 ifp->if_oerrors++; 635 continue; 636 } 637 #ifdef DIAGNOSTIC 638 if (m0->m_pkthdr.len != len) { 639 printf("%s: length %d should be %d\n", 640 ifp->if_xname, m0->m_pkthdr.len, len); 641 m_freem(m0); 642 ifp->if_oerrors++; 643 continue; 644 } 645 #endif 646 } 647 648 if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2)) 649 ieee80211_dump_pkt(m0->m_data, m0->m_len, 650 ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & 651 IEEE80211_RATE_VAL, -1); 652 653 for (m = m0, len = 0; m != NULL; m = m->m_next) { 654 awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *), 655 m->m_len); 656 len += m->m_len; 657 } 658 m_freem(m0); 659 rate = (ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & 660 IEEE80211_RATE_VAL) * 5; 661 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0); 662 awi_write_4(sc, txd + AWI_TXD_START, frame); 663 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd); 664 awi_write_4(sc, txd + AWI_TXD_LENGTH, len); 665 awi_write_1(sc, txd + AWI_TXD_RATE, rate); 666 awi_write_4(sc, txd + AWI_TXD_NDA, 0); 667 awi_write_4(sc, txd + AWI_TXD_NRA, 0); 668 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN); 669 sc->sc_txnext = ntxd; 670 671 sc->sc_tx_timer = 5; 672 ifp->if_timer = 1; 673 } 674 } 675 676 static void 677 awi_watchdog(struct ifnet *ifp) 678 { 679 struct awi_softc *sc = ifp->if_softc; 680 u_int32_t prevdone; 681 int ocansleep; 682 683 ifp->if_timer = 0; 684 if (!sc->sc_enabled || sc->sc_invalid) 685 return; 686 687 ocansleep = sc->sc_cansleep; 688 sc->sc_cansleep = 0; 689 if (sc->sc_tx_timer) { 690 if (--sc->sc_tx_timer == 0) { 691 printf("%s: device timeout\n", ifp->if_xname); 692 prevdone = sc->sc_txdone; 693 awi_tx_int(sc); 694 if (sc->sc_txdone == prevdone) { 695 ifp->if_oerrors++; 696 awi_init(ifp); 697 goto out; 698 } 699 } 700 ifp->if_timer = 1; 701 } 702 if (sc->sc_rx_timer) { 703 if (--sc->sc_rx_timer == 0) { 704 if (sc->sc_ic.ic_state == IEEE80211_S_RUN) { 705 ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1); 706 goto out; 707 } 708 } else 709 ifp->if_timer = 1; 710 } 711 /* TODO: rate control */ 712 ieee80211_watchdog(ifp); 713 out: 714 sc->sc_cansleep = ocansleep; 715 } 716 717 static int 718 awi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 719 { 720 struct awi_softc *sc = ifp->if_softc; 721 struct ifreq *ifr = (struct ifreq *)data; 722 int s, error; 723 724 s = splnet(); 725 /* serialize ioctl, since we may sleep */ 726 if ((error = awi_lock(sc)) != 0) 727 goto cantlock; 728 729 switch (cmd) { 730 case SIOCSIFFLAGS: 731 if (ifp->if_flags & IFF_UP) { 732 if (sc->sc_enabled) { 733 /* 734 * To avoid rescanning another access point, 735 * do not call awi_init() here. Instead, 736 * only reflect promisc mode settings. 737 */ 738 error = awi_mode_init(sc); 739 } else 740 error = awi_init(ifp); 741 } else if (sc->sc_enabled) 742 awi_stop(ifp, 1); 743 break; 744 case SIOCSIFMEDIA: 745 case SIOCGIFMEDIA: 746 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 747 break; 748 case SIOCADDMULTI: 749 case SIOCDELMULTI: 750 error = (cmd == SIOCADDMULTI) ? 751 ether_addmulti(ifr, &sc->sc_ic.ic_ec) : 752 ether_delmulti(ifr, &sc->sc_ic.ic_ec); 753 if (error == ENETRESET) { 754 /* do not rescan */ 755 if (sc->sc_enabled) 756 error = awi_mode_init(sc); 757 else 758 error = 0; 759 } 760 break; 761 default: 762 error = ieee80211_ioctl(ifp, cmd, data); 763 if (error == ENETRESET) { 764 if (sc->sc_enabled) 765 error = awi_init(ifp); 766 else 767 error = 0; 768 } 769 break; 770 } 771 awi_unlock(sc); 772 cantlock: 773 splx(s); 774 return error; 775 } 776 777 /* 778 * Called from ifmedia_ioctl via awi_ioctl with lock obtained. 779 */ 780 static int 781 awi_media_change(struct ifnet *ifp) 782 { 783 struct awi_softc *sc = ifp->if_softc; 784 struct ieee80211com *ic = &sc->sc_ic; 785 struct ifmedia_entry *ime; 786 int i, rate, error = 0; 787 788 ime = sc->sc_media.ifm_cur; 789 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { 790 ic->ic_fixed_rate = -1; 791 } else { 792 rate = awi_media_opt2rate(sc, ime->ifm_media); 793 if (rate == 0) 794 return EINVAL; 795 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 796 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate) 797 break; 798 } 799 if (i == IEEE80211_RATE_SIZE) 800 return EINVAL; 801 ic->ic_fixed_rate = i; 802 } 803 804 /* 805 * ADHOC,-FLAG0 ADHOC, !no_bssid, !adhoc_ap IBSS 806 * ADHOC, FLAG0 ADHOC no_bssid, !adhoc_ap WaveLAN adhoc 807 * -ADHOC,-FLAG0 ~ADHOC, !no_bssid, !adhoc_ap Infra 808 * -ADHOC, FLAG0 ADHOC, !no_bssid, adhoc_ap Melco old AP 809 * also LINK0 810 */ 811 if (ime->ifm_media & IFM_IEEE80211_ADHOC) { 812 if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) { 813 ic->ic_flags |= IEEE80211_F_ADHOC; 814 error = ENETRESET; 815 } 816 ic->ic_flags |= IEEE80211_F_IBSSON; 817 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH && 818 (ime->ifm_media & IFM_FLAG0)) { 819 if (sc->sc_no_bssid == 0) { 820 sc->sc_no_bssid = 1; 821 error = ENETRESET; 822 } 823 } else { 824 if (sc->sc_no_bssid) { 825 sc->sc_no_bssid = 0; 826 error = ENETRESET; 827 } 828 } 829 if (sc->sc_adhoc_ap) { 830 sc->sc_adhoc_ap = 0; 831 error = ENETRESET; 832 } 833 } else { 834 ic->ic_flags &= ~IEEE80211_F_IBSSON; 835 if (sc->sc_no_bssid) { 836 sc->sc_no_bssid = 0; 837 error = ENETRESET; 838 } 839 if (ime->ifm_media & IFM_FLAG0) { 840 if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) { 841 ic->ic_flags |= IEEE80211_F_ADHOC; 842 error = ENETRESET; 843 } 844 if (!sc->sc_adhoc_ap) { 845 sc->sc_adhoc_ap = 1; 846 error = ENETRESET; 847 } 848 } else { 849 if (ic->ic_flags & IEEE80211_F_ADHOC) { 850 ic->ic_flags &= ~IEEE80211_F_ADHOC; 851 error = ENETRESET; 852 } 853 if (sc->sc_adhoc_ap) { 854 sc->sc_adhoc_ap = 0; 855 error = ENETRESET; 856 } 857 } 858 } 859 if (error == ENETRESET) { 860 if (sc->sc_enabled) 861 error = awi_init(ifp); 862 else 863 error = 0; 864 } 865 return error; 866 } 867 868 static void 869 awi_media_status(struct ifnet *ifp, struct ifmediareq *imr) 870 { 871 struct awi_softc *sc = ifp->if_softc; 872 struct ieee80211com *ic = &sc->sc_ic; 873 int rate; 874 875 imr->ifm_status = IFM_AVALID; 876 if (ic->ic_state == IEEE80211_S_RUN) 877 imr->ifm_status |= IFM_ACTIVE; 878 imr->ifm_active = IFM_IEEE80211; 879 if (ic->ic_state == IEEE80211_S_RUN) 880 rate = ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & 881 IEEE80211_RATE_VAL; 882 else { 883 if (ic->ic_fixed_rate == -1) 884 rate = 0; 885 else 886 rate = ic->ic_sup_rates[ic->ic_fixed_rate] & 887 IEEE80211_RATE_VAL; 888 } 889 imr->ifm_active |= awi_media_rate2opt(sc, rate); 890 if (ic->ic_flags & IEEE80211_F_ADHOC) { 891 if (sc->sc_adhoc_ap) 892 imr->ifm_active |= IFM_FLAG0; 893 else { 894 imr->ifm_active |= IFM_IEEE80211_ADHOC; 895 if (sc->sc_no_bssid) 896 imr->ifm_active |= IFM_FLAG0; 897 } 898 } 899 } 900 901 static int 902 awi_mode_init(struct awi_softc *sc) 903 { 904 struct ifnet *ifp = &sc->sc_ic.ic_if; 905 int n, error; 906 struct ether_multi *enm; 907 struct ether_multistep step; 908 909 /* reinitialize muticast filter */ 910 n = 0; 911 sc->sc_mib_local.Accept_All_Multicast_Dis = 0; 912 if (ifp->if_flags & IFF_PROMISC) { 913 sc->sc_mib_mac.aPromiscuous_Enable = 1; 914 goto set_mib; 915 } 916 sc->sc_mib_mac.aPromiscuous_Enable = 0; 917 ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm); 918 while (enm != NULL) { 919 if (n == AWI_GROUP_ADDR_SIZE || 920 memcmp(enm->enm_addrlo, enm->enm_addrhi, IEEE80211_ADDR_LEN) 921 != 0) 922 goto set_mib; 923 memcpy(sc->sc_mib_addr.aGroup_Addresses[n], enm->enm_addrlo, 924 IEEE80211_ADDR_LEN); 925 n++; 926 ETHER_NEXT_MULTI(step, enm); 927 } 928 for (; n < AWI_GROUP_ADDR_SIZE; n++) 929 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0, IEEE80211_ADDR_LEN); 930 sc->sc_mib_local.Accept_All_Multicast_Dis = 1; 931 932 set_mib: 933 if (sc->sc_mib_local.Accept_All_Multicast_Dis) 934 ifp->if_flags &= ~IFF_ALLMULTI; 935 else 936 ifp->if_flags |= IFF_ALLMULTI; 937 sc->sc_mib_mgt.Wep_Required = 938 (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) ? 1 : 0; 939 940 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) || 941 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR, AWI_WAIT)) || 942 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC, AWI_WAIT)) || 943 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_WAIT)) || 944 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY, AWI_WAIT))) { 945 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error)); 946 return error; 947 } 948 return 0; 949 } 950 951 /* XXX should be moved to if_ieee80211subr.c ? */ 952 static int 953 awi_media_rate2opt(struct awi_softc *sc, int rate) 954 { 955 int mword; 956 957 mword = 0; 958 switch (rate & IEEE80211_RATE_VAL) { 959 case 2: 960 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 961 mword = IFM_IEEE80211_FH1; 962 else 963 mword = IFM_IEEE80211_DS1; 964 break; 965 case 4: 966 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) 967 mword = IFM_IEEE80211_FH2; 968 else 969 mword = IFM_IEEE80211_DS2; 970 break; 971 case 11: 972 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_DS) 973 mword = IFM_IEEE80211_DS5; 974 break; 975 case 22: 976 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_DS) 977 mword = IFM_IEEE80211_DS11; 978 break; 979 } 980 return mword; 981 } 982 983 static int 984 awi_media_opt2rate(struct awi_softc *sc, int opt) 985 { 986 int rate; 987 988 rate = 0; 989 switch (IFM_SUBTYPE(opt)) { 990 case IFM_IEEE80211_FH1: 991 case IFM_IEEE80211_FH2: 992 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH) 993 return 0; 994 break; 995 case IFM_IEEE80211_DS1: 996 case IFM_IEEE80211_DS2: 997 case IFM_IEEE80211_DS5: 998 case IFM_IEEE80211_DS11: 999 if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_DS) 1000 return 0; 1001 break; 1002 } 1003 1004 switch (IFM_SUBTYPE(opt)) { 1005 case IFM_IEEE80211_FH1: 1006 case IFM_IEEE80211_DS1: 1007 rate = 2; 1008 break; 1009 case IFM_IEEE80211_FH2: 1010 case IFM_IEEE80211_DS2: 1011 rate = 4; 1012 break; 1013 case IFM_IEEE80211_DS5: 1014 rate = 11; 1015 break; 1016 case IFM_IEEE80211_DS11: 1017 rate = 22; 1018 break; 1019 } 1020 return rate; 1021 } 1022 1023 static void 1024 awi_rx_int(struct awi_softc *sc) 1025 { 1026 struct ifnet *ifp = &sc->sc_ic.ic_if; 1027 u_int8_t state, rate, rssi; 1028 u_int16_t len; 1029 u_int32_t frame, next, timoff, rxoff; 1030 struct mbuf *m; 1031 1032 rxoff = sc->sc_rxdoff; 1033 for (;;) { 1034 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE); 1035 if (state & AWI_RXD_ST_OWN) 1036 break; 1037 if (!(state & AWI_RXD_ST_CONSUMED)) { 1038 if (state & AWI_RXD_ST_RXERROR) { 1039 ifp->if_ierrors++; 1040 goto rx_next; 1041 } 1042 len = awi_read_2(sc, rxoff + AWI_RXD_LEN); 1043 rate = awi_read_1(sc, rxoff + AWI_RXD_RATE); 1044 rssi = awi_read_1(sc, rxoff + AWI_RXD_RSSI); 1045 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) & 1046 0x7fff; 1047 timoff = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME); 1048 m = awi_devget(sc, frame, len); 1049 if (m == NULL) { 1050 ifp->if_ierrors++; 1051 goto rx_next; 1052 } 1053 if (state & AWI_RXD_ST_LF) { 1054 /* TODO check my bss */ 1055 if (!(sc->sc_ic.ic_flags & IEEE80211_F_SIBSS) && 1056 sc->sc_ic.ic_state == IEEE80211_S_RUN) { 1057 sc->sc_rx_timer = 10; 1058 ifp->if_timer = 1; 1059 } 1060 if ((ifp->if_flags & IFF_DEBUG) && 1061 (ifp->if_flags & IFF_LINK2)) 1062 ieee80211_dump_pkt(m->m_data, m->m_len, 1063 rate / 5, rssi); 1064 if ((ifp->if_flags & IFF_LINK0) || 1065 sc->sc_adhoc_ap) 1066 m = awi_ether_modcap(sc, m); 1067 if (m == NULL) 1068 ifp->if_ierrors++; 1069 else 1070 ieee80211_input(ifp, m, rssi, timoff); 1071 } else 1072 sc->sc_rxpend = m; 1073 rx_next: 1074 state |= AWI_RXD_ST_CONSUMED; 1075 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1076 } 1077 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT); 1078 if (next & AWI_RXD_NEXT_LAST) 1079 break; 1080 /* make sure the next pointer is correct */ 1081 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT)) 1082 break; 1083 state |= AWI_RXD_ST_OWN; 1084 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1085 rxoff = next & 0x7fff; 1086 } 1087 sc->sc_rxdoff = rxoff; 1088 } 1089 1090 static void 1091 awi_tx_int(struct awi_softc *sc) 1092 { 1093 struct ifnet *ifp = &sc->sc_ic.ic_if; 1094 u_int8_t flags; 1095 1096 while (sc->sc_txdone != sc->sc_txnext) { 1097 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE); 1098 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE)) 1099 break; 1100 if (flags & AWI_TXD_ST_ERROR) 1101 ifp->if_oerrors++; 1102 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) & 1103 0x7fff; 1104 } 1105 DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n", 1106 sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend)); 1107 sc->sc_tx_timer = 0; 1108 ifp->if_flags &= ~IFF_OACTIVE; 1109 awi_start(ifp); 1110 } 1111 1112 static struct mbuf * 1113 awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len) 1114 { 1115 struct ifnet *ifp = &sc->sc_ic.ic_if; 1116 struct mbuf *m; 1117 struct mbuf *top, **mp; 1118 u_int tlen; 1119 1120 top = sc->sc_rxpend; 1121 mp = ⊤ 1122 if (top != NULL) { 1123 sc->sc_rxpend = NULL; 1124 top->m_pkthdr.len += len; 1125 m = top; 1126 while (*mp != NULL) { 1127 m = *mp; 1128 mp = &m->m_next; 1129 } 1130 if (m->m_flags & M_EXT) 1131 tlen = m->m_ext.ext_size; 1132 else if (m->m_flags & M_PKTHDR) 1133 tlen = MHLEN; 1134 else 1135 tlen = MLEN; 1136 tlen -= m->m_len; 1137 if (tlen > len) 1138 tlen = len; 1139 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen); 1140 off += tlen; 1141 len -= tlen; 1142 } 1143 1144 while (len > 0) { 1145 if (top == NULL) { 1146 MGETHDR(m, M_DONTWAIT, MT_DATA); 1147 if (m == NULL) 1148 return NULL; 1149 m->m_pkthdr.rcvif = ifp; 1150 m->m_pkthdr.len = len; 1151 m->m_len = MHLEN; 1152 m->m_flags |= M_HASFCS; 1153 } else { 1154 MGET(m, M_DONTWAIT, MT_DATA); 1155 if (m == NULL) { 1156 m_freem(top); 1157 return NULL; 1158 } 1159 m->m_len = MLEN; 1160 } 1161 if (len >= MINCLSIZE) { 1162 MCLGET(m, M_DONTWAIT); 1163 if (m->m_flags & M_EXT) 1164 m->m_len = m->m_ext.ext_size; 1165 } 1166 if (top == NULL) { 1167 int hdrlen = sizeof(struct ieee80211_frame) + 1168 sizeof(struct llc); 1169 caddr_t newdata = (caddr_t) 1170 ALIGN(m->m_data + hdrlen) - hdrlen; 1171 m->m_len -= newdata - m->m_data; 1172 m->m_data = newdata; 1173 } 1174 if (m->m_len > len) 1175 m->m_len = len; 1176 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len); 1177 off += m->m_len; 1178 len -= m->m_len; 1179 *mp = m; 1180 mp = &m->m_next; 1181 } 1182 return top; 1183 } 1184 1185 /* 1186 * Initialize hardware and start firmware to accept commands. 1187 * Called everytime after power on firmware. 1188 */ 1189 1190 static int 1191 awi_hw_init(struct awi_softc *sc) 1192 { 1193 u_int8_t status; 1194 u_int16_t intmask; 1195 int i, error; 1196 1197 sc->sc_enab_intr = 0; 1198 sc->sc_invalid = 0; /* XXX: really? */ 1199 awi_drvstate(sc, AWI_DRV_RESET); 1200 1201 /* reset firmware */ 1202 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1203 DELAY(100); 1204 awi_write_1(sc, AWI_SELFTEST, 0); 1205 awi_write_1(sc, AWI_CMD, 0); 1206 awi_write_1(sc, AWI_BANNER, 0); 1207 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1208 DELAY(100); 1209 1210 /* wait for selftest completion */ 1211 for (i = 0; ; i++) { 1212 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) { 1213 printf("%s: failed to complete selftest (timeout)\n", 1214 sc->sc_dev.dv_xname); 1215 return ENXIO; 1216 } 1217 status = awi_read_1(sc, AWI_SELFTEST); 1218 if ((status & 0xf0) == 0xf0) 1219 break; 1220 if (sc->sc_cansleep) { 1221 sc->sc_sleep_cnt++; 1222 (void)tsleep(sc, PWAIT, "awitst", 1); 1223 sc->sc_sleep_cnt--; 1224 } else { 1225 DELAY(1000*1000/hz); 1226 } 1227 } 1228 if (status != AWI_SELFTEST_PASSED) { 1229 printf("%s: failed to complete selftest (code %x)\n", 1230 sc->sc_dev.dv_xname, status); 1231 return ENXIO; 1232 } 1233 1234 /* check banner to confirm firmware write it */ 1235 awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN); 1236 if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) { 1237 printf("%s: failed to complete selftest (bad banner)\n", 1238 sc->sc_dev.dv_xname); 1239 for (i = 0; i < AWI_BANNER_LEN; i++) 1240 printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]); 1241 printf("\n"); 1242 return ENXIO; 1243 } 1244 1245 /* initializing interrupt */ 1246 sc->sc_enab_intr = 1; 1247 error = awi_intr_lock(sc); 1248 if (error) 1249 return error; 1250 intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT | 1251 AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD; 1252 awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff); 1253 awi_write_1(sc, AWI_INTMASK2, 0); 1254 awi_write_1(sc, AWI_INTSTAT, 0); 1255 awi_write_1(sc, AWI_INTSTAT2, 0); 1256 awi_intr_unlock(sc); 1257 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT); 1258 1259 /* issuing interface test command */ 1260 error = awi_cmd(sc, AWI_CMD_NOP, AWI_WAIT); 1261 if (error) { 1262 printf("%s: failed to complete selftest", sc->sc_dev.dv_xname); 1263 if (error == ENXIO) 1264 printf(" (no hardware)\n"); 1265 else if (error != EWOULDBLOCK) 1266 printf(" (error %d)\n", error); 1267 else if (sc->sc_cansleep) 1268 printf(" (lost interrupt)\n"); 1269 else 1270 printf(" (command timeout)\n"); 1271 } 1272 return error; 1273 } 1274 1275 /* 1276 * Extract the factory default MIB value from firmware and assign the driver 1277 * default value. 1278 * Called once at attaching the interface. 1279 */ 1280 1281 static int 1282 awi_init_mibs(struct awi_softc *sc) 1283 { 1284 int i, error; 1285 struct awi_chanset *cs; 1286 1287 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) || 1288 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR, AWI_WAIT)) || 1289 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC, AWI_WAIT)) || 1290 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) || 1291 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY, AWI_WAIT))) { 1292 printf("%s: failed to get default mib value (error %d)\n", 1293 sc->sc_dev.dv_xname, error); 1294 return error; 1295 } 1296 1297 memset(&sc->sc_ic.ic_chan_avail, 0, sizeof(sc->sc_ic.ic_chan_avail)); 1298 for (cs = awi_chanset; ; cs++) { 1299 if (cs->cs_type == 0) { 1300 printf("%s: failed to set available channel\n", 1301 sc->sc_dev.dv_xname); 1302 return ENXIO; 1303 } 1304 if (cs->cs_type == sc->sc_mib_phy.IEEE_PHY_Type && 1305 cs->cs_region == sc->sc_mib_phy.aCurrent_Reg_Domain) 1306 break; 1307 } 1308 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1309 for (i = cs->cs_min; i <= cs->cs_max; i++) { 1310 setbit(sc->sc_ic.ic_chan_avail, 1311 IEEE80211_FH_CHAN(i % 3 + 1, i)); 1312 /* 1313 * According to the IEEE 802.11 specification, 1314 * hop pattern parameter for FH phy should be 1315 * incremented by 3 for given hop chanset, i.e., 1316 * the chanset parameter is calculated for given 1317 * hop patter. However, BayStack 650 Access Points 1318 * apparently use fixed hop chanset parameter value 1319 * 1 for any hop pattern. So we also try this 1320 * combination of hop chanset and pattern. 1321 */ 1322 setbit(sc->sc_ic.ic_chan_avail, 1323 IEEE80211_FH_CHAN(1, i)); 1324 } 1325 } else { 1326 for (i = cs->cs_min; i <= cs->cs_max; i++) 1327 setbit(sc->sc_ic.ic_chan_avail, i); 1328 } 1329 sc->sc_cur_chan = cs->cs_def; 1330 1331 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE); 1332 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID; 1333 sc->sc_mib_local.Fragmentation_Dis = 1; 1334 sc->sc_mib_local.Accept_All_Multicast_Dis = 1; 1335 sc->sc_mib_local.Power_Saving_Mode_Dis = 1; 1336 1337 /* allocate buffers */ 1338 sc->sc_txbase = AWI_BUFFERS; 1339 sc->sc_txend = sc->sc_txbase + 1340 (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) + 1341 sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS; 1342 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase); 1343 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size, 1344 sc->sc_txend - sc->sc_txbase); 1345 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend); 1346 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size, 1347 AWI_BUFFERS_END - sc->sc_txend); 1348 sc->sc_mib_local.Network_Mode = 1; 1349 sc->sc_mib_local.Acting_as_AP = 0; 1350 return 0; 1351 } 1352 1353 static int 1354 awi_chan_check(void *arg, u_char *chanreq) 1355 { 1356 struct awi_softc *sc = arg; 1357 int i; 1358 struct awi_chanset *cs; 1359 u_char chanlist[(IEEE80211_CHAN_MAX+1)/NBBY]; 1360 1361 for (cs = awi_chanset; cs->cs_type != 0; cs++) { 1362 if (cs->cs_type != sc->sc_mib_phy.IEEE_PHY_Type) 1363 continue; 1364 memset(chanlist, 0, sizeof(chanlist)); 1365 for (i = 0; ; i++) { 1366 if (i == IEEE80211_CHAN_MAX) { 1367 sc->sc_mib_phy.aCurrent_Reg_Domain = 1368 cs->cs_region; 1369 memcpy(sc->sc_ic.ic_chan_avail, chanlist, 1370 sizeof(sc->sc_ic.ic_chan_avail)); 1371 sc->sc_cur_chan = cs->cs_def; 1372 return 0; 1373 } 1374 if (i >= cs->cs_min && i <= cs->cs_max) 1375 setbit(chanlist, i); 1376 else if (isset(chanreq, i)) 1377 break; 1378 } 1379 } 1380 return EINVAL; 1381 } 1382 1383 static int 1384 awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib, int wflag) 1385 { 1386 int error; 1387 u_int8_t size, *ptr; 1388 1389 switch (mib) { 1390 case AWI_MIB_LOCAL: 1391 ptr = (u_int8_t *)&sc->sc_mib_local; 1392 size = sizeof(sc->sc_mib_local); 1393 break; 1394 case AWI_MIB_ADDR: 1395 ptr = (u_int8_t *)&sc->sc_mib_addr; 1396 size = sizeof(sc->sc_mib_addr); 1397 break; 1398 case AWI_MIB_MAC: 1399 ptr = (u_int8_t *)&sc->sc_mib_mac; 1400 size = sizeof(sc->sc_mib_mac); 1401 break; 1402 case AWI_MIB_STAT: 1403 ptr = (u_int8_t *)&sc->sc_mib_stat; 1404 size = sizeof(sc->sc_mib_stat); 1405 break; 1406 case AWI_MIB_MGT: 1407 ptr = (u_int8_t *)&sc->sc_mib_mgt; 1408 size = sizeof(sc->sc_mib_mgt); 1409 break; 1410 case AWI_MIB_PHY: 1411 ptr = (u_int8_t *)&sc->sc_mib_phy; 1412 size = sizeof(sc->sc_mib_phy); 1413 break; 1414 default: 1415 return EINVAL; 1416 } 1417 if (sc->sc_cmd_inprog) { 1418 if ((error = awi_cmd_wait(sc)) != 0) { 1419 if (error == EWOULDBLOCK) 1420 DPRINTF(("awi_mib: cmd %d inprog", 1421 sc->sc_cmd_inprog)); 1422 return error; 1423 } 1424 } 1425 sc->sc_cmd_inprog = cmd; 1426 if (cmd == AWI_CMD_SET_MIB) 1427 awi_write_bytes(sc, AWI_CA_MIB_DATA, ptr, size); 1428 awi_write_1(sc, AWI_CA_MIB_TYPE, mib); 1429 awi_write_1(sc, AWI_CA_MIB_SIZE, size); 1430 awi_write_1(sc, AWI_CA_MIB_INDEX, 0); 1431 if ((error = awi_cmd(sc, cmd, wflag)) != 0) 1432 return error; 1433 if (cmd == AWI_CMD_GET_MIB) { 1434 awi_read_bytes(sc, AWI_CA_MIB_DATA, ptr, size); 1435 #ifdef AWI_DEBUG 1436 if (awi_debug) { 1437 int i; 1438 1439 printf("awi_mib: #%d:", mib); 1440 for (i = 0; i < size; i++) 1441 printf(" %02x", ptr[i]); 1442 printf("\n"); 1443 } 1444 #endif 1445 } 1446 return 0; 1447 } 1448 1449 static int 1450 awi_cmd(struct awi_softc *sc, u_int8_t cmd, int wflag) 1451 { 1452 u_int8_t status; 1453 int error = 0; 1454 #ifdef AWI_DEBUG 1455 static const char *cmdname[] = { 1456 "IDLE", "NOP", "SET_MIB", "INIT_TX", "FLUSH_TX", "INIT_RX", 1457 "KILL_RX", "SLEEP", "WAKE", "GET_MIB", "SCAN", "SYNC", "RESUME" 1458 }; 1459 #endif 1460 1461 #ifdef AWI_DEBUG 1462 if (awi_debug > 1) { 1463 if (cmd >= sizeof(cmdname)/sizeof(cmdname[0])) 1464 printf("awi_cmd: #%d", cmd); 1465 else 1466 printf("awi_cmd: %s", cmdname[cmd]); 1467 printf(" %s\n", wflag == AWI_NOWAIT ? "nowait" : "wait"); 1468 } 1469 #endif 1470 sc->sc_cmd_inprog = cmd; 1471 awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE); 1472 awi_write_1(sc, AWI_CMD, cmd); 1473 if (wflag == AWI_NOWAIT) 1474 return EINPROGRESS; 1475 if ((error = awi_cmd_wait(sc)) != 0) 1476 return error; 1477 status = awi_read_1(sc, AWI_CMD_STATUS); 1478 awi_write_1(sc, AWI_CMD, 0); 1479 switch (status) { 1480 case AWI_STAT_OK: 1481 break; 1482 case AWI_STAT_BADPARM: 1483 return EINVAL; 1484 default: 1485 printf("%s: command %d failed %x\n", 1486 sc->sc_dev.dv_xname, cmd, status); 1487 return ENXIO; 1488 } 1489 return 0; 1490 } 1491 1492 static int 1493 awi_cmd_wait(struct awi_softc *sc) 1494 { 1495 int i, error = 0; 1496 1497 i = 0; 1498 while (sc->sc_cmd_inprog) { 1499 if (sc->sc_invalid) 1500 return ENXIO; 1501 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) { 1502 printf("%s: failed to access hardware\n", 1503 sc->sc_dev.dv_xname); 1504 sc->sc_invalid = 1; 1505 return ENXIO; 1506 } 1507 if (sc->sc_cansleep) { 1508 sc->sc_sleep_cnt++; 1509 error = tsleep(sc, PWAIT, "awicmd", 1510 AWI_CMD_TIMEOUT*hz/1000); 1511 sc->sc_sleep_cnt--; 1512 } else { 1513 if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) { 1514 awi_cmd_done(sc); 1515 break; 1516 } 1517 if (i++ >= AWI_CMD_TIMEOUT*1000/10) 1518 error = EWOULDBLOCK; 1519 else 1520 DELAY(10); 1521 } 1522 if (error) 1523 break; 1524 } 1525 if (error) { 1526 DPRINTF(("awi_cmd_wait: cmd 0x%x, error %d\n", 1527 sc->sc_cmd_inprog, error)); 1528 } 1529 return error; 1530 } 1531 1532 static void 1533 awi_cmd_done(struct awi_softc *sc) 1534 { 1535 u_int8_t cmd, status; 1536 1537 status = awi_read_1(sc, AWI_CMD_STATUS); 1538 if (status == AWI_STAT_IDLE) 1539 return; /* stray interrupt */ 1540 1541 cmd = sc->sc_cmd_inprog; 1542 sc->sc_cmd_inprog = 0; 1543 wakeup(sc); 1544 awi_write_1(sc, AWI_CMD, 0); 1545 1546 if (status != AWI_STAT_OK) { 1547 printf("%s: command %d failed %x\n", 1548 sc->sc_dev.dv_xname, cmd, status); 1549 sc->sc_substate = AWI_ST_NONE; 1550 return; 1551 } 1552 if (sc->sc_substate != AWI_ST_NONE) 1553 (void)ieee80211_new_state(&sc->sc_ic.ic_if, sc->sc_nstate, -1); 1554 } 1555 1556 static int 1557 awi_next_txd(struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t *ntxdp) 1558 { 1559 u_int32_t txd, ntxd, frame; 1560 1561 txd = sc->sc_txnext; 1562 frame = txd + AWI_TXD_SIZE; 1563 if (frame + len > sc->sc_txend) 1564 frame = sc->sc_txbase; 1565 ntxd = frame + len; 1566 if (ntxd + AWI_TXD_SIZE > sc->sc_txend) 1567 ntxd = sc->sc_txbase; 1568 *framep = frame; 1569 *ntxdp = ntxd; 1570 /* 1571 * Determine if there are any room in ring buffer. 1572 * --- send wait, === new data, +++ conflict (ENOBUFS) 1573 * base........................end 1574 * done----txd=====ntxd OK 1575 * --txd=====done++++ntxd-- full 1576 * --txd=====ntxd done-- OK 1577 * ==ntxd done----txd=== OK 1578 * ==done++++ntxd----txd=== full 1579 * ++ntxd txd=====done++ full 1580 */ 1581 if (txd < ntxd) { 1582 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone) 1583 return ENOBUFS; 1584 } else { 1585 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone) 1586 return ENOBUFS; 1587 } 1588 return 0; 1589 } 1590 1591 static int 1592 awi_lock(struct awi_softc *sc) 1593 { 1594 int error = 0; 1595 1596 if (curproc == NULL) { 1597 /* 1598 * XXX 1599 * Though driver ioctl should be called with context, 1600 * KAME ipv6 stack calls ioctl in interrupt for now. 1601 * We simply abort the request if there are other 1602 * ioctl requests in progress. 1603 */ 1604 if (sc->sc_busy) { 1605 return EWOULDBLOCK; 1606 if (sc->sc_invalid) 1607 return ENXIO; 1608 } 1609 sc->sc_busy = 1; 1610 sc->sc_cansleep = 0; 1611 return 0; 1612 } 1613 while (sc->sc_busy) { 1614 if (sc->sc_invalid) 1615 return ENXIO; 1616 sc->sc_sleep_cnt++; 1617 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0); 1618 sc->sc_sleep_cnt--; 1619 if (error) 1620 return error; 1621 } 1622 sc->sc_busy = 1; 1623 sc->sc_cansleep = 1; 1624 return 0; 1625 } 1626 1627 static void 1628 awi_unlock(struct awi_softc *sc) 1629 { 1630 sc->sc_busy = 0; 1631 sc->sc_cansleep = 0; 1632 if (sc->sc_sleep_cnt) 1633 wakeup(sc); 1634 } 1635 1636 static int 1637 awi_intr_lock(struct awi_softc *sc) 1638 { 1639 u_int8_t status; 1640 int i, retry; 1641 1642 status = 1; 1643 for (retry = 0; retry < 10; retry++) { 1644 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) { 1645 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0) 1646 break; 1647 DELAY(5); 1648 } 1649 if (status != 0) 1650 break; 1651 awi_write_1(sc, AWI_LOCKOUT_MAC, 1); 1652 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0) 1653 break; 1654 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 1655 } 1656 if (status != 0) { 1657 printf("%s: failed to lock interrupt\n", 1658 sc->sc_dev.dv_xname); 1659 return ENXIO; 1660 } 1661 return 0; 1662 } 1663 1664 static void 1665 awi_intr_unlock(struct awi_softc *sc) 1666 { 1667 1668 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 1669 } 1670 1671 static int 1672 awi_newstate(void *arg, enum ieee80211_state nstate) 1673 { 1674 struct awi_softc *sc = arg; 1675 struct ieee80211com *ic = &sc->sc_ic; 1676 struct ieee80211_bss *bs = &ic->ic_bss; 1677 struct ifnet *ifp = &ic->ic_if; 1678 int error; 1679 u_int8_t newmode; 1680 enum ieee80211_state ostate; 1681 #ifdef AWI_DEBUG 1682 static const char *stname[] = 1683 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" }; 1684 static const char *substname[] = 1685 { "NONE", "SCAN_INIT", "SCAN_SETMIB", "SCAN_SCCMD", 1686 "SUB_INIT", "SUB_SETSS", "SUB_SYNC" }; 1687 #endif /* AWI_DEBUG */ 1688 1689 ostate = ic->ic_state; 1690 DPRINTF(("awi_newstate: %s (%s/%s) -> %s\n", stname[ostate], 1691 stname[sc->sc_nstate], substname[sc->sc_substate], stname[nstate])); 1692 1693 /* set LED */ 1694 switch (nstate) { 1695 case IEEE80211_S_INIT: 1696 awi_drvstate(sc, AWI_DRV_RESET); 1697 break; 1698 case IEEE80211_S_SCAN: 1699 if (ic->ic_flags & IEEE80211_F_ADHOC) 1700 awi_drvstate(sc, AWI_DRV_ADHSC); 1701 else 1702 awi_drvstate(sc, AWI_DRV_INFSY); 1703 break; 1704 case IEEE80211_S_AUTH: 1705 awi_drvstate(sc, AWI_DRV_INFSY); 1706 break; 1707 case IEEE80211_S_ASSOC: 1708 awi_drvstate(sc, AWI_DRV_INFAUTH); 1709 break; 1710 case IEEE80211_S_RUN: 1711 if (ic->ic_flags & IEEE80211_F_ADHOC) 1712 awi_drvstate(sc, AWI_DRV_ADHSY); 1713 else 1714 awi_drvstate(sc, AWI_DRV_INFASSOC); 1715 break; 1716 } 1717 1718 if (nstate == IEEE80211_S_INIT) { 1719 sc->sc_substate = AWI_ST_NONE; 1720 ic->ic_flags &= ~IEEE80211_F_SIBSS; 1721 return 0; 1722 } 1723 1724 /* state transition */ 1725 if (nstate == IEEE80211_S_SCAN) { 1726 /* SCAN substate */ 1727 if (sc->sc_substate == AWI_ST_NONE) { 1728 sc->sc_nstate = nstate; /* next state in transition */ 1729 sc->sc_substate = AWI_ST_SCAN_INIT; 1730 } 1731 switch (sc->sc_substate) { 1732 case AWI_ST_SCAN_INIT: 1733 sc->sc_substate = AWI_ST_SCAN_SETMIB; 1734 switch (ostate) { 1735 case IEEE80211_S_RUN: 1736 /* beacon miss */ 1737 if (ifp->if_flags & IFF_DEBUG) 1738 printf("%s: no recent beacons from %s;" 1739 " rescanning\n", 1740 ifp->if_xname, 1741 ether_sprintf(ic->ic_bss.bs_bssid)); 1742 /* FALLTHRU */ 1743 case IEEE80211_S_AUTH: 1744 case IEEE80211_S_ASSOC: 1745 /* timeout restart scan */ 1746 ieee80211_free_scan(ifp); 1747 /* FALLTHRU */ 1748 case IEEE80211_S_INIT: 1749 ic->ic_flags |= IEEE80211_F_ASCAN; 1750 ic->ic_scan_timer = 0; 1751 /* FALLTHRU */ 1752 case IEEE80211_S_SCAN: 1753 /* scan next */ 1754 break; 1755 } 1756 if (ic->ic_flags & IEEE80211_F_ASCAN) 1757 newmode = AWI_SCAN_ACTIVE; 1758 else 1759 newmode = AWI_SCAN_PASSIVE; 1760 if (sc->sc_mib_mgt.aScan_Mode != newmode) { 1761 sc->sc_mib_mgt.aScan_Mode = newmode; 1762 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, 1763 AWI_MIB_MGT, AWI_NOWAIT)) != 0) 1764 break; 1765 } 1766 /* FALLTHRU */ 1767 case AWI_ST_SCAN_SETMIB: 1768 sc->sc_substate = AWI_ST_SCAN_SCCMD; 1769 if (sc->sc_cmd_inprog) { 1770 if ((error = awi_cmd_wait(sc)) != 0) 1771 break; 1772 } 1773 sc->sc_cmd_inprog = AWI_CMD_SCAN; 1774 awi_write_2(sc, AWI_CA_SCAN_DURATION, 1775 (ic->ic_flags & IEEE80211_F_ASCAN) ? 1776 AWI_ASCAN_DURATION : AWI_PSCAN_DURATION); 1777 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1778 awi_write_1(sc, AWI_CA_SCAN_SET, 1779 IEEE80211_FH_CHANSET(bs->bs_chan)); 1780 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 1781 IEEE80211_FH_CHANPAT(bs->bs_chan)); 1782 awi_write_1(sc, AWI_CA_SCAN_IDX, 1); 1783 } else { 1784 awi_write_1(sc, AWI_CA_SCAN_SET, bs->bs_chan); 1785 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 0); 1786 awi_write_1(sc, AWI_CA_SCAN_IDX, 0); 1787 } 1788 awi_write_1(sc, AWI_CA_SCAN_SUSP, 0); 1789 sc->sc_cur_chan = bs->bs_chan; 1790 if ((error = awi_cmd(sc, AWI_CMD_SCAN, AWI_NOWAIT)) 1791 != 0) 1792 break; 1793 /* FALLTHRU */ 1794 case AWI_ST_SCAN_SCCMD: 1795 if (ic->ic_scan_timer == 0) 1796 ic->ic_scan_timer = 1797 (ic->ic_flags & IEEE80211_F_ASCAN) ? 1798 IEEE80211_ASCAN_WAIT : IEEE80211_PSCAN_WAIT; 1799 ifp->if_timer = 1; 1800 ic->ic_state = nstate; 1801 sc->sc_substate = AWI_ST_NONE; 1802 error = EINPROGRESS; 1803 break; 1804 default: 1805 DPRINTF(("awi_newstate: unexpected state %s/%s\n", 1806 stname[nstate], substname[sc->sc_substate])); 1807 sc->sc_substate = AWI_ST_NONE; 1808 error = EIO; 1809 break; 1810 } 1811 return error; 1812 } 1813 1814 if (ostate == IEEE80211_S_SCAN) { 1815 /* set SSID and channel */ 1816 /* substate */ 1817 if (sc->sc_substate == AWI_ST_NONE) { 1818 sc->sc_nstate = nstate; /* next state in transition */ 1819 sc->sc_substate = AWI_ST_SUB_INIT; 1820 } 1821 switch (sc->sc_substate) { 1822 case AWI_ST_SUB_INIT: 1823 sc->sc_substate = AWI_ST_SUB_SETSS; 1824 memcpy(&sc->sc_mib_mgt.aCurrent_BSS_ID, bs->bs_bssid, 1825 IEEE80211_ADDR_LEN); 1826 memset(&sc->sc_mib_mgt.aCurrent_ESS_ID, 0, 1827 AWI_ESS_ID_SIZE); 1828 sc->sc_mib_mgt.aCurrent_ESS_ID[0] = 1829 IEEE80211_ELEMID_SSID; 1830 sc->sc_mib_mgt.aCurrent_ESS_ID[1] = bs->bs_esslen; 1831 memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID[2], 1832 bs->bs_essid, bs->bs_esslen); 1833 LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, 1834 bs->bs_intval); 1835 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, 1836 AWI_NOWAIT)) != 0) 1837 break; 1838 /* FALLTHRU */ 1839 case AWI_ST_SUB_SETSS: 1840 sc->sc_substate = AWI_ST_SUB_SYNC; 1841 if (sc->sc_cmd_inprog) { 1842 if (awi_cmd_wait(sc)) 1843 break; 1844 } 1845 sc->sc_cmd_inprog = AWI_CMD_SYNC; 1846 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1847 awi_write_1(sc, AWI_CA_SYNC_SET, 1848 IEEE80211_FH_CHANSET(bs->bs_chan)); 1849 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 1850 IEEE80211_FH_CHANPAT(bs->bs_chan)); 1851 awi_write_1(sc, AWI_CA_SYNC_IDX, 1852 bs->bs_fhindex); 1853 awi_write_2(sc, AWI_CA_SYNC_DWELL, 1854 bs->bs_fhdwell); 1855 } else { 1856 awi_write_1(sc, AWI_CA_SYNC_SET, bs->bs_chan); 1857 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 0); 1858 awi_write_1(sc, AWI_CA_SYNC_IDX, 0); 1859 awi_write_2(sc, AWI_CA_SYNC_DWELL, 0); 1860 } 1861 if ((ic->ic_flags & IEEE80211_F_SIBSS) && 1862 !sc->sc_no_bssid) 1863 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1); 1864 else 1865 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0); 1866 awi_write_2(sc, AWI_CA_SYNC_MBZ, 0); 1867 awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP, 1868 bs->bs_tstamp, 8); 1869 awi_write_4(sc, AWI_CA_SYNC_REFTIME, bs->bs_timoff); 1870 sc->sc_cur_chan = bs->bs_chan; 1871 if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT)) 1872 != 0) 1873 break; 1874 /* FALLTHRU */ 1875 case AWI_ST_SUB_SYNC: 1876 sc->sc_substate = AWI_ST_NONE; 1877 if (ic->ic_flags & IEEE80211_F_SIBSS) { 1878 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, 1879 AWI_MIB_MGT, AWI_WAIT)) != 0) 1880 break; 1881 memcpy(bs->bs_bssid, 1882 &sc->sc_mib_mgt.aCurrent_BSS_ID, 1883 IEEE80211_ADDR_LEN); 1884 } else { 1885 if (nstate == IEEE80211_S_RUN) { 1886 sc->sc_rx_timer = 10; 1887 ifp->if_timer = 1; 1888 } 1889 } 1890 error = 0; 1891 break; 1892 default: 1893 DPRINTF(("awi_newstate: unexpected state %s/%s\n", 1894 stname[nstate], substname[sc->sc_substate])); 1895 sc->sc_substate = AWI_ST_NONE; 1896 error = EIO; 1897 break; 1898 } 1899 return error; 1900 } 1901 1902 sc->sc_substate = AWI_ST_NONE; 1903 1904 return 0; 1905 } 1906 1907 static struct mbuf * 1908 awi_ether_encap(struct awi_softc *sc, struct mbuf *m) 1909 { 1910 struct ieee80211com *ic = &sc->sc_ic; 1911 struct ieee80211_bss *bs = &ic->ic_bss; 1912 struct ether_header *eh; 1913 struct ieee80211_frame *wh; 1914 1915 if (m->m_len < sizeof(struct ether_header)) { 1916 m = m_pullup(m, sizeof(struct ether_header)); 1917 if (m == NULL) 1918 return NULL; 1919 } 1920 eh = mtod(m, struct ether_header *); 1921 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); 1922 if (m == NULL) 1923 return NULL; 1924 wh = mtod(m, struct ieee80211_frame *); 1925 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; 1926 *(u_int16_t *)wh->i_dur = 0; 1927 *(u_int16_t *)wh->i_seq = 1928 htole16(bs->bs_txseq << IEEE80211_SEQ_SEQ_SHIFT); 1929 bs->bs_txseq++; 1930 if (ic->ic_flags & IEEE80211_F_ADHOC) { 1931 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 1932 if (sc->sc_adhoc_ap) 1933 memcpy(wh->i_addr1, bs->bs_macaddr, IEEE80211_ADDR_LEN); 1934 else 1935 memcpy(wh->i_addr1, eh->ether_dhost, 1936 IEEE80211_ADDR_LEN); 1937 memcpy(wh->i_addr2, eh->ether_shost, IEEE80211_ADDR_LEN); 1938 memcpy(wh->i_addr3, bs->bs_bssid, IEEE80211_ADDR_LEN); 1939 } else { 1940 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; 1941 memcpy(wh->i_addr1, bs->bs_bssid, IEEE80211_ADDR_LEN); 1942 memcpy(wh->i_addr2, eh->ether_shost, IEEE80211_ADDR_LEN); 1943 memcpy(wh->i_addr3, eh->ether_dhost, IEEE80211_ADDR_LEN); 1944 } 1945 return m; 1946 } 1947 1948 static struct mbuf * 1949 awi_ether_modcap(struct awi_softc *sc, struct mbuf *m) 1950 { 1951 struct ieee80211com *ic = &sc->sc_ic; 1952 struct ether_header eh; 1953 struct ieee80211_frame wh; 1954 struct llc *llc; 1955 1956 if (m->m_len < sizeof(wh) + sizeof(eh)) { 1957 m = m_pullup(m, sizeof(wh) + sizeof(eh)); 1958 if (m == NULL) 1959 return NULL; 1960 } 1961 memcpy(&wh, mtod(m, caddr_t), sizeof(wh)); 1962 if (wh.i_fc[0] != (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA)) 1963 return m; 1964 memcpy(&eh, mtod(m, caddr_t) + sizeof(wh), sizeof(eh)); 1965 m_adj(m, sizeof(eh) - sizeof(*llc)); 1966 if (ic->ic_flags & IEEE80211_F_ADHOC) 1967 memcpy(wh.i_addr2, eh.ether_shost, IEEE80211_ADDR_LEN); 1968 memcpy(mtod(m, caddr_t), &wh, sizeof(wh)); 1969 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); 1970 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 1971 llc->llc_control = LLC_UI; 1972 llc->llc_snap.org_code[0] = 0; 1973 llc->llc_snap.org_code[1] = 0; 1974 llc->llc_snap.org_code[2] = 0; 1975 llc->llc_snap.ether_type = eh.ether_type; 1976 return m; 1977 } 1978