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