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