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