1 /* $NetBSD: awi.c,v 1.50 2002/10/01 03:27:04 onoe 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.50 2002/10/01 03:27:04 onoe 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 } 508 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); 509 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE); 510 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID; 511 sc->sc_mib_mac.aDesired_ESS_ID[1] = ic->ic_des_esslen; 512 memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], ic->ic_des_essid, 513 ic->ic_des_esslen); 514 515 if ((error = awi_mode_init(sc)) != 0) { 516 DPRINTF(("awi_init: awi_mode_init failed %d\n", error)); 517 awi_stop(ifp, 1); 518 return error; 519 } 520 521 /* start transmitter */ 522 sc->sc_txdone = sc->sc_txnext = sc->sc_txbase; 523 awi_write_4(sc, sc->sc_txbase + AWI_TXD_START, 0); 524 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NEXT, 0); 525 awi_write_4(sc, sc->sc_txbase + AWI_TXD_LENGTH, 0); 526 awi_write_1(sc, sc->sc_txbase + AWI_TXD_RATE, 0); 527 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NDA, 0); 528 awi_write_4(sc, sc->sc_txbase + AWI_TXD_NRA, 0); 529 awi_write_1(sc, sc->sc_txbase + AWI_TXD_STATE, 0); 530 awi_write_4(sc, AWI_CA_TX_DATA, sc->sc_txbase); 531 awi_write_4(sc, AWI_CA_TX_MGT, 0); 532 awi_write_4(sc, AWI_CA_TX_BCAST, 0); 533 awi_write_4(sc, AWI_CA_TX_PS, 0); 534 awi_write_4(sc, AWI_CA_TX_CF, 0); 535 if ((error = awi_cmd(sc, AWI_CMD_INIT_TX, AWI_WAIT)) != 0) { 536 DPRINTF(("awi_init: failed to start transmitter: %d\n", error)); 537 awi_stop(ifp, 1); 538 return error; 539 } 540 541 /* start receiver */ 542 if ((error = awi_cmd(sc, AWI_CMD_INIT_RX, AWI_WAIT)) != 0) { 543 DPRINTF(("awi_init: failed to start receiver: %d\n", error)); 544 awi_stop(ifp, 1); 545 return error; 546 } 547 sc->sc_rxdoff = awi_read_4(sc, AWI_CA_IRX_DATA_DESC); 548 sc->sc_rxmoff = awi_read_4(sc, AWI_CA_IRX_PS_DESC); 549 550 ifp->if_flags |= IFF_RUNNING; 551 ifp->if_flags &= ~IFF_OACTIVE; 552 553 if (ic->ic_opmode == IEEE80211_M_AHDEMO || 554 ic->ic_opmode == IEEE80211_M_HOSTAP) { 555 ni->ni_chan = ic->ic_ibss_chan; 556 ni->ni_intval = ic->ic_lintval; 557 ni->ni_rssi = 0; 558 ni->ni_rstamp = 0; 559 memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); 560 ni->ni_nrate = 0; 561 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 562 if (ic->ic_sup_rates[i]) 563 ni->ni_rates[ni->ni_nrate++] = 564 ic->ic_sup_rates[i]; 565 } 566 IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); 567 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 568 IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); 569 ni->ni_esslen = ic->ic_des_esslen; 570 memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); 571 ni->ni_capinfo = IEEE80211_CAPINFO_ESS; 572 if (ic->ic_phytype == IEEE80211_T_FH) { 573 ni->ni_fhdwell = 200; /* XXX */ 574 ni->ni_fhindex = 1; 575 } 576 } else { 577 ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; 578 memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN); 579 ni->ni_esslen = 0; 580 } 581 if (ic->ic_flags & IEEE80211_F_WEPON) 582 ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; 583 if (ic->ic_opmode != IEEE80211_M_AHDEMO) 584 ic->ic_flags |= IEEE80211_F_SIBSS; 585 ic->ic_state = IEEE80211_S_SCAN; /*XXX*/ 586 sc->sc_substate = AWI_ST_NONE; 587 ieee80211_new_state(&ic->ic_if, IEEE80211_S_RUN, -1); 588 } else { 589 ni->ni_chan = sc->sc_cur_chan; 590 ieee80211_new_state(&ic->ic_if, IEEE80211_S_SCAN, -1); 591 } 592 return 0; 593 } 594 595 static void 596 awi_stop(struct ifnet *ifp, int disable) 597 { 598 struct awi_softc *sc = ifp->if_softc; 599 600 if (!sc->sc_enabled) 601 return; 602 603 DPRINTF(("awi_stop(%d)\n", disable)); 604 605 ieee80211_new_state(&sc->sc_ic.ic_if, IEEE80211_S_INIT, -1); 606 607 if (!sc->sc_invalid) { 608 if (sc->sc_cmd_inprog) 609 (void)awi_cmd_wait(sc); 610 (void)awi_cmd(sc, AWI_CMD_KILL_RX, AWI_WAIT); 611 sc->sc_cmd_inprog = AWI_CMD_FLUSH_TX; 612 awi_write_1(sc, AWI_CA_FTX_DATA, 1); 613 awi_write_1(sc, AWI_CA_FTX_MGT, 0); 614 awi_write_1(sc, AWI_CA_FTX_BCAST, 0); 615 awi_write_1(sc, AWI_CA_FTX_PS, 0); 616 awi_write_1(sc, AWI_CA_FTX_CF, 0); 617 (void)awi_cmd(sc, AWI_CMD_FLUSH_TX, AWI_WAIT); 618 } 619 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 620 ifp->if_timer = 0; 621 sc->sc_tx_timer = sc->sc_rx_timer = 0; 622 if (sc->sc_rxpend != NULL) { 623 m_freem(sc->sc_rxpend); 624 sc->sc_rxpend = NULL; 625 } 626 IFQ_PURGE(&ifp->if_snd); 627 628 if (disable) { 629 if (sc->sc_disable) 630 (*sc->sc_disable)(sc); 631 sc->sc_enabled = 0; 632 } 633 } 634 635 static void 636 awi_start(struct ifnet *ifp) 637 { 638 struct awi_softc *sc = ifp->if_softc; 639 struct ieee80211com *ic = &sc->sc_ic; 640 struct ieee80211_frame *wh; 641 struct mbuf *m, *m0; 642 int len, dowep; 643 u_int32_t txd, frame, ntxd; 644 u_int8_t rate; 645 646 if (!sc->sc_enabled || sc->sc_invalid) 647 return; 648 649 for (;;) { 650 txd = sc->sc_txnext; 651 IF_POLL(&ic->ic_mgtq, m0); 652 dowep = 0; 653 if (m0 != NULL) { 654 len = m0->m_pkthdr.len; 655 if (awi_next_txd(sc, len, &frame, &ntxd)) { 656 ifp->if_flags |= IFF_OACTIVE; 657 break; 658 } 659 IF_DEQUEUE(&ic->ic_mgtq, m0); 660 } else { 661 if (ic->ic_state != IEEE80211_S_RUN) 662 break; 663 IFQ_POLL(&ifp->if_snd, m0); 664 if (m0 == NULL) 665 break; 666 /* 667 * Need to calculate the real length to determine 668 * if the transmit buffer has a room for the packet. 669 */ 670 len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame); 671 if (!(ifp->if_flags & IFF_LINK0) && !sc->sc_adhoc_ap) 672 len += sizeof(struct llc) - 673 sizeof(struct ether_header); 674 if (ic->ic_flags & IEEE80211_F_WEPON) { 675 dowep = 1; 676 len += IEEE80211_WEP_IVLEN + 677 IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; 678 } 679 if (awi_next_txd(sc, len, &frame, &ntxd)) { 680 ifp->if_flags |= IFF_OACTIVE; 681 break; 682 } 683 IFQ_DEQUEUE(&ifp->if_snd, m0); 684 ifp->if_opackets++; 685 #if NBPFILTER > 0 686 if (ifp->if_bpf) 687 bpf_mtap(ifp->if_bpf, m0); 688 #endif 689 if ((ifp->if_flags & IFF_LINK0) || sc->sc_adhoc_ap) 690 m0 = awi_ether_encap(sc, m0); 691 else 692 m0 = ieee80211_encap(ifp, m0); 693 if (m0 == NULL) { 694 ifp->if_oerrors++; 695 continue; 696 } 697 wh = mtod(m0, struct ieee80211_frame *); 698 if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 699 (ic->ic_opmode == IEEE80211_M_HOSTAP || 700 ic->ic_opmode == IEEE80211_M_IBSS) && 701 sc->sc_adhoc_ap == 0 && 702 (ifp->if_flags & IFF_LINK0) == 0 && 703 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 704 IEEE80211_FC0_TYPE_DATA && 705 ieee80211_find_node(ic, wh->i_addr1) == NULL) { 706 m_freem(m0); 707 ifp->if_oerrors++; 708 continue; 709 } 710 } 711 #if NBPFILTER > 0 712 if (ic->ic_rawbpf) 713 bpf_mtap(ic->ic_rawbpf, m0); 714 #endif 715 if (dowep) { 716 if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) { 717 ifp->if_oerrors++; 718 continue; 719 } 720 } 721 #ifdef DIAGNOSTIC 722 if (m0->m_pkthdr.len != len) { 723 printf("%s: length %d should be %d\n", 724 ifp->if_xname, m0->m_pkthdr.len, len); 725 m_freem(m0); 726 ifp->if_oerrors++; 727 continue; 728 } 729 #endif 730 731 if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2)) 732 ieee80211_dump_pkt(m0->m_data, m0->m_len, 733 ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & 734 IEEE80211_RATE_VAL, -1); 735 736 for (m = m0, len = 0; m != NULL; m = m->m_next) { 737 awi_write_bytes(sc, frame + len, mtod(m, u_int8_t *), 738 m->m_len); 739 len += m->m_len; 740 } 741 m_freem(m0); 742 rate = (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & 743 IEEE80211_RATE_VAL) * 5; 744 awi_write_1(sc, ntxd + AWI_TXD_STATE, 0); 745 awi_write_4(sc, txd + AWI_TXD_START, frame); 746 awi_write_4(sc, txd + AWI_TXD_NEXT, ntxd); 747 awi_write_4(sc, txd + AWI_TXD_LENGTH, len); 748 awi_write_1(sc, txd + AWI_TXD_RATE, rate); 749 awi_write_4(sc, txd + AWI_TXD_NDA, 0); 750 awi_write_4(sc, txd + AWI_TXD_NRA, 0); 751 awi_write_1(sc, txd + AWI_TXD_STATE, AWI_TXD_ST_OWN); 752 sc->sc_txnext = ntxd; 753 754 sc->sc_tx_timer = 5; 755 ifp->if_timer = 1; 756 } 757 } 758 759 static void 760 awi_watchdog(struct ifnet *ifp) 761 { 762 struct awi_softc *sc = ifp->if_softc; 763 u_int32_t prevdone; 764 int ocansleep; 765 766 ifp->if_timer = 0; 767 if (!sc->sc_enabled || sc->sc_invalid) 768 return; 769 770 ocansleep = sc->sc_cansleep; 771 sc->sc_cansleep = 0; 772 if (sc->sc_tx_timer) { 773 if (--sc->sc_tx_timer == 0) { 774 printf("%s: device timeout\n", ifp->if_xname); 775 prevdone = sc->sc_txdone; 776 awi_tx_int(sc); 777 if (sc->sc_txdone == prevdone) { 778 ifp->if_oerrors++; 779 awi_init(ifp); 780 goto out; 781 } 782 } 783 ifp->if_timer = 1; 784 } 785 if (sc->sc_rx_timer) { 786 if (--sc->sc_rx_timer == 0) { 787 if (sc->sc_ic.ic_state == IEEE80211_S_RUN) { 788 ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1); 789 goto out; 790 } 791 } else 792 ifp->if_timer = 1; 793 } 794 /* TODO: rate control */ 795 ieee80211_watchdog(ifp); 796 out: 797 sc->sc_cansleep = ocansleep; 798 } 799 800 static int 801 awi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 802 { 803 struct awi_softc *sc = ifp->if_softc; 804 struct ifreq *ifr = (struct ifreq *)data; 805 int s, error; 806 807 s = splnet(); 808 /* serialize ioctl, since we may sleep */ 809 if ((error = awi_lock(sc)) != 0) 810 goto cantlock; 811 812 switch (cmd) { 813 case SIOCSIFFLAGS: 814 if (ifp->if_flags & IFF_UP) { 815 if (sc->sc_enabled) { 816 /* 817 * To avoid rescanning another access point, 818 * do not call awi_init() here. Instead, 819 * only reflect promisc mode settings. 820 */ 821 error = awi_mode_init(sc); 822 } else 823 error = awi_init(ifp); 824 } else if (sc->sc_enabled) 825 awi_stop(ifp, 1); 826 break; 827 case SIOCSIFMEDIA: 828 case SIOCGIFMEDIA: 829 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 830 break; 831 case SIOCADDMULTI: 832 case SIOCDELMULTI: 833 error = (cmd == SIOCADDMULTI) ? 834 ether_addmulti(ifr, &sc->sc_ic.ic_ec) : 835 ether_delmulti(ifr, &sc->sc_ic.ic_ec); 836 if (error == ENETRESET) { 837 /* do not rescan */ 838 if (sc->sc_enabled) 839 error = awi_mode_init(sc); 840 else 841 error = 0; 842 } 843 break; 844 default: 845 error = ieee80211_ioctl(ifp, cmd, data); 846 if (error == ENETRESET) { 847 if (sc->sc_enabled) 848 error = awi_init(ifp); 849 else 850 error = 0; 851 } 852 break; 853 } 854 awi_unlock(sc); 855 cantlock: 856 splx(s); 857 return error; 858 } 859 860 /* 861 * Called from ifmedia_ioctl via awi_ioctl with lock obtained. 862 */ 863 static int 864 awi_media_change(struct ifnet *ifp) 865 { 866 struct awi_softc *sc = ifp->if_softc; 867 struct ieee80211com *ic = &sc->sc_ic; 868 struct ifmedia_entry *ime; 869 enum ieee80211_opmode newmode; 870 int i, rate, newadhoc_ap, error = 0; 871 872 ime = sc->sc_media.ifm_cur; 873 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { 874 i = -1; 875 } else { 876 rate = ieee80211_media2rate(ime->ifm_media, ic->ic_phytype); 877 if (rate == 0) 878 return EINVAL; 879 for (i = 0; i < IEEE80211_RATE_SIZE; i++) { 880 if ((ic->ic_sup_rates[i] & IEEE80211_RATE_VAL) == rate) 881 break; 882 } 883 if (i == IEEE80211_RATE_SIZE) 884 return EINVAL; 885 } 886 if (ic->ic_fixed_rate != i) { 887 ic->ic_fixed_rate = i; 888 error = ENETRESET; 889 } 890 891 /* 892 * combination of mediaopt 893 * 894 * hostap adhoc flag0 opmode adhoc_ap comment 895 * + - - HOSTAP 0 HostAP 896 * - + - IBSS 0 IBSS 897 * - + + AHDEMO 0 WaveLAN adhoc 898 * - - + IBSS 1 Melco old Sta 899 * also LINK0 900 * - - - STA 0 Infra Station 901 */ 902 newadhoc_ap = 0; 903 if (ime->ifm_media & IFM_IEEE80211_HOSTAP) 904 newmode = IEEE80211_M_HOSTAP; 905 else if (ime->ifm_media & IFM_IEEE80211_ADHOC) { 906 if (ic->ic_phytype == IEEE80211_T_DS && 907 (ime->ifm_media & IFM_FLAG0)) 908 newmode = IEEE80211_M_AHDEMO; 909 else 910 newmode = IEEE80211_M_IBSS; 911 } else if (ime->ifm_media & IFM_FLAG0) { 912 newmode = IEEE80211_M_IBSS; 913 newadhoc_ap = 1; 914 } else 915 newmode = IEEE80211_M_STA; 916 if (ic->ic_opmode != newmode || sc->sc_adhoc_ap != newadhoc_ap) { 917 ic->ic_opmode = newmode; 918 sc->sc_adhoc_ap = newadhoc_ap; 919 error = ENETRESET; 920 } 921 922 if (error == ENETRESET) { 923 if (sc->sc_enabled) 924 error = awi_init(ifp); 925 else 926 error = 0; 927 } 928 return error; 929 } 930 931 static void 932 awi_media_status(struct ifnet *ifp, struct ifmediareq *imr) 933 { 934 struct awi_softc *sc = ifp->if_softc; 935 struct ieee80211com *ic = &sc->sc_ic; 936 int rate; 937 938 imr->ifm_status = IFM_AVALID; 939 if (ic->ic_state == IEEE80211_S_RUN) 940 imr->ifm_status |= IFM_ACTIVE; 941 imr->ifm_active = IFM_IEEE80211; 942 if (ic->ic_state == IEEE80211_S_RUN) 943 rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & 944 IEEE80211_RATE_VAL; 945 else { 946 if (ic->ic_fixed_rate == -1) 947 rate = 0; 948 else 949 rate = ic->ic_sup_rates[ic->ic_fixed_rate] & 950 IEEE80211_RATE_VAL; 951 } 952 imr->ifm_active |= ieee80211_rate2media(rate, ic->ic_phytype); 953 switch (ic->ic_opmode) { 954 case IEEE80211_M_STA: 955 break; 956 case IEEE80211_M_IBSS: 957 if (sc->sc_adhoc_ap) 958 imr->ifm_active |= IFM_FLAG0; 959 else 960 imr->ifm_active |= IFM_IEEE80211_ADHOC; 961 break; 962 case IEEE80211_M_AHDEMO: 963 imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0; 964 break; 965 case IEEE80211_M_HOSTAP: 966 imr->ifm_active |= IFM_IEEE80211_HOSTAP; 967 break; 968 } 969 } 970 971 static int 972 awi_mode_init(struct awi_softc *sc) 973 { 974 struct ifnet *ifp = &sc->sc_ic.ic_if; 975 int n, error; 976 struct ether_multi *enm; 977 struct ether_multistep step; 978 979 /* reinitialize muticast filter */ 980 n = 0; 981 sc->sc_mib_local.Accept_All_Multicast_Dis = 0; 982 if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP && 983 (ifp->if_flags & IFF_PROMISC)) { 984 sc->sc_mib_mac.aPromiscuous_Enable = 1; 985 goto set_mib; 986 } 987 sc->sc_mib_mac.aPromiscuous_Enable = 0; 988 ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm); 989 while (enm != NULL) { 990 if (n == AWI_GROUP_ADDR_SIZE || 991 !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) 992 goto set_mib; 993 IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n], 994 enm->enm_addrlo); 995 n++; 996 ETHER_NEXT_MULTI(step, enm); 997 } 998 for (; n < AWI_GROUP_ADDR_SIZE; n++) 999 memset(sc->sc_mib_addr.aGroup_Addresses[n], 0, 1000 IEEE80211_ADDR_LEN); 1001 sc->sc_mib_local.Accept_All_Multicast_Dis = 1; 1002 1003 set_mib: 1004 if (sc->sc_mib_local.Accept_All_Multicast_Dis) 1005 ifp->if_flags &= ~IFF_ALLMULTI; 1006 else 1007 ifp->if_flags |= IFF_ALLMULTI; 1008 sc->sc_mib_mgt.Wep_Required = 1009 (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) ? AWI_WEP_ON : AWI_WEP_OFF; 1010 1011 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) || 1012 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_ADDR, AWI_WAIT)) || 1013 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MAC, AWI_WAIT)) || 1014 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_WAIT)) || 1015 (error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_PHY, AWI_WAIT))) { 1016 DPRINTF(("awi_mode_init: MIB set failed: %d\n", error)); 1017 return error; 1018 } 1019 return 0; 1020 } 1021 1022 static void 1023 awi_rx_int(struct awi_softc *sc) 1024 { 1025 struct ifnet *ifp = &sc->sc_ic.ic_if; 1026 u_int8_t state, rate, rssi; 1027 u_int16_t len; 1028 u_int32_t frame, next, rstamp, rxoff; 1029 struct mbuf *m; 1030 1031 rxoff = sc->sc_rxdoff; 1032 for (;;) { 1033 state = awi_read_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE); 1034 if (state & AWI_RXD_ST_OWN) 1035 break; 1036 if (!(state & AWI_RXD_ST_CONSUMED)) { 1037 if (sc->sc_substate != AWI_ST_NONE) 1038 goto rx_next; 1039 if (state & AWI_RXD_ST_RXERROR) { 1040 ifp->if_ierrors++; 1041 goto rx_next; 1042 } 1043 len = awi_read_2(sc, rxoff + AWI_RXD_LEN); 1044 rate = awi_read_1(sc, rxoff + AWI_RXD_RATE); 1045 rssi = awi_read_1(sc, rxoff + AWI_RXD_RSSI); 1046 frame = awi_read_4(sc, rxoff + AWI_RXD_START_FRAME) & 1047 0x7fff; 1048 rstamp = awi_read_4(sc, rxoff + AWI_RXD_LOCALTIME); 1049 m = awi_devget(sc, frame, len); 1050 if (m == NULL) { 1051 ifp->if_ierrors++; 1052 goto rx_next; 1053 } 1054 if (state & AWI_RXD_ST_LF) { 1055 /* TODO check my bss */ 1056 if (!(sc->sc_ic.ic_flags & IEEE80211_F_SIBSS) && 1057 sc->sc_ic.ic_state == IEEE80211_S_RUN) { 1058 sc->sc_rx_timer = 10; 1059 ifp->if_timer = 1; 1060 } 1061 if ((ifp->if_flags & IFF_DEBUG) && 1062 (ifp->if_flags & IFF_LINK2)) 1063 ieee80211_dump_pkt(m->m_data, m->m_len, 1064 rate / 5, rssi); 1065 if ((ifp->if_flags & IFF_LINK0) || 1066 sc->sc_adhoc_ap) 1067 m = awi_ether_modcap(sc, m); 1068 if (m == NULL) 1069 ifp->if_ierrors++; 1070 else 1071 ieee80211_input(ifp, m, rssi, rstamp); 1072 } else 1073 sc->sc_rxpend = m; 1074 rx_next: 1075 state |= AWI_RXD_ST_CONSUMED; 1076 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1077 } 1078 next = awi_read_4(sc, rxoff + AWI_RXD_NEXT); 1079 if (next & AWI_RXD_NEXT_LAST) 1080 break; 1081 /* make sure the next pointer is correct */ 1082 if (next != awi_read_4(sc, rxoff + AWI_RXD_NEXT)) 1083 break; 1084 state |= AWI_RXD_ST_OWN; 1085 awi_write_1(sc, rxoff + AWI_RXD_HOST_DESC_STATE, state); 1086 rxoff = next & 0x7fff; 1087 } 1088 sc->sc_rxdoff = rxoff; 1089 } 1090 1091 static void 1092 awi_tx_int(struct awi_softc *sc) 1093 { 1094 struct ifnet *ifp = &sc->sc_ic.ic_if; 1095 u_int8_t flags; 1096 1097 while (sc->sc_txdone != sc->sc_txnext) { 1098 flags = awi_read_1(sc, sc->sc_txdone + AWI_TXD_STATE); 1099 if ((flags & AWI_TXD_ST_OWN) || !(flags & AWI_TXD_ST_DONE)) 1100 break; 1101 if (flags & AWI_TXD_ST_ERROR) 1102 ifp->if_oerrors++; 1103 sc->sc_txdone = awi_read_4(sc, sc->sc_txdone + AWI_TXD_NEXT) & 1104 0x7fff; 1105 } 1106 DPRINTF2(("awi_txint: txdone %d txnext %d txbase %d txend %d\n", 1107 sc->sc_txdone, sc->sc_txnext, sc->sc_txbase, sc->sc_txend)); 1108 sc->sc_tx_timer = 0; 1109 ifp->if_flags &= ~IFF_OACTIVE; 1110 awi_start(ifp); 1111 } 1112 1113 static struct mbuf * 1114 awi_devget(struct awi_softc *sc, u_int32_t off, u_int16_t len) 1115 { 1116 struct ifnet *ifp = &sc->sc_ic.ic_if; 1117 struct mbuf *m; 1118 struct mbuf *top, **mp; 1119 u_int tlen; 1120 1121 top = sc->sc_rxpend; 1122 mp = ⊤ 1123 if (top != NULL) { 1124 sc->sc_rxpend = NULL; 1125 top->m_pkthdr.len += len; 1126 m = top; 1127 while (*mp != NULL) { 1128 m = *mp; 1129 mp = &m->m_next; 1130 } 1131 if (m->m_flags & M_EXT) 1132 tlen = m->m_ext.ext_size; 1133 else if (m->m_flags & M_PKTHDR) 1134 tlen = MHLEN; 1135 else 1136 tlen = MLEN; 1137 tlen -= m->m_len; 1138 if (tlen > len) 1139 tlen = len; 1140 awi_read_bytes(sc, off, mtod(m, u_int8_t *) + m->m_len, tlen); 1141 off += tlen; 1142 len -= tlen; 1143 } 1144 1145 while (len > 0) { 1146 if (top == NULL) { 1147 MGETHDR(m, M_DONTWAIT, MT_DATA); 1148 if (m == NULL) 1149 return NULL; 1150 m->m_pkthdr.rcvif = ifp; 1151 m->m_pkthdr.len = len; 1152 m->m_len = MHLEN; 1153 m->m_flags |= M_HASFCS; 1154 } else { 1155 MGET(m, M_DONTWAIT, MT_DATA); 1156 if (m == NULL) { 1157 m_freem(top); 1158 return NULL; 1159 } 1160 m->m_len = MLEN; 1161 } 1162 if (len >= MINCLSIZE) { 1163 MCLGET(m, M_DONTWAIT); 1164 if (m->m_flags & M_EXT) 1165 m->m_len = m->m_ext.ext_size; 1166 } 1167 if (top == NULL) { 1168 int hdrlen = sizeof(struct ieee80211_frame) + 1169 sizeof(struct llc); 1170 caddr_t newdata = (caddr_t) 1171 ALIGN(m->m_data + hdrlen) - hdrlen; 1172 m->m_len -= newdata - m->m_data; 1173 m->m_data = newdata; 1174 } 1175 if (m->m_len > len) 1176 m->m_len = len; 1177 awi_read_bytes(sc, off, mtod(m, u_int8_t *), m->m_len); 1178 off += m->m_len; 1179 len -= m->m_len; 1180 *mp = m; 1181 mp = &m->m_next; 1182 } 1183 return top; 1184 } 1185 1186 /* 1187 * Initialize hardware and start firmware to accept commands. 1188 * Called everytime after power on firmware. 1189 */ 1190 1191 static int 1192 awi_hw_init(struct awi_softc *sc) 1193 { 1194 u_int8_t status; 1195 u_int16_t intmask; 1196 int i, error; 1197 1198 sc->sc_enab_intr = 0; 1199 sc->sc_invalid = 0; /* XXX: really? */ 1200 awi_drvstate(sc, AWI_DRV_RESET); 1201 1202 /* reset firmware */ 1203 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1204 DELAY(100); 1205 awi_write_1(sc, AWI_SELFTEST, 0); 1206 awi_write_1(sc, AWI_CMD, 0); 1207 awi_write_1(sc, AWI_BANNER, 0); 1208 am79c930_gcr_clearbits(&sc->sc_chip, AM79C930_GCR_CORESET); 1209 DELAY(100); 1210 1211 /* wait for selftest completion */ 1212 for (i = 0; ; i++) { 1213 if (i >= AWI_SELFTEST_TIMEOUT*hz/1000) { 1214 printf("%s: failed to complete selftest (timeout)\n", 1215 sc->sc_dev.dv_xname); 1216 return ENXIO; 1217 } 1218 status = awi_read_1(sc, AWI_SELFTEST); 1219 if ((status & 0xf0) == 0xf0) 1220 break; 1221 if (sc->sc_cansleep) { 1222 sc->sc_sleep_cnt++; 1223 (void)tsleep(sc, PWAIT, "awitst", 1); 1224 sc->sc_sleep_cnt--; 1225 } else { 1226 DELAY(1000*1000/hz); 1227 } 1228 } 1229 if (status != AWI_SELFTEST_PASSED) { 1230 printf("%s: failed to complete selftest (code %x)\n", 1231 sc->sc_dev.dv_xname, status); 1232 return ENXIO; 1233 } 1234 1235 /* check banner to confirm firmware write it */ 1236 awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN); 1237 if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) { 1238 printf("%s: failed to complete selftest (bad banner)\n", 1239 sc->sc_dev.dv_xname); 1240 for (i = 0; i < AWI_BANNER_LEN; i++) 1241 printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]); 1242 printf("\n"); 1243 return ENXIO; 1244 } 1245 1246 /* initializing interrupt */ 1247 sc->sc_enab_intr = 1; 1248 error = awi_intr_lock(sc); 1249 if (error) 1250 return error; 1251 intmask = AWI_INT_GROGGY | AWI_INT_SCAN_CMPLT | 1252 AWI_INT_TX | AWI_INT_RX | AWI_INT_CMD; 1253 awi_write_1(sc, AWI_INTMASK, ~intmask & 0xff); 1254 awi_write_1(sc, AWI_INTMASK2, 0); 1255 awi_write_1(sc, AWI_INTSTAT, 0); 1256 awi_write_1(sc, AWI_INTSTAT2, 0); 1257 awi_intr_unlock(sc); 1258 am79c930_gcr_setbits(&sc->sc_chip, AM79C930_GCR_ENECINT); 1259 1260 /* issuing interface test command */ 1261 error = awi_cmd(sc, AWI_CMD_NOP, AWI_WAIT); 1262 if (error) { 1263 printf("%s: failed to complete selftest", sc->sc_dev.dv_xname); 1264 if (error == ENXIO) 1265 printf(" (no hardware)\n"); 1266 else if (error != EWOULDBLOCK) 1267 printf(" (error %d)\n", error); 1268 else if (sc->sc_cansleep) 1269 printf(" (lost interrupt)\n"); 1270 else 1271 printf(" (command timeout)\n"); 1272 return error; 1273 } 1274 1275 /* Initialize VBM */ 1276 awi_write_1(sc, AWI_VBM_OFFSET, 0); 1277 awi_write_1(sc, AWI_VBM_LENGTH, 1); 1278 awi_write_1(sc, AWI_VBM_BITMAP, 0); 1279 return 0; 1280 } 1281 1282 /* 1283 * Extract the factory default MIB value from firmware and assign the driver 1284 * default value. 1285 * Called once at attaching the interface. 1286 */ 1287 1288 static int 1289 awi_init_mibs(struct awi_softc *sc) 1290 { 1291 int i, error; 1292 struct awi_chanset *cs; 1293 1294 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_LOCAL, AWI_WAIT)) || 1295 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_ADDR, AWI_WAIT)) || 1296 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MAC, AWI_WAIT)) || 1297 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) || 1298 (error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_PHY, AWI_WAIT))) { 1299 printf("%s: failed to get default mib value (error %d)\n", 1300 sc->sc_dev.dv_xname, error); 1301 return error; 1302 } 1303 1304 memset(&sc->sc_ic.ic_chan_avail, 0, sizeof(sc->sc_ic.ic_chan_avail)); 1305 for (cs = awi_chanset; ; cs++) { 1306 if (cs->cs_type == 0) { 1307 printf("%s: failed to set available channel\n", 1308 sc->sc_dev.dv_xname); 1309 return ENXIO; 1310 } 1311 if (cs->cs_type == sc->sc_mib_phy.IEEE_PHY_Type && 1312 cs->cs_region == sc->sc_mib_phy.aCurrent_Reg_Domain) 1313 break; 1314 } 1315 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1316 for (i = cs->cs_min; i <= cs->cs_max; i++) { 1317 setbit(sc->sc_ic.ic_chan_avail, 1318 IEEE80211_FH_CHAN(i % 3 + 1, i)); 1319 /* 1320 * According to the IEEE 802.11 specification, 1321 * hop pattern parameter for FH phy should be 1322 * incremented by 3 for given hop chanset, i.e., 1323 * the chanset parameter is calculated for given 1324 * hop patter. However, BayStack 650 Access Points 1325 * apparently use fixed hop chanset parameter value 1326 * 1 for any hop pattern. So we also try this 1327 * combination of hop chanset and pattern. 1328 */ 1329 setbit(sc->sc_ic.ic_chan_avail, 1330 IEEE80211_FH_CHAN(1, i)); 1331 } 1332 } else { 1333 for (i = cs->cs_min; i <= cs->cs_max; i++) 1334 setbit(sc->sc_ic.ic_chan_avail, i); 1335 } 1336 sc->sc_cur_chan = cs->cs_def; 1337 1338 sc->sc_mib_local.Fragmentation_Dis = 1; 1339 sc->sc_mib_local.Add_PLCP_Dis = 0; 1340 sc->sc_mib_local.MAC_Hdr_Prsv = 1; 1341 sc->sc_mib_local.Rx_Mgmt_Que_En = 0; 1342 sc->sc_mib_local.Re_Assembly_Dis = 1; 1343 sc->sc_mib_local.Strip_PLCP_Dis = 0; 1344 sc->sc_mib_local.Power_Saving_Mode_Dis = 1; 1345 sc->sc_mib_local.Accept_All_Multicast_Dis = 1; 1346 sc->sc_mib_local.Check_Seq_Cntl_Dis = 1; 1347 sc->sc_mib_local.Flush_CFP_Queue_On_CF_End = 0; 1348 sc->sc_mib_local.Network_Mode = 1; 1349 sc->sc_mib_local.PWD_Lvl = 0; 1350 sc->sc_mib_local.CFP_Mode = 0; 1351 1352 /* allocate buffers */ 1353 sc->sc_txbase = AWI_BUFFERS; 1354 sc->sc_txend = sc->sc_txbase + 1355 (AWI_TXD_SIZE + sizeof(struct ieee80211_frame) + 1356 sizeof(struct ether_header) + ETHERMTU) * AWI_NTXBUFS; 1357 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Offset, sc->sc_txbase); 1358 LE_WRITE_4(&sc->sc_mib_local.Tx_Buffer_Size, 1359 sc->sc_txend - sc->sc_txbase); 1360 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Offset, sc->sc_txend); 1361 LE_WRITE_4(&sc->sc_mib_local.Rx_Buffer_Size, 1362 AWI_BUFFERS_END - sc->sc_txend); 1363 sc->sc_mib_local.Acting_as_AP = 0; 1364 sc->sc_mib_local.Fill_CFP = 0; 1365 1366 memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE); 1367 sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID; 1368 1369 sc->sc_mib_mgt.aPower_Mgt_Mode = 0; 1370 sc->sc_mib_mgt.aDTIM_Period = 1; 1371 LE_WRITE_2(&sc->sc_mib_mgt.aATIM_Window, 0); 1372 return 0; 1373 } 1374 1375 static int 1376 awi_chan_check(void *arg, u_char *chanreq) 1377 { 1378 struct awi_softc *sc = arg; 1379 int i; 1380 struct awi_chanset *cs; 1381 u_char chanlist[(IEEE80211_CHAN_MAX+1)/NBBY]; 1382 1383 for (cs = awi_chanset; cs->cs_type != 0; cs++) { 1384 if (cs->cs_type != sc->sc_mib_phy.IEEE_PHY_Type) 1385 continue; 1386 memset(chanlist, 0, sizeof(chanlist)); 1387 for (i = 0; ; i++) { 1388 if (i == IEEE80211_CHAN_MAX) { 1389 sc->sc_mib_phy.aCurrent_Reg_Domain = 1390 cs->cs_region; 1391 memcpy(sc->sc_ic.ic_chan_avail, chanlist, 1392 sizeof(sc->sc_ic.ic_chan_avail)); 1393 sc->sc_ic.ic_bss.ni_chan = cs->cs_def; 1394 sc->sc_cur_chan = cs->cs_def; 1395 return 0; 1396 } 1397 if (i >= cs->cs_min && i <= cs->cs_max) 1398 setbit(chanlist, i); 1399 else if (isset(chanreq, i)) 1400 break; 1401 } 1402 } 1403 return EINVAL; 1404 } 1405 1406 static int 1407 awi_mib(struct awi_softc *sc, u_int8_t cmd, u_int8_t mib, int wflag) 1408 { 1409 int error; 1410 u_int8_t size, *ptr; 1411 1412 switch (mib) { 1413 case AWI_MIB_LOCAL: 1414 ptr = (u_int8_t *)&sc->sc_mib_local; 1415 size = sizeof(sc->sc_mib_local); 1416 break; 1417 case AWI_MIB_ADDR: 1418 ptr = (u_int8_t *)&sc->sc_mib_addr; 1419 size = sizeof(sc->sc_mib_addr); 1420 break; 1421 case AWI_MIB_MAC: 1422 ptr = (u_int8_t *)&sc->sc_mib_mac; 1423 size = sizeof(sc->sc_mib_mac); 1424 break; 1425 case AWI_MIB_STAT: 1426 ptr = (u_int8_t *)&sc->sc_mib_stat; 1427 size = sizeof(sc->sc_mib_stat); 1428 break; 1429 case AWI_MIB_MGT: 1430 ptr = (u_int8_t *)&sc->sc_mib_mgt; 1431 size = sizeof(sc->sc_mib_mgt); 1432 break; 1433 case AWI_MIB_PHY: 1434 ptr = (u_int8_t *)&sc->sc_mib_phy; 1435 size = sizeof(sc->sc_mib_phy); 1436 break; 1437 default: 1438 return EINVAL; 1439 } 1440 if (sc->sc_cmd_inprog) { 1441 if ((error = awi_cmd_wait(sc)) != 0) { 1442 if (error == EWOULDBLOCK) 1443 DPRINTF(("awi_mib: cmd %d inprog", 1444 sc->sc_cmd_inprog)); 1445 return error; 1446 } 1447 } 1448 sc->sc_cmd_inprog = cmd; 1449 if (cmd == AWI_CMD_SET_MIB) 1450 awi_write_bytes(sc, AWI_CA_MIB_DATA, ptr, size); 1451 awi_write_1(sc, AWI_CA_MIB_TYPE, mib); 1452 awi_write_1(sc, AWI_CA_MIB_SIZE, size); 1453 awi_write_1(sc, AWI_CA_MIB_INDEX, 0); 1454 if ((error = awi_cmd(sc, cmd, wflag)) != 0) 1455 return error; 1456 if (cmd == AWI_CMD_GET_MIB) { 1457 awi_read_bytes(sc, AWI_CA_MIB_DATA, ptr, size); 1458 #ifdef AWI_DEBUG 1459 if (awi_debug) { 1460 int i; 1461 1462 printf("awi_mib: #%d:", mib); 1463 for (i = 0; i < size; i++) 1464 printf(" %02x", ptr[i]); 1465 printf("\n"); 1466 } 1467 #endif 1468 } 1469 return 0; 1470 } 1471 1472 static int 1473 awi_cmd(struct awi_softc *sc, u_int8_t cmd, int wflag) 1474 { 1475 u_int8_t status; 1476 int error = 0; 1477 #ifdef AWI_DEBUG 1478 static const char *cmdname[] = { 1479 "IDLE", "NOP", "SET_MIB", "INIT_TX", "FLUSH_TX", "INIT_RX", 1480 "KILL_RX", "SLEEP", "WAKE", "GET_MIB", "SCAN", "SYNC", "RESUME" 1481 }; 1482 #endif 1483 1484 #ifdef AWI_DEBUG 1485 if (awi_debug > 1) { 1486 if (cmd >= sizeof(cmdname)/sizeof(cmdname[0])) 1487 printf("awi_cmd: #%d", cmd); 1488 else 1489 printf("awi_cmd: %s", cmdname[cmd]); 1490 printf(" %s\n", wflag == AWI_NOWAIT ? "nowait" : "wait"); 1491 } 1492 #endif 1493 sc->sc_cmd_inprog = cmd; 1494 awi_write_1(sc, AWI_CMD_STATUS, AWI_STAT_IDLE); 1495 awi_write_1(sc, AWI_CMD, cmd); 1496 if (wflag == AWI_NOWAIT) 1497 return EINPROGRESS; 1498 if ((error = awi_cmd_wait(sc)) != 0) 1499 return error; 1500 status = awi_read_1(sc, AWI_CMD_STATUS); 1501 awi_write_1(sc, AWI_CMD, 0); 1502 switch (status) { 1503 case AWI_STAT_OK: 1504 break; 1505 case AWI_STAT_BADPARM: 1506 return EINVAL; 1507 default: 1508 printf("%s: command %d failed %x\n", 1509 sc->sc_dev.dv_xname, cmd, status); 1510 return ENXIO; 1511 } 1512 return 0; 1513 } 1514 1515 static int 1516 awi_cmd_wait(struct awi_softc *sc) 1517 { 1518 int i, error = 0; 1519 1520 i = 0; 1521 while (sc->sc_cmd_inprog) { 1522 if (sc->sc_invalid) 1523 return ENXIO; 1524 if (awi_read_1(sc, AWI_CMD) != sc->sc_cmd_inprog) { 1525 printf("%s: failed to access hardware\n", 1526 sc->sc_dev.dv_xname); 1527 sc->sc_invalid = 1; 1528 return ENXIO; 1529 } 1530 if (sc->sc_cansleep) { 1531 sc->sc_sleep_cnt++; 1532 error = tsleep(sc, PWAIT, "awicmd", 1533 AWI_CMD_TIMEOUT*hz/1000); 1534 sc->sc_sleep_cnt--; 1535 } else { 1536 if (awi_read_1(sc, AWI_CMD_STATUS) != AWI_STAT_IDLE) { 1537 awi_cmd_done(sc); 1538 break; 1539 } 1540 if (i++ >= AWI_CMD_TIMEOUT*1000/10) 1541 error = EWOULDBLOCK; 1542 else 1543 DELAY(10); 1544 } 1545 if (error) 1546 break; 1547 } 1548 if (error) { 1549 DPRINTF(("awi_cmd_wait: cmd 0x%x, error %d\n", 1550 sc->sc_cmd_inprog, error)); 1551 } 1552 return error; 1553 } 1554 1555 static void 1556 awi_cmd_done(struct awi_softc *sc) 1557 { 1558 u_int8_t cmd, status; 1559 1560 status = awi_read_1(sc, AWI_CMD_STATUS); 1561 if (status == AWI_STAT_IDLE) 1562 return; /* stray interrupt */ 1563 1564 cmd = sc->sc_cmd_inprog; 1565 sc->sc_cmd_inprog = 0; 1566 wakeup(sc); 1567 awi_write_1(sc, AWI_CMD, 0); 1568 1569 if (status != AWI_STAT_OK) { 1570 printf("%s: command %d failed %x\n", 1571 sc->sc_dev.dv_xname, cmd, status); 1572 sc->sc_substate = AWI_ST_NONE; 1573 return; 1574 } 1575 if (sc->sc_substate != AWI_ST_NONE) 1576 (void)ieee80211_new_state(&sc->sc_ic.ic_if, sc->sc_nstate, -1); 1577 } 1578 1579 static int 1580 awi_next_txd(struct awi_softc *sc, int len, u_int32_t *framep, u_int32_t *ntxdp) 1581 { 1582 u_int32_t txd, ntxd, frame; 1583 1584 txd = sc->sc_txnext; 1585 frame = txd + AWI_TXD_SIZE; 1586 if (frame + len > sc->sc_txend) 1587 frame = sc->sc_txbase; 1588 ntxd = frame + len; 1589 if (ntxd + AWI_TXD_SIZE > sc->sc_txend) 1590 ntxd = sc->sc_txbase; 1591 *framep = frame; 1592 *ntxdp = ntxd; 1593 /* 1594 * Determine if there are any room in ring buffer. 1595 * --- send wait, === new data, +++ conflict (ENOBUFS) 1596 * base........................end 1597 * done----txd=====ntxd OK 1598 * --txd=====done++++ntxd-- full 1599 * --txd=====ntxd done-- OK 1600 * ==ntxd done----txd=== OK 1601 * ==done++++ntxd----txd=== full 1602 * ++ntxd txd=====done++ full 1603 */ 1604 if (txd < ntxd) { 1605 if (txd < sc->sc_txdone && ntxd + AWI_TXD_SIZE > sc->sc_txdone) 1606 return ENOBUFS; 1607 } else { 1608 if (txd < sc->sc_txdone || ntxd + AWI_TXD_SIZE > sc->sc_txdone) 1609 return ENOBUFS; 1610 } 1611 return 0; 1612 } 1613 1614 static int 1615 awi_lock(struct awi_softc *sc) 1616 { 1617 int error = 0; 1618 1619 if (curproc == NULL) { 1620 /* 1621 * XXX 1622 * Though driver ioctl should be called with context, 1623 * KAME ipv6 stack calls ioctl in interrupt for now. 1624 * We simply abort the request if there are other 1625 * ioctl requests in progress. 1626 */ 1627 if (sc->sc_busy) { 1628 return EWOULDBLOCK; 1629 if (sc->sc_invalid) 1630 return ENXIO; 1631 } 1632 sc->sc_busy = 1; 1633 sc->sc_cansleep = 0; 1634 return 0; 1635 } 1636 while (sc->sc_busy) { 1637 if (sc->sc_invalid) 1638 return ENXIO; 1639 sc->sc_sleep_cnt++; 1640 error = tsleep(sc, PWAIT | PCATCH, "awilck", 0); 1641 sc->sc_sleep_cnt--; 1642 if (error) 1643 return error; 1644 } 1645 sc->sc_busy = 1; 1646 sc->sc_cansleep = 1; 1647 return 0; 1648 } 1649 1650 static void 1651 awi_unlock(struct awi_softc *sc) 1652 { 1653 sc->sc_busy = 0; 1654 sc->sc_cansleep = 0; 1655 if (sc->sc_sleep_cnt) 1656 wakeup(sc); 1657 } 1658 1659 static int 1660 awi_intr_lock(struct awi_softc *sc) 1661 { 1662 u_int8_t status; 1663 int i, retry; 1664 1665 status = 1; 1666 for (retry = 0; retry < 10; retry++) { 1667 for (i = 0; i < AWI_LOCKOUT_TIMEOUT*1000/5; i++) { 1668 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0) 1669 break; 1670 DELAY(5); 1671 } 1672 if (status != 0) 1673 break; 1674 awi_write_1(sc, AWI_LOCKOUT_MAC, 1); 1675 if ((status = awi_read_1(sc, AWI_LOCKOUT_HOST)) == 0) 1676 break; 1677 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 1678 } 1679 if (status != 0) { 1680 printf("%s: failed to lock interrupt\n", 1681 sc->sc_dev.dv_xname); 1682 return ENXIO; 1683 } 1684 return 0; 1685 } 1686 1687 static void 1688 awi_intr_unlock(struct awi_softc *sc) 1689 { 1690 1691 awi_write_1(sc, AWI_LOCKOUT_MAC, 0); 1692 } 1693 1694 static int 1695 awi_newstate(void *arg, enum ieee80211_state nstate) 1696 { 1697 struct awi_softc *sc = arg; 1698 struct ieee80211com *ic = &sc->sc_ic; 1699 struct ieee80211_node *ni; 1700 struct ifnet *ifp = &ic->ic_if; 1701 int error; 1702 u_int8_t newmode; 1703 enum ieee80211_state ostate; 1704 #ifdef AWI_DEBUG 1705 static const char *stname[] = 1706 { "INIT", "SCAN", "AUTH", "ASSOC", "RUN" }; 1707 static const char *substname[] = 1708 { "NONE", "SCAN_INIT", "SCAN_SETMIB", "SCAN_SCCMD", 1709 "SUB_INIT", "SUB_SETSS", "SUB_SYNC" }; 1710 #endif /* AWI_DEBUG */ 1711 1712 ostate = ic->ic_state; 1713 DPRINTF(("awi_newstate: %s (%s/%s) -> %s\n", stname[ostate], 1714 stname[sc->sc_nstate], substname[sc->sc_substate], stname[nstate])); 1715 1716 /* set LED */ 1717 switch (nstate) { 1718 case IEEE80211_S_INIT: 1719 awi_drvstate(sc, AWI_DRV_RESET); 1720 break; 1721 case IEEE80211_S_SCAN: 1722 if (ic->ic_opmode == IEEE80211_M_IBSS || 1723 ic->ic_opmode == IEEE80211_M_AHDEMO) 1724 awi_drvstate(sc, AWI_DRV_ADHSC); 1725 else 1726 awi_drvstate(sc, AWI_DRV_INFSY); 1727 break; 1728 case IEEE80211_S_AUTH: 1729 awi_drvstate(sc, AWI_DRV_INFSY); 1730 break; 1731 case IEEE80211_S_ASSOC: 1732 awi_drvstate(sc, AWI_DRV_INFAUTH); 1733 break; 1734 case IEEE80211_S_RUN: 1735 if (ic->ic_opmode == IEEE80211_M_IBSS || 1736 ic->ic_opmode == IEEE80211_M_AHDEMO) 1737 awi_drvstate(sc, AWI_DRV_ADHSY); 1738 else 1739 awi_drvstate(sc, AWI_DRV_INFASSOC); 1740 break; 1741 } 1742 1743 if (nstate == IEEE80211_S_INIT) { 1744 sc->sc_substate = AWI_ST_NONE; 1745 ic->ic_flags &= ~IEEE80211_F_SIBSS; 1746 return 0; 1747 } 1748 1749 /* state transition */ 1750 if (nstate == IEEE80211_S_SCAN) { 1751 /* SCAN substate */ 1752 if (sc->sc_substate == AWI_ST_NONE) { 1753 sc->sc_nstate = nstate; /* next state in transition */ 1754 sc->sc_substate = AWI_ST_SCAN_INIT; 1755 } 1756 switch (sc->sc_substate) { 1757 case AWI_ST_SCAN_INIT: 1758 sc->sc_substate = AWI_ST_SCAN_SETMIB; 1759 switch (ostate) { 1760 case IEEE80211_S_RUN: 1761 /* beacon miss */ 1762 if (ifp->if_flags & IFF_DEBUG) 1763 printf("%s: no recent beacons from %s;" 1764 " rescanning\n", 1765 ifp->if_xname, 1766 ether_sprintf(ic->ic_bss.ni_bssid)); 1767 /* FALLTHRU */ 1768 case IEEE80211_S_AUTH: 1769 case IEEE80211_S_ASSOC: 1770 /* timeout restart scan */ 1771 ieee80211_free_allnodes(ic); 1772 /* FALLTHRU */ 1773 case IEEE80211_S_INIT: 1774 ic->ic_flags |= IEEE80211_F_ASCAN; 1775 ic->ic_scan_timer = 0; 1776 /* FALLTHRU */ 1777 case IEEE80211_S_SCAN: 1778 /* scan next */ 1779 break; 1780 } 1781 if (ic->ic_flags & IEEE80211_F_ASCAN) 1782 newmode = AWI_SCAN_ACTIVE; 1783 else 1784 newmode = AWI_SCAN_PASSIVE; 1785 if (sc->sc_mib_mgt.aScan_Mode != newmode) { 1786 sc->sc_mib_mgt.aScan_Mode = newmode; 1787 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, 1788 AWI_MIB_MGT, AWI_NOWAIT)) != 0) 1789 break; 1790 } 1791 /* FALLTHRU */ 1792 case AWI_ST_SCAN_SETMIB: 1793 sc->sc_substate = AWI_ST_SCAN_SCCMD; 1794 if (sc->sc_cmd_inprog) { 1795 if ((error = awi_cmd_wait(sc)) != 0) 1796 break; 1797 } 1798 sc->sc_cmd_inprog = AWI_CMD_SCAN; 1799 ni = &ic->ic_bss; 1800 awi_write_2(sc, AWI_CA_SCAN_DURATION, 1801 (ic->ic_flags & IEEE80211_F_ASCAN) ? 1802 AWI_ASCAN_DURATION : AWI_PSCAN_DURATION); 1803 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1804 awi_write_1(sc, AWI_CA_SCAN_SET, 1805 IEEE80211_FH_CHANSET(ni->ni_chan)); 1806 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 1807 IEEE80211_FH_CHANPAT(ni->ni_chan)); 1808 awi_write_1(sc, AWI_CA_SCAN_IDX, 1); 1809 } else { 1810 awi_write_1(sc, AWI_CA_SCAN_SET, ni->ni_chan); 1811 awi_write_1(sc, AWI_CA_SCAN_PATTERN, 0); 1812 awi_write_1(sc, AWI_CA_SCAN_IDX, 0); 1813 } 1814 awi_write_1(sc, AWI_CA_SCAN_SUSP, 0); 1815 sc->sc_cur_chan = ni->ni_chan; 1816 if ((error = awi_cmd(sc, AWI_CMD_SCAN, AWI_NOWAIT)) 1817 != 0) 1818 break; 1819 /* FALLTHRU */ 1820 case AWI_ST_SCAN_SCCMD: 1821 if (ic->ic_scan_timer == 0) 1822 ic->ic_scan_timer = 1823 (ic->ic_flags & IEEE80211_F_ASCAN) ? 1824 IEEE80211_ASCAN_WAIT : IEEE80211_PSCAN_WAIT; 1825 ifp->if_timer = 1; 1826 ic->ic_state = nstate; 1827 sc->sc_substate = AWI_ST_NONE; 1828 error = EINPROGRESS; 1829 break; 1830 default: 1831 DPRINTF(("awi_newstate: unexpected state %s/%s\n", 1832 stname[nstate], substname[sc->sc_substate])); 1833 sc->sc_substate = AWI_ST_NONE; 1834 error = EIO; 1835 break; 1836 } 1837 return error; 1838 } 1839 1840 if (ostate == IEEE80211_S_SCAN) { 1841 /* set SSID and channel */ 1842 /* substate */ 1843 if (sc->sc_substate == AWI_ST_NONE) { 1844 sc->sc_nstate = nstate; /* next state in transition */ 1845 sc->sc_substate = AWI_ST_SUB_INIT; 1846 } 1847 ni = &ic->ic_bss; 1848 switch (sc->sc_substate) { 1849 case AWI_ST_SUB_INIT: 1850 sc->sc_substate = AWI_ST_SUB_SETSS; 1851 IEEE80211_ADDR_COPY(&sc->sc_mib_mgt.aCurrent_BSS_ID, 1852 ni->ni_bssid); 1853 memset(&sc->sc_mib_mgt.aCurrent_ESS_ID, 0, 1854 AWI_ESS_ID_SIZE); 1855 sc->sc_mib_mgt.aCurrent_ESS_ID[0] = 1856 IEEE80211_ELEMID_SSID; 1857 sc->sc_mib_mgt.aCurrent_ESS_ID[1] = ni->ni_esslen; 1858 memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID[2], 1859 ni->ni_essid, ni->ni_esslen); 1860 LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, 1861 ni->ni_intval); 1862 if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, 1863 AWI_NOWAIT)) != 0) 1864 break; 1865 /* FALLTHRU */ 1866 case AWI_ST_SUB_SETSS: 1867 sc->sc_substate = AWI_ST_SUB_SYNC; 1868 if (sc->sc_cmd_inprog) { 1869 if ((error = awi_cmd_wait(sc)) != 0) 1870 break; 1871 } 1872 sc->sc_cmd_inprog = AWI_CMD_SYNC; 1873 if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { 1874 awi_write_1(sc, AWI_CA_SYNC_SET, 1875 IEEE80211_FH_CHANSET(ni->ni_chan)); 1876 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 1877 IEEE80211_FH_CHANPAT(ni->ni_chan)); 1878 awi_write_1(sc, AWI_CA_SYNC_IDX, 1879 ni->ni_fhindex); 1880 awi_write_2(sc, AWI_CA_SYNC_DWELL, 1881 ni->ni_fhdwell); 1882 } else { 1883 awi_write_1(sc, AWI_CA_SYNC_SET, ni->ni_chan); 1884 awi_write_1(sc, AWI_CA_SYNC_PATTERN, 0); 1885 awi_write_1(sc, AWI_CA_SYNC_IDX, 0); 1886 awi_write_2(sc, AWI_CA_SYNC_DWELL, 0); 1887 } 1888 if (ic->ic_flags & IEEE80211_F_SIBSS) 1889 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1); 1890 else 1891 awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0); 1892 awi_write_2(sc, AWI_CA_SYNC_MBZ, 0); 1893 awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP, 1894 ni->ni_tstamp, 8); 1895 awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp); 1896 sc->sc_cur_chan = ni->ni_chan; 1897 if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT)) 1898 != 0) 1899 break; 1900 /* FALLTHRU */ 1901 case AWI_ST_SUB_SYNC: 1902 sc->sc_substate = AWI_ST_NONE; 1903 if (ic->ic_flags & IEEE80211_F_SIBSS) { 1904 if ((error = awi_mib(sc, AWI_CMD_GET_MIB, 1905 AWI_MIB_MGT, AWI_WAIT)) != 0) 1906 break; 1907 IEEE80211_ADDR_COPY(ni->ni_bssid, 1908 &sc->sc_mib_mgt.aCurrent_BSS_ID); 1909 } else { 1910 if (nstate == IEEE80211_S_RUN) { 1911 sc->sc_rx_timer = 10; 1912 ifp->if_timer = 1; 1913 } 1914 } 1915 error = 0; 1916 break; 1917 default: 1918 DPRINTF(("awi_newstate: unexpected state %s/%s\n", 1919 stname[nstate], substname[sc->sc_substate])); 1920 sc->sc_substate = AWI_ST_NONE; 1921 error = EIO; 1922 break; 1923 } 1924 return error; 1925 } 1926 1927 sc->sc_substate = AWI_ST_NONE; 1928 1929 return 0; 1930 } 1931 1932 static struct mbuf * 1933 awi_ether_encap(struct awi_softc *sc, struct mbuf *m) 1934 { 1935 struct ieee80211com *ic = &sc->sc_ic; 1936 struct ieee80211_node *ni = &ic->ic_bss; 1937 struct ether_header *eh; 1938 struct ieee80211_frame *wh; 1939 1940 if (m->m_len < sizeof(struct ether_header)) { 1941 m = m_pullup(m, sizeof(struct ether_header)); 1942 if (m == NULL) 1943 return NULL; 1944 } 1945 eh = mtod(m, struct ether_header *); 1946 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); 1947 if (m == NULL) 1948 return NULL; 1949 wh = mtod(m, struct ieee80211_frame *); 1950 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; 1951 *(u_int16_t *)wh->i_dur = 0; 1952 *(u_int16_t *)wh->i_seq = 1953 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); 1954 ni->ni_txseq++; 1955 if (ic->ic_opmode == IEEE80211_M_IBSS || 1956 ic->ic_opmode == IEEE80211_M_AHDEMO) { 1957 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 1958 if (sc->sc_adhoc_ap) 1959 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); 1960 else 1961 IEEE80211_ADDR_COPY(wh->i_addr1, eh->ether_dhost); 1962 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost); 1963 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); 1964 } else { 1965 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; 1966 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid); 1967 IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost); 1968 IEEE80211_ADDR_COPY(wh->i_addr3, eh->ether_dhost); 1969 } 1970 return m; 1971 } 1972 1973 static struct mbuf * 1974 awi_ether_modcap(struct awi_softc *sc, struct mbuf *m) 1975 { 1976 struct ieee80211com *ic = &sc->sc_ic; 1977 struct ether_header eh; 1978 struct ieee80211_frame wh; 1979 struct llc *llc; 1980 1981 if (m->m_len < sizeof(wh) + sizeof(eh)) { 1982 m = m_pullup(m, sizeof(wh) + sizeof(eh)); 1983 if (m == NULL) 1984 return NULL; 1985 } 1986 memcpy(&wh, mtod(m, caddr_t), sizeof(wh)); 1987 if (wh.i_fc[0] != (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA)) 1988 return m; 1989 memcpy(&eh, mtod(m, caddr_t) + sizeof(wh), sizeof(eh)); 1990 m_adj(m, sizeof(eh) - sizeof(*llc)); 1991 if (ic->ic_opmode == IEEE80211_M_IBSS || 1992 ic->ic_opmode == IEEE80211_M_AHDEMO) 1993 IEEE80211_ADDR_COPY(wh.i_addr2, eh.ether_shost); 1994 memcpy(mtod(m, caddr_t), &wh, sizeof(wh)); 1995 llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); 1996 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 1997 llc->llc_control = LLC_UI; 1998 llc->llc_snap.org_code[0] = 0; 1999 llc->llc_snap.org_code[1] = 0; 2000 llc->llc_snap.org_code[2] = 0; 2001 llc->llc_snap.ether_type = eh.ether_type; 2002 return m; 2003 } 2004