1 /* $NetBSD: an.c,v 1.38 2005/12/11 12:21:25 christos Exp $ */ 2 /* 3 * Copyright (c) 1997, 1998, 1999 4 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Bill Paul. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD: src/sys/dev/an/if_an.c,v 1.12 2000/11/13 23:04:12 wpaul Exp $ 34 */ 35 /* 36 * Copyright (c) 2004, 2005 David Young. All rights reserved. 37 * Copyright (c) 2004, 2005 OJC Technologies. All rights reserved. 38 * Copyright (c) 2004, 2005 Dayton Data Center Services, LLC. All 39 * rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the author nor the names of any co-contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY David Young AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL David Young AND CONTRIBUTORS 57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 63 * THE POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 /* 67 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD. 68 * 69 * Written by Bill Paul <wpaul@ctr.columbia.edu> 70 * Electrical Engineering Department 71 * Columbia University, New York City 72 */ 73 74 /* 75 * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego 76 * IETF meeting. 77 */ 78 79 #include <sys/cdefs.h> 80 __KERNEL_RCSID(0, "$NetBSD: an.c,v 1.38 2005/12/11 12:21:25 christos Exp $"); 81 82 #include "bpfilter.h" 83 84 #include <sys/param.h> 85 #include <sys/callout.h> 86 #include <sys/sysctl.h> 87 #include <sys/systm.h> 88 #include <sys/sockio.h> 89 #include <sys/mbuf.h> 90 #include <sys/kernel.h> 91 #include <sys/ucred.h> 92 #include <sys/socket.h> 93 #include <sys/device.h> 94 #include <sys/proc.h> 95 #include <sys/md4.h> 96 #include <sys/endian.h> 97 98 #include <machine/bus.h> 99 100 #include <net/if.h> 101 #include <net/if_dl.h> 102 #include <net/if_ether.h> 103 #include <net/if_llc.h> 104 #include <net/if_media.h> 105 #include <net/if_types.h> 106 107 #include <net80211/ieee80211_netbsd.h> 108 #include <net80211/ieee80211_var.h> 109 110 #if NBPFILTER > 0 111 #include <net/bpf.h> 112 #endif 113 114 #include <dev/ic/anreg.h> 115 #include <dev/ic/anvar.h> 116 117 static int an_reset(struct an_softc *); 118 static void an_wait(struct an_softc *); 119 static int an_init(struct ifnet *); 120 static void an_stop(struct ifnet *, int); 121 static void an_start(struct ifnet *); 122 static void an_watchdog(struct ifnet *); 123 static int an_ioctl(struct ifnet *, u_long, caddr_t); 124 static int an_media_change(struct ifnet *); 125 static void an_media_status(struct ifnet *, struct ifmediareq *); 126 127 static int an_set_nwkey(struct an_softc *, struct ieee80211_nwkey *); 128 static int an_set_nwkey_wep(struct an_softc *, struct ieee80211_nwkey *); 129 static int an_set_nwkey_eap(struct an_softc *, struct ieee80211_nwkey *); 130 static int an_get_nwkey(struct an_softc *, struct ieee80211_nwkey *); 131 static int an_write_wepkey(struct an_softc *, int, struct an_wepkey *, 132 int); 133 134 static void an_rx_intr(struct an_softc *); 135 static void an_tx_intr(struct an_softc *, int); 136 static void an_linkstat_intr(struct an_softc *); 137 138 static int an_cmd(struct an_softc *, int, int); 139 static int an_seek_bap(struct an_softc *, int, int); 140 static int an_read_bap(struct an_softc *, int, int, void *, int); 141 static int an_write_bap(struct an_softc *, int, int, void *, int); 142 static int an_mwrite_bap(struct an_softc *, int, int, struct mbuf *, int); 143 static int an_read_rid(struct an_softc *, int, void *, int *); 144 static int an_write_rid(struct an_softc *, int, void *, int); 145 146 static int an_alloc_fid(struct an_softc *, int, int *); 147 148 static int an_newstate(struct ieee80211com *, enum ieee80211_state, int); 149 150 #ifdef AN_DEBUG 151 int an_debug = 0; 152 153 #define DPRINTF(X) if (an_debug) printf X 154 #define DPRINTF2(X) if (an_debug > 1) printf X 155 static int an_sysctl_verify(SYSCTLFN_PROTO, int lower, int upper); 156 static int an_sysctl_verify_debug(SYSCTLFN_PROTO); 157 #else 158 #define DPRINTF(X) 159 #define DPRINTF2(X) 160 #endif 161 162 int 163 an_attach(struct an_softc *sc) 164 { 165 struct ieee80211com *ic = &sc->sc_ic; 166 struct ifnet *ifp = &sc->sc_if; 167 int i, s; 168 struct an_rid_wepkey *akey; 169 int buflen, kid, rid; 170 int chan, chan_min, chan_max; 171 172 s = splnet(); 173 sc->sc_invalid = 0; 174 175 an_wait(sc); 176 if (an_reset(sc) != 0) { 177 sc->sc_invalid = 1; 178 splx(s); 179 return 1; 180 } 181 182 /* Load factory config */ 183 if (an_cmd(sc, AN_CMD_READCFG, 0) != 0) { 184 splx(s); 185 aprint_error("%s: failed to load config data\n", 186 sc->sc_dev.dv_xname); 187 return 1; 188 } 189 190 /* Read the current configuration */ 191 buflen = sizeof(sc->sc_config); 192 if (an_read_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, &buflen) != 0) { 193 splx(s); 194 aprint_error("%s: read config failed\n", sc->sc_dev.dv_xname); 195 return 1; 196 } 197 198 /* Read the card capabilities */ 199 buflen = sizeof(sc->sc_caps); 200 if (an_read_rid(sc, AN_RID_CAPABILITIES, &sc->sc_caps, &buflen) != 0) { 201 splx(s); 202 aprint_error("%s: read caps failed\n", sc->sc_dev.dv_xname); 203 return 1; 204 } 205 206 #ifdef AN_DEBUG 207 if (an_debug) { 208 static const int dumprid[] = { 209 AN_RID_GENCONFIG, AN_RID_CAPABILITIES, AN_RID_SSIDLIST, 210 AN_RID_APLIST, AN_RID_STATUS, AN_RID_ENCAP 211 }; 212 213 for (rid = 0; rid < sizeof(dumprid)/sizeof(dumprid[0]); rid++) { 214 buflen = sizeof(sc->sc_buf); 215 if (an_read_rid(sc, dumprid[rid], &sc->sc_buf, &buflen) 216 != 0) 217 continue; 218 printf("%04x (%d):\n", dumprid[rid], buflen); 219 for (i = 0; i < (buflen + 1) / 2; i++) 220 printf(" %04x", sc->sc_buf.sc_val[i]); 221 printf("\n"); 222 } 223 } 224 #endif 225 226 /* Read WEP settings from persistent memory */ 227 akey = &sc->sc_buf.sc_wepkey; 228 buflen = sizeof(struct an_rid_wepkey); 229 rid = AN_RID_WEP_VOLATILE; /* first persistent key */ 230 while (an_read_rid(sc, rid, akey, &buflen) == 0) { 231 kid = le16toh(akey->an_key_index); 232 DPRINTF(("an_attach: wep rid=0x%x len=%d(%d) index=0x%04x " 233 "mac[0]=%02x keylen=%d\n", 234 rid, buflen, sizeof(*akey), kid, 235 akey->an_mac_addr[0], le16toh(akey->an_key_len))); 236 if (kid == 0xffff) { 237 sc->sc_tx_perskey = akey->an_mac_addr[0]; 238 sc->sc_tx_key = -1; 239 break; 240 } 241 if (kid >= IEEE80211_WEP_NKID) 242 break; 243 sc->sc_perskeylen[kid] = le16toh(akey->an_key_len); 244 sc->sc_wepkeys[kid].an_wep_keylen = -1; 245 rid = AN_RID_WEP_PERSISTENT; /* for next key */ 246 buflen = sizeof(struct an_rid_wepkey); 247 } 248 249 aprint_normal("%s: %s %s (firmware %s)\n", sc->sc_dev.dv_xname, 250 sc->sc_caps.an_manufname, sc->sc_caps.an_prodname, 251 sc->sc_caps.an_prodvers); 252 253 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 254 255 ifp->if_softc = sc; 256 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX | 257 IFF_MULTICAST | IFF_ALLMULTI; 258 ifp->if_ioctl = an_ioctl; 259 ifp->if_start = an_start; 260 ifp->if_init = an_init; 261 ifp->if_stop = an_stop; 262 ifp->if_watchdog = an_watchdog; 263 IFQ_SET_READY(&ifp->if_snd); 264 265 ic->ic_ifp = ifp; 266 ic->ic_phytype = IEEE80211_T_DS; 267 ic->ic_opmode = IEEE80211_M_STA; 268 ic->ic_caps = IEEE80211_C_WEP | IEEE80211_C_PMGT | IEEE80211_C_IBSS | 269 IEEE80211_C_MONITOR; 270 ic->ic_state = IEEE80211_S_INIT; 271 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_caps.an_oemaddr); 272 273 switch (le16toh(sc->sc_caps.an_regdomain)) { 274 default: 275 case AN_REGDOMAIN_USA: 276 case AN_REGDOMAIN_CANADA: 277 chan_min = 1; chan_max = 11; break; 278 case AN_REGDOMAIN_EUROPE: 279 case AN_REGDOMAIN_AUSTRALIA: 280 chan_min = 1; chan_max = 13; break; 281 case AN_REGDOMAIN_JAPAN: 282 chan_min = 14; chan_max = 14; break; 283 case AN_REGDOMAIN_SPAIN: 284 chan_min = 10; chan_max = 11; break; 285 case AN_REGDOMAIN_FRANCE: 286 chan_min = 10; chan_max = 13; break; 287 case AN_REGDOMAIN_JAPANWIDE: 288 chan_min = 1; chan_max = 14; break; 289 } 290 291 for (chan = chan_min; chan <= chan_max; chan++) { 292 ic->ic_channels[chan].ic_freq = 293 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ); 294 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B; 295 } 296 ic->ic_ibss_chan = &ic->ic_channels[chan_min]; 297 298 aprint_normal("%s: 802.11 address: %s, channel: %d-%d\n", 299 ifp->if_xname, ether_sprintf(ic->ic_myaddr), chan_min, chan_max); 300 301 /* Find supported rate */ 302 for (i = 0; i < sizeof(sc->sc_caps.an_rates); i++) { 303 if (sc->sc_caps.an_rates[i] == 0) 304 continue; 305 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ 306 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates++] = 307 sc->sc_caps.an_rates[i]; 308 } 309 310 /* 311 * Call MI attach routine. 312 */ 313 if_attach(ifp); 314 ieee80211_ifattach(ic); 315 316 sc->sc_newstate = ic->ic_newstate; 317 ic->ic_newstate = an_newstate; 318 319 ieee80211_media_init(ic, an_media_change, an_media_status); 320 sc->sc_attached = 1; 321 splx(s); 322 323 ieee80211_announce(ic); 324 return 0; 325 } 326 327 #ifdef AN_DEBUG 328 /* 329 * Setup sysctl(3) MIB, hw.an.* 330 * 331 * TBD condition CTLFLAG_PERMANENT on being an LKM or not 332 */ 333 SYSCTL_SETUP(sysctl_an, "sysctl an(4) subtree setup") 334 { 335 int rc; 336 const struct sysctlnode *cnode, *rnode; 337 338 if ((rc = sysctl_createv(clog, 0, NULL, &rnode, 339 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, 340 NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) 341 goto err; 342 343 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 344 CTLFLAG_PERMANENT, CTLTYPE_NODE, "an", 345 "Cisco/Aironet 802.11 controls", 346 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 347 goto err; 348 349 /* control debugging printfs */ 350 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 351 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 352 "debug", SYSCTL_DESCR("Enable Cisco/Aironet debugging output"), 353 an_sysctl_verify_debug, 0, &an_debug, 0, 354 CTL_CREATE, CTL_EOL)) != 0) 355 goto err; 356 357 return; 358 err: 359 printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 360 } 361 362 static int 363 an_sysctl_verify(SYSCTLFN_ARGS, int lower, int upper) 364 { 365 int error, t; 366 struct sysctlnode node; 367 368 node = *rnode; 369 t = *(int*)rnode->sysctl_data; 370 node.sysctl_data = &t; 371 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 372 if (error || newp == NULL) 373 return (error); 374 375 if (t < lower || t > upper) 376 return (EINVAL); 377 378 *(int*)rnode->sysctl_data = t; 379 380 return (0); 381 } 382 383 static int 384 an_sysctl_verify_debug(SYSCTLFN_ARGS) 385 { 386 return an_sysctl_verify(SYSCTLFN_CALL(rnode), 0, 2); 387 } 388 #endif /* AN_DEBUG */ 389 390 int 391 an_detach(struct an_softc *sc) 392 { 393 struct ieee80211com *ic = &sc->sc_ic; 394 struct ifnet *ifp = &sc->sc_if; 395 int s; 396 397 if (!sc->sc_attached) 398 return 0; 399 400 s = splnet(); 401 sc->sc_invalid = 1; 402 an_stop(ifp, 1); 403 ieee80211_ifdetach(ic); 404 if_detach(ifp); 405 splx(s); 406 return 0; 407 } 408 409 int 410 an_activate(struct device *self, enum devact act) 411 { 412 struct an_softc *sc = (struct an_softc *)self; 413 int s, error = 0; 414 415 s = splnet(); 416 switch (act) { 417 case DVACT_ACTIVATE: 418 error = EOPNOTSUPP; 419 break; 420 421 case DVACT_DEACTIVATE: 422 sc->sc_invalid = 1; 423 if_deactivate(&sc->sc_if); 424 break; 425 } 426 splx(s); 427 428 return error; 429 } 430 431 void 432 an_power(int why, void *arg) 433 { 434 int s; 435 struct an_softc *sc = arg; 436 struct ifnet *ifp = &sc->sc_if; 437 438 s = splnet(); 439 switch (why) { 440 case PWR_SUSPEND: 441 case PWR_STANDBY: 442 an_stop(ifp, 1); 443 break; 444 case PWR_RESUME: 445 if (ifp->if_flags & IFF_UP) { 446 an_init(ifp); 447 (void)an_intr(sc); 448 } 449 break; 450 case PWR_SOFTSUSPEND: 451 case PWR_SOFTSTANDBY: 452 case PWR_SOFTRESUME: 453 break; 454 } 455 splx(s); 456 } 457 458 void 459 an_shutdown(struct an_softc *sc) 460 { 461 462 if (sc->sc_attached) 463 an_stop(&sc->sc_if, 1); 464 } 465 466 int 467 an_intr(void *arg) 468 { 469 struct an_softc *sc = arg; 470 struct ifnet *ifp = &sc->sc_if; 471 int i; 472 u_int16_t status; 473 474 if (!sc->sc_enabled || sc->sc_invalid || 475 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || 476 (ifp->if_flags & IFF_RUNNING) == 0) 477 return 0; 478 479 if ((ifp->if_flags & IFF_UP) == 0) { 480 CSR_WRITE_2(sc, AN_INT_EN, 0); 481 CSR_WRITE_2(sc, AN_EVENT_ACK, ~0); 482 return 1; 483 } 484 485 /* maximum 10 loops per interrupt */ 486 for (i = 0; i < 10; i++) { 487 if (!sc->sc_enabled || sc->sc_invalid) 488 return 1; 489 if (CSR_READ_2(sc, AN_SW0) != AN_MAGIC) { 490 DPRINTF(("an_intr: magic number changed: %x\n", 491 CSR_READ_2(sc, AN_SW0))); 492 sc->sc_invalid = 1; 493 return 1; 494 } 495 status = CSR_READ_2(sc, AN_EVENT_STAT); 496 CSR_WRITE_2(sc, AN_EVENT_ACK, status & ~(AN_INTRS)); 497 if ((status & AN_INTRS) == 0) 498 break; 499 500 if (status & AN_EV_RX) 501 an_rx_intr(sc); 502 503 if (status & (AN_EV_TX | AN_EV_TX_EXC)) 504 an_tx_intr(sc, status); 505 506 if (status & AN_EV_LINKSTAT) 507 an_linkstat_intr(sc); 508 509 if ((ifp->if_flags & IFF_OACTIVE) == 0 && 510 sc->sc_ic.ic_state == IEEE80211_S_RUN && 511 !IFQ_IS_EMPTY(&ifp->if_snd)) 512 an_start(ifp); 513 } 514 515 return 1; 516 } 517 518 static int 519 an_init(struct ifnet *ifp) 520 { 521 struct an_softc *sc = ifp->if_softc; 522 struct ieee80211com *ic = &sc->sc_ic; 523 int i, error, fid; 524 525 DPRINTF(("an_init: enabled %d\n", sc->sc_enabled)); 526 if (!sc->sc_enabled) { 527 if (sc->sc_enable) 528 (*sc->sc_enable)(sc); 529 an_wait(sc); 530 sc->sc_enabled = 1; 531 } else { 532 an_stop(ifp, 0); 533 if ((error = an_reset(sc)) != 0) { 534 printf("%s: failed to reset\n", ifp->if_xname); 535 an_stop(ifp, 1); 536 return error; 537 } 538 } 539 CSR_WRITE_2(sc, AN_SW0, AN_MAGIC); 540 541 /* Allocate the TX buffers */ 542 for (i = 0; i < AN_TX_RING_CNT; i++) { 543 if ((error = an_alloc_fid(sc, AN_TX_MAX_LEN, &fid)) != 0) { 544 printf("%s: failed to allocate nic memory\n", 545 ifp->if_xname); 546 an_stop(ifp, 1); 547 return error; 548 } 549 DPRINTF2(("an_init: txbuf %d allocated %x\n", i, fid)); 550 sc->sc_txd[i].d_fid = fid; 551 sc->sc_txd[i].d_inuse = 0; 552 } 553 sc->sc_txcur = sc->sc_txnext = 0; 554 555 IEEE80211_ADDR_COPY(sc->sc_config.an_macaddr, ic->ic_myaddr); 556 sc->sc_config.an_scanmode = htole16(AN_SCANMODE_ACTIVE); 557 sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_OPEN); /*XXX*/ 558 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 559 sc->sc_config.an_authtype |= 560 htole16(AN_AUTHTYPE_PRIVACY_IN_USE); 561 if (sc->sc_use_leap) 562 sc->sc_config.an_authtype |= 563 htole16(AN_AUTHTYPE_LEAP); 564 } 565 sc->sc_config.an_listen_interval = htole16(ic->ic_lintval); 566 sc->sc_config.an_beacon_period = htole16(ic->ic_lintval); 567 if (ic->ic_flags & IEEE80211_F_PMGTON) 568 sc->sc_config.an_psave_mode = htole16(AN_PSAVE_PSP); 569 else 570 sc->sc_config.an_psave_mode = htole16(AN_PSAVE_CAM); 571 sc->sc_config.an_ds_channel = 572 htole16(ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 573 574 switch (ic->ic_opmode) { 575 case IEEE80211_M_STA: 576 sc->sc_config.an_opmode = 577 htole16(AN_OPMODE_INFRASTRUCTURE_STATION); 578 sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR); 579 break; 580 case IEEE80211_M_IBSS: 581 sc->sc_config.an_opmode = htole16(AN_OPMODE_IBSS_ADHOC); 582 sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR); 583 break; 584 case IEEE80211_M_MONITOR: 585 sc->sc_config.an_opmode = 586 htole16(AN_OPMODE_INFRASTRUCTURE_STATION); 587 sc->sc_config.an_rxmode = 588 htole16(AN_RXMODE_80211_MONITOR_ANYBSS); 589 sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_NONE); 590 if (ic->ic_flags & IEEE80211_F_PRIVACY) 591 sc->sc_config.an_authtype |= 592 htole16(AN_AUTHTYPE_PRIVACY_IN_USE | 593 AN_AUTHTYPE_ALLOW_UNENCRYPTED); 594 break; 595 default: 596 printf("%s: bad opmode %d\n", ifp->if_xname, ic->ic_opmode); 597 an_stop(ifp, 1); 598 return EIO; 599 } 600 sc->sc_config.an_rxmode |= htole16(AN_RXMODE_NO_8023_HEADER); 601 602 /* Set the ssid list */ 603 memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_ssidlist)); 604 sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid_len = 605 htole16(ic->ic_des_esslen); 606 if (ic->ic_des_esslen) 607 memcpy(sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid, 608 ic->ic_des_essid, ic->ic_des_esslen); 609 if (an_write_rid(sc, AN_RID_SSIDLIST, &sc->sc_buf, 610 sizeof(sc->sc_buf.sc_ssidlist)) != 0) { 611 printf("%s: failed to write ssid list\n", ifp->if_xname); 612 an_stop(ifp, 1); 613 return error; 614 } 615 616 /* Set the AP list */ 617 memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_aplist)); 618 (void)an_write_rid(sc, AN_RID_APLIST, &sc->sc_buf, 619 sizeof(sc->sc_buf.sc_aplist)); 620 621 /* Set the encapsulation */ 622 for (i = 0; i < AN_ENCAP_NENTS; i++) { 623 sc->sc_buf.sc_encap.an_entry[i].an_ethertype = htole16(0); 624 sc->sc_buf.sc_encap.an_entry[i].an_action = 625 htole16(AN_RXENCAP_RFC1024 | AN_TXENCAP_RFC1024); 626 } 627 (void)an_write_rid(sc, AN_RID_ENCAP, &sc->sc_buf, 628 sizeof(sc->sc_buf.sc_encap)); 629 630 /* Set the WEP Keys */ 631 if (ic->ic_flags & IEEE80211_F_PRIVACY) 632 an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->sc_wepkeys, 633 sc->sc_tx_key); 634 635 /* Set the configuration */ 636 #ifdef AN_DEBUG 637 if (an_debug) { 638 printf("write config:\n"); 639 for (i = 0; i < sizeof(sc->sc_config) / 2; i++) 640 printf(" %04x", ((u_int16_t *)&sc->sc_config)[i]); 641 printf("\n"); 642 } 643 #endif 644 if (an_write_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, 645 sizeof(sc->sc_config)) != 0) { 646 printf("%s: failed to write config\n", ifp->if_xname); 647 an_stop(ifp, 1); 648 return error; 649 } 650 651 /* Enable the MAC */ 652 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 653 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname); 654 an_stop(ifp, 1); 655 return ENXIO; 656 } 657 if (ifp->if_flags & IFF_PROMISC) 658 an_cmd(sc, AN_CMD_SET_MODE, 0xffff); 659 660 ifp->if_flags |= IFF_RUNNING; 661 ifp->if_flags &= ~IFF_OACTIVE; 662 ic->ic_state = IEEE80211_S_INIT; 663 if (ic->ic_opmode == IEEE80211_M_MONITOR) 664 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 665 666 /* enable interrupts */ 667 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 668 return 0; 669 } 670 671 static void 672 an_stop(struct ifnet *ifp, int disable) 673 { 674 struct an_softc *sc = ifp->if_softc; 675 int i, s; 676 677 if (!sc->sc_enabled) 678 return; 679 680 DPRINTF(("an_stop: disable %d\n", disable)); 681 682 s = splnet(); 683 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 684 if (!sc->sc_invalid) { 685 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 686 CSR_WRITE_2(sc, AN_INT_EN, 0); 687 an_cmd(sc, AN_CMD_DISABLE, 0); 688 689 for (i = 0; i < AN_TX_RING_CNT; i++) 690 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->sc_txd[i].d_fid); 691 } 692 693 sc->sc_tx_timer = 0; 694 ifp->if_timer = 0; 695 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 696 697 if (disable) { 698 if (sc->sc_disable) 699 (*sc->sc_disable)(sc); 700 sc->sc_enabled = 0; 701 } 702 splx(s); 703 } 704 705 static void 706 an_start(struct ifnet *ifp) 707 { 708 struct an_softc *sc = (struct an_softc *)ifp->if_softc; 709 struct ieee80211com *ic = &sc->sc_ic; 710 struct ieee80211_node *ni; 711 struct ieee80211_frame *wh; 712 struct an_txframe frmhdr; 713 struct ether_header *eh; 714 struct mbuf *m; 715 u_int16_t len; 716 int cur, fid; 717 718 if (!sc->sc_enabled || sc->sc_invalid) { 719 DPRINTF(("an_start: noop: enabled %d invalid %d\n", 720 sc->sc_enabled, sc->sc_invalid)); 721 return; 722 } 723 724 memset(&frmhdr, 0, sizeof(frmhdr)); 725 cur = sc->sc_txnext; 726 for (;;) { 727 if (ic->ic_state != IEEE80211_S_RUN) { 728 DPRINTF(("an_start: not running %d\n", ic->ic_state)); 729 break; 730 } 731 IFQ_POLL(&ifp->if_snd, m); 732 if (m == NULL) { 733 DPRINTF2(("an_start: no pending mbuf\n")); 734 break; 735 } 736 if (sc->sc_txd[cur].d_inuse) { 737 DPRINTF2(("an_start: %x/%d busy\n", 738 sc->sc_txd[cur].d_fid, cur)); 739 ifp->if_flags |= IFF_OACTIVE; 740 break; 741 } 742 IFQ_DEQUEUE(&ifp->if_snd, m); 743 ifp->if_opackets++; 744 #if NBPFILTER > 0 745 if (ifp->if_bpf) 746 bpf_mtap(ifp->if_bpf, m); 747 #endif 748 eh = mtod(m, struct ether_header *); 749 ni = ieee80211_find_txnode(ic, eh->ether_dhost); 750 if (ni == NULL) { 751 /* NB: ieee80211_find_txnode does stat+msg */ 752 goto bad; 753 } 754 if ((m = ieee80211_encap(ic, m, ni)) == NULL) 755 goto bad; 756 ieee80211_free_node(ni); 757 #if NBPFILTER > 0 758 if (ic->ic_rawbpf) 759 bpf_mtap(ic->ic_rawbpf, m); 760 #endif 761 762 wh = mtod(m, struct ieee80211_frame *); 763 if (ic->ic_flags & IEEE80211_F_PRIVACY) 764 wh->i_fc[1] |= IEEE80211_FC1_WEP; 765 m_copydata(m, 0, sizeof(struct ieee80211_frame), 766 (caddr_t)&frmhdr.an_whdr); 767 768 /* insert payload length in front of llc/snap */ 769 len = htons(m->m_pkthdr.len - sizeof(struct ieee80211_frame)); 770 m_adj(m, sizeof(struct ieee80211_frame) - sizeof(len)); 771 if (mtod(m, u_long) & 0x01) 772 memcpy(mtod(m, caddr_t), &len, sizeof(len)); 773 else 774 *mtod(m, u_int16_t *) = len; 775 776 /* 777 * XXX Aironet firmware apparently convert the packet 778 * with longer than 1500 bytes in length into LLC/SNAP. 779 * If we have 1500 bytes in ethernet payload, it is 780 * 1508 bytes including LLC/SNAP and will be inserted 781 * additional LLC/SNAP header with 1501-1508 in its 782 * ethertype !! 783 * So we skip LLC/SNAP header and force firmware to 784 * convert it to LLC/SNAP again. 785 */ 786 m_adj(m, sizeof(struct llc)); 787 788 frmhdr.an_tx_ctl = htole16(AN_TXCTL_80211); 789 frmhdr.an_tx_payload_len = htole16(m->m_pkthdr.len); 790 frmhdr.an_gaplen = htole16(AN_TXGAP_802_11); 791 792 if (ic->ic_fixed_rate != -1) 793 frmhdr.an_tx_rate = 794 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ 795 ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 796 else 797 frmhdr.an_tx_rate = 0; 798 799 #ifdef AN_DEBUG 800 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == 801 (IFF_DEBUG|IFF_LINK2)) { 802 ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr, 803 sizeof(struct ieee80211_frame), -1, 0); 804 printf(" txctl 0x%x plen %u\n", 805 le16toh(frmhdr.an_tx_ctl), 806 le16toh(frmhdr.an_tx_payload_len)); 807 } 808 #endif 809 if (sizeof(frmhdr) + AN_TXGAP_802_11 + sizeof(len) + 810 m->m_pkthdr.len > AN_TX_MAX_LEN) 811 goto bad; 812 813 fid = sc->sc_txd[cur].d_fid; 814 if (an_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) 815 goto bad; 816 /* dummy write to avoid seek. */ 817 an_write_bap(sc, fid, -1, &frmhdr, AN_TXGAP_802_11); 818 an_mwrite_bap(sc, fid, -1, m, m->m_pkthdr.len); 819 m_freem(m); 820 821 DPRINTF2(("an_start: send %d byte via %x/%d\n", 822 ntohs(len) + sizeof(struct ieee80211_frame), 823 fid, cur)); 824 sc->sc_txd[cur].d_inuse = 1; 825 if (an_cmd(sc, AN_CMD_TX, fid)) { 826 printf("%s: xmit failed\n", ifp->if_xname); 827 sc->sc_txd[cur].d_inuse = 0; 828 continue; 829 } 830 sc->sc_tx_timer = 5; 831 ifp->if_timer = 1; 832 AN_INC(cur, AN_TX_RING_CNT); 833 sc->sc_txnext = cur; 834 continue; 835 bad: 836 ifp->if_oerrors++; 837 m_freem(m); 838 } 839 } 840 841 static int 842 an_reset(struct an_softc *sc) 843 { 844 845 DPRINTF(("an_reset\n")); 846 847 if (!sc->sc_enabled) 848 return ENXIO; 849 850 an_cmd(sc, AN_CMD_ENABLE, 0); 851 an_cmd(sc, AN_CMD_FW_RESTART, 0); 852 an_cmd(sc, AN_CMD_NOOP2, 0); 853 854 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) { 855 printf("%s: reset failed\n", sc->sc_dev.dv_xname); 856 return ETIMEDOUT; 857 } 858 859 an_cmd(sc, AN_CMD_DISABLE, 0); 860 return 0; 861 } 862 863 static void 864 an_watchdog(struct ifnet *ifp) 865 { 866 struct an_softc *sc = ifp->if_softc; 867 868 if (!sc->sc_enabled) 869 return; 870 871 if (sc->sc_tx_timer) { 872 if (--sc->sc_tx_timer == 0) { 873 printf("%s: device timeout\n", ifp->if_xname); 874 ifp->if_oerrors++; 875 an_init(ifp); 876 return; 877 } 878 ifp->if_timer = 1; 879 } 880 ieee80211_watchdog(&sc->sc_ic); 881 } 882 883 static int 884 an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 885 { 886 struct an_softc *sc = ifp->if_softc; 887 int s, error = 0; 888 889 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) 890 return ENXIO; 891 892 s = splnet(); 893 894 switch (command) { 895 case SIOCSIFFLAGS: 896 if (ifp->if_flags & IFF_UP) { 897 if (sc->sc_enabled) { 898 /* 899 * To avoid rescanning another access point, 900 * do not call an_init() here. Instead, only 901 * reflect promisc mode settings. 902 */ 903 error = an_cmd(sc, AN_CMD_SET_MODE, 904 (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0); 905 } else 906 error = an_init(ifp); 907 } else if (sc->sc_enabled) 908 an_stop(ifp, 1); 909 break; 910 case SIOCADDMULTI: 911 case SIOCDELMULTI: 912 error = ether_ioctl(ifp, command, data); 913 if (error == ENETRESET) { 914 /* we don't have multicast filter. */ 915 error = 0; 916 } 917 break; 918 case SIOCS80211NWKEY: 919 error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data); 920 break; 921 case SIOCG80211NWKEY: 922 error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data); 923 break; 924 default: 925 error = ieee80211_ioctl(&sc->sc_ic, command, data); 926 break; 927 } 928 if (error == ENETRESET) { 929 if (sc->sc_enabled) 930 error = an_init(ifp); 931 else 932 error = 0; 933 } 934 splx(s); 935 return error; 936 } 937 938 /* TBD factor with ieee80211_media_change */ 939 static int 940 an_media_change(struct ifnet *ifp) 941 { 942 struct an_softc *sc = ifp->if_softc; 943 struct ieee80211com *ic = &sc->sc_ic; 944 struct ifmedia_entry *ime; 945 enum ieee80211_opmode newmode; 946 int i, rate, error = 0; 947 948 ime = ic->ic_media.ifm_cur; 949 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { 950 i = -1; 951 } else { 952 struct ieee80211_rateset *rs = 953 &ic->ic_sup_rates[IEEE80211_MODE_11B]; 954 rate = ieee80211_media2rate(ime->ifm_media); 955 if (rate == 0) 956 return EINVAL; 957 for (i = 0; i < rs->rs_nrates; i++) { 958 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate) 959 break; 960 } 961 if (i == rs->rs_nrates) 962 return EINVAL; 963 } 964 if (ic->ic_fixed_rate != i) { 965 ic->ic_fixed_rate = i; 966 error = ENETRESET; 967 } 968 969 if (ime->ifm_media & IFM_IEEE80211_ADHOC) 970 newmode = IEEE80211_M_IBSS; 971 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) 972 newmode = IEEE80211_M_HOSTAP; 973 else if (ime->ifm_media & IFM_IEEE80211_MONITOR) 974 newmode = IEEE80211_M_MONITOR; 975 else 976 newmode = IEEE80211_M_STA; 977 if (ic->ic_opmode != newmode) { 978 ic->ic_opmode = newmode; 979 error = ENETRESET; 980 } 981 if (error == ENETRESET) { 982 if (sc->sc_enabled) 983 error = an_init(ifp); 984 else 985 error = 0; 986 } 987 ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media); 988 989 return error; 990 } 991 992 static void 993 an_media_status(struct ifnet *ifp, struct ifmediareq *imr) 994 { 995 struct an_softc *sc = ifp->if_softc; 996 struct ieee80211com *ic = &sc->sc_ic; 997 int rate, buflen; 998 999 if (sc->sc_enabled == 0) { 1000 imr->ifm_active = IFM_IEEE80211 | IFM_NONE; 1001 imr->ifm_status = 0; 1002 return; 1003 } 1004 1005 imr->ifm_status = IFM_AVALID; 1006 imr->ifm_active = IFM_IEEE80211; 1007 if (ic->ic_state == IEEE80211_S_RUN) 1008 imr->ifm_status |= IFM_ACTIVE; 1009 buflen = sizeof(sc->sc_buf); 1010 if (ic->ic_fixed_rate != -1) 1011 rate = ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ 1012 ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 1013 else if (an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen) != 0) 1014 rate = 0; 1015 else 1016 rate = le16toh(sc->sc_buf.sc_status.an_current_tx_rate); 1017 imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B); 1018 switch (ic->ic_opmode) { 1019 case IEEE80211_M_STA: 1020 break; 1021 case IEEE80211_M_IBSS: 1022 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1023 break; 1024 case IEEE80211_M_HOSTAP: 1025 imr->ifm_active |= IFM_IEEE80211_HOSTAP; 1026 break; 1027 case IEEE80211_M_MONITOR: 1028 imr->ifm_active |= IFM_IEEE80211_MONITOR; 1029 break; 1030 default: 1031 break; 1032 } 1033 } 1034 1035 static int 1036 an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1037 { 1038 int error; 1039 struct ieee80211com *ic = &sc->sc_ic; 1040 u_int16_t prevauth; 1041 1042 error = 0; 1043 prevauth = sc->sc_config.an_authtype; 1044 1045 switch (nwkey->i_wepon) { 1046 case IEEE80211_NWKEY_OPEN: 1047 sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN; 1048 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1049 break; 1050 1051 case IEEE80211_NWKEY_WEP: 1052 case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST: 1053 error = an_set_nwkey_wep(sc, nwkey); 1054 if (error == 0 || error == ENETRESET) { 1055 sc->sc_config.an_authtype = 1056 AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE; 1057 ic->ic_flags |= IEEE80211_F_PRIVACY; 1058 } 1059 break; 1060 1061 case IEEE80211_NWKEY_EAP: 1062 error = an_set_nwkey_eap(sc, nwkey); 1063 if (error == 0 || error == ENETRESET) { 1064 sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN | 1065 AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP; 1066 ic->ic_flags |= IEEE80211_F_PRIVACY; 1067 } 1068 break; 1069 default: 1070 error = EINVAL; 1071 break; 1072 } 1073 if (error == 0 && prevauth != sc->sc_config.an_authtype) 1074 error = ENETRESET; 1075 return error; 1076 } 1077 1078 static int 1079 an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1080 { 1081 int i, txkey, anysetkey, needreset, error; 1082 struct an_wepkey keys[IEEE80211_WEP_NKID]; 1083 1084 error = 0; 1085 memset(keys, 0, sizeof(keys)); 1086 anysetkey = needreset = 0; 1087 1088 /* load argument and sanity check */ 1089 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1090 keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen; 1091 if (keys[i].an_wep_keylen < 0) 1092 continue; 1093 if (keys[i].an_wep_keylen != 0 && 1094 keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN) 1095 return EINVAL; 1096 if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key)) 1097 return EINVAL; 1098 if ((error = copyin(nwkey->i_key[i].i_keydat, 1099 keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0) 1100 return error; 1101 anysetkey++; 1102 } 1103 txkey = nwkey->i_defkid - 1; 1104 if (txkey >= 0) { 1105 if (txkey >= IEEE80211_WEP_NKID) 1106 return EINVAL; 1107 /* default key must have a valid value */ 1108 if (keys[txkey].an_wep_keylen == 0 || 1109 (keys[txkey].an_wep_keylen < 0 && 1110 sc->sc_perskeylen[txkey] == 0)) 1111 return EINVAL; 1112 anysetkey++; 1113 } 1114 DPRINTF(("an_set_nwkey_wep: %s: %sold(%d:%d,%d,%d,%d) " 1115 "pers(%d:%d,%d,%d,%d) new(%d:%d,%d,%d,%d)\n", 1116 sc->sc_dev.dv_xname, 1117 ((nwkey->i_wepon & IEEE80211_NWKEY_PERSIST) ? "persist: " : ""), 1118 sc->sc_tx_key, 1119 sc->sc_wepkeys[0].an_wep_keylen, sc->sc_wepkeys[1].an_wep_keylen, 1120 sc->sc_wepkeys[2].an_wep_keylen, sc->sc_wepkeys[3].an_wep_keylen, 1121 sc->sc_tx_perskey, 1122 sc->sc_perskeylen[0], sc->sc_perskeylen[1], 1123 sc->sc_perskeylen[2], sc->sc_perskeylen[3], 1124 txkey, 1125 keys[0].an_wep_keylen, keys[1].an_wep_keylen, 1126 keys[2].an_wep_keylen, keys[3].an_wep_keylen)); 1127 if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) { 1128 /* set temporary keys */ 1129 sc->sc_tx_key = txkey; 1130 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1131 if (keys[i].an_wep_keylen < 0) 1132 continue; 1133 memcpy(&sc->sc_wepkeys[i], &keys[i], sizeof(keys[i])); 1134 } 1135 } else { 1136 /* set persist keys */ 1137 if (anysetkey) { 1138 /* prepare to write nvram */ 1139 if (!sc->sc_enabled) { 1140 if (sc->sc_enable) 1141 (*sc->sc_enable)(sc); 1142 an_wait(sc); 1143 sc->sc_enabled = 1; 1144 error = an_write_wepkey(sc, 1145 AN_RID_WEP_PERSISTENT, keys, txkey); 1146 if (sc->sc_disable) 1147 (*sc->sc_disable)(sc); 1148 sc->sc_enabled = 0; 1149 } else { 1150 an_cmd(sc, AN_CMD_DISABLE, 0); 1151 error = an_write_wepkey(sc, 1152 AN_RID_WEP_PERSISTENT, keys, txkey); 1153 an_cmd(sc, AN_CMD_ENABLE, 0); 1154 } 1155 if (error) 1156 return error; 1157 } 1158 if (txkey >= 0) 1159 sc->sc_tx_perskey = txkey; 1160 if (sc->sc_tx_key >= 0) { 1161 sc->sc_tx_key = -1; 1162 needreset++; 1163 } 1164 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1165 if (sc->sc_wepkeys[i].an_wep_keylen >= 0) { 1166 memset(&sc->sc_wepkeys[i].an_wep_key, 0, 1167 sizeof(sc->sc_wepkeys[i].an_wep_key)); 1168 sc->sc_wepkeys[i].an_wep_keylen = -1; 1169 needreset++; 1170 } 1171 if (keys[i].an_wep_keylen >= 0) 1172 sc->sc_perskeylen[i] = keys[i].an_wep_keylen; 1173 } 1174 } 1175 if (needreset) { 1176 /* firmware restart to reload persistent key */ 1177 an_reset(sc); 1178 } 1179 if (anysetkey || needreset) 1180 error = ENETRESET; 1181 return error; 1182 } 1183 1184 static int 1185 an_set_nwkey_eap(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1186 { 1187 int i, error, len; 1188 struct ifnet *ifp = &sc->sc_if; 1189 struct an_rid_leapkey *key; 1190 u_int16_t unibuf[sizeof(key->an_key)]; 1191 static const int leap_rid[] = { AN_RID_LEAP_PASS, AN_RID_LEAP_USER }; 1192 MD4_CTX ctx; 1193 1194 error = 0; 1195 1196 if (nwkey->i_key[0].i_keydat == NULL && 1197 nwkey->i_key[1].i_keydat == NULL) 1198 return 0; 1199 if (!sc->sc_enabled) 1200 return ENXIO; 1201 an_cmd(sc, AN_CMD_DISABLE, 0); 1202 key = &sc->sc_buf.sc_leapkey; 1203 for (i = 0; i < 2; i++) { 1204 if (nwkey->i_key[i].i_keydat == NULL) 1205 continue; 1206 len = nwkey->i_key[i].i_keylen; 1207 if (len > sizeof(key->an_key)) 1208 return EINVAL; 1209 memset(key, 0, sizeof(*key)); 1210 key->an_key_len = htole16(len); 1211 if ((error = copyin(nwkey->i_key[i].i_keydat, key->an_key, 1212 len)) != 0) 1213 return error; 1214 if (i == 1) { 1215 /* 1216 * Cisco seems to use PasswordHash and PasswordHashHash 1217 * in RFC-2759 (MS-CHAP-V2). 1218 */ 1219 memset(unibuf, 0, sizeof(unibuf)); 1220 /* XXX: convert password to unicode */ 1221 for (i = 0; i < len; i++) 1222 unibuf[i] = key->an_key[i]; 1223 /* set PasswordHash */ 1224 MD4Init(&ctx); 1225 MD4Update(&ctx, (u_int8_t *)unibuf, len * 2); 1226 MD4Final(key->an_key, &ctx); 1227 /* set PasswordHashHash */ 1228 MD4Init(&ctx); 1229 MD4Update(&ctx, key->an_key, 16); 1230 MD4Final(key->an_key + 16, &ctx); 1231 key->an_key_len = htole16(32); 1232 } 1233 if ((error = an_write_rid(sc, leap_rid[i], key, 1234 sizeof(*key))) != 0) { 1235 printf("%s: LEAP set failed\n", ifp->if_xname); 1236 return error; 1237 } 1238 } 1239 error = an_cmd(sc, AN_CMD_ENABLE, 0); 1240 if (error) 1241 printf("%s: an_set_nwkey: failed to enable MAC\n", 1242 ifp->if_xname); 1243 else 1244 error = ENETRESET; 1245 return error; 1246 } 1247 1248 static int 1249 an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1250 { 1251 int i, error; 1252 1253 error = 0; 1254 if (sc->sc_config.an_authtype & AN_AUTHTYPE_LEAP) 1255 nwkey->i_wepon = IEEE80211_NWKEY_EAP; 1256 else if (sc->sc_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) 1257 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 1258 else 1259 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 1260 if (sc->sc_tx_key == -1) 1261 nwkey->i_defkid = sc->sc_tx_perskey + 1; 1262 else 1263 nwkey->i_defkid = sc->sc_tx_key + 1; 1264 if (nwkey->i_key[0].i_keydat == NULL) 1265 return 0; 1266 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1267 if (nwkey->i_key[i].i_keydat == NULL) 1268 continue; 1269 /* do not show any keys to non-root user */ 1270 if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0) 1271 break; 1272 nwkey->i_key[i].i_keylen = sc->sc_wepkeys[i].an_wep_keylen; 1273 if (nwkey->i_key[i].i_keylen < 0) { 1274 if (sc->sc_perskeylen[i] == 0) 1275 nwkey->i_key[i].i_keylen = 0; 1276 continue; 1277 } 1278 if ((error = copyout(sc->sc_wepkeys[i].an_wep_key, 1279 nwkey->i_key[i].i_keydat, 1280 sc->sc_wepkeys[i].an_wep_keylen)) != 0) 1281 break; 1282 } 1283 return error; 1284 } 1285 1286 static int 1287 an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid) 1288 { 1289 int i, error; 1290 struct an_rid_wepkey *akey; 1291 1292 error = 0; 1293 akey = &sc->sc_buf.sc_wepkey; 1294 memset(akey, 0, sizeof(struct an_rid_wepkey)); 1295 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1296 if (keys[i].an_wep_keylen < 0 || 1297 keys[i].an_wep_keylen > sizeof(akey->an_key)) 1298 continue; 1299 akey->an_key_len = htole16(keys[i].an_wep_keylen); 1300 akey->an_key_index = htole16(i); 1301 akey->an_mac_addr[0] = 1; /* default mac */ 1302 memcpy(akey->an_key, keys[i].an_wep_key, keys[i].an_wep_keylen); 1303 if ((error = an_write_rid(sc, type, akey, sizeof(*akey))) != 0) 1304 return error; 1305 } 1306 if (kid >= 0) { 1307 akey->an_key_index = htole16(0xffff); 1308 akey->an_mac_addr[0] = kid; 1309 akey->an_key_len = htole16(0); 1310 memset(akey->an_key, 0, sizeof(akey->an_key)); 1311 error = an_write_rid(sc, type, akey, sizeof(*akey)); 1312 } 1313 return error; 1314 } 1315 1316 #ifdef AN_DEBUG 1317 static void 1318 an_dump_pkt(const char *devname, struct mbuf *m) 1319 { 1320 int col, col0, i; 1321 uint8_t *pkt = mtod(m, uint8_t *); 1322 const char *delim = ""; 1323 int delimw = 0; 1324 1325 printf("%s: pkt ", devname); 1326 col = col0 = strlen(devname) + strlen(": pkt "); 1327 for (i = 0; i < m->m_len; i++) { 1328 printf("%s%02x", delim, pkt[i]); 1329 delim = ":"; 1330 delimw = 1; 1331 col += delimw + 2; 1332 if (col >= 72) { 1333 printf("\n%*s", col0, ""); 1334 col = col0; 1335 delim = ""; 1336 delimw = 0; 1337 } 1338 } 1339 if (col != 0) 1340 printf("\n"); 1341 } 1342 #endif /* AN_DEBUG */ 1343 1344 /* 1345 * Low level functions 1346 */ 1347 1348 static void 1349 an_rx_intr(struct an_softc *sc) 1350 { 1351 struct ieee80211com *ic = &sc->sc_ic; 1352 struct ifnet *ifp = &sc->sc_if; 1353 struct ieee80211_frame_min *wh; 1354 struct ieee80211_node *ni; 1355 struct an_rxframe frmhdr; 1356 struct mbuf *m; 1357 u_int16_t status; 1358 int fid, gaplen, len, off; 1359 uint8_t *gap; 1360 1361 fid = CSR_READ_2(sc, AN_RX_FID); 1362 1363 /* First read in the frame header */ 1364 if (an_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) { 1365 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1366 ifp->if_ierrors++; 1367 DPRINTF(("an_rx_intr: read fid %x failed\n", fid)); 1368 return; 1369 } 1370 1371 #ifdef AN_DEBUG 1372 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) { 1373 ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr, 1374 sizeof(struct ieee80211_frame), frmhdr.an_rx_rate, 1375 frmhdr.an_rx_signal_strength); 1376 printf(" time 0x%x status 0x%x plen %u chan %u" 1377 " plcp %02x %02x %02x %02x gap %u\n", 1378 le32toh(frmhdr.an_rx_time), le16toh(frmhdr.an_rx_status), 1379 le16toh(frmhdr.an_rx_payload_len), frmhdr.an_rx_chan, 1380 frmhdr.an_plcp_hdr[0], frmhdr.an_plcp_hdr[1], 1381 frmhdr.an_plcp_hdr[2], frmhdr.an_plcp_hdr[3], 1382 le16toh(frmhdr.an_gaplen)); 1383 } 1384 #endif 1385 1386 status = le16toh(frmhdr.an_rx_status); 1387 if ((status & AN_STAT_ERRSTAT) != 0 && 1388 ic->ic_opmode != IEEE80211_M_MONITOR) { 1389 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1390 ifp->if_ierrors++; 1391 DPRINTF(("an_rx_intr: fid %x status %x\n", fid, status)); 1392 return; 1393 } 1394 1395 /* the payload length field includes a 16-bit "mystery field" */ 1396 len = le16toh(frmhdr.an_rx_payload_len) - sizeof(uint16_t); 1397 off = ALIGN(sizeof(struct ieee80211_frame)); 1398 1399 if (off + len > MCLBYTES) { 1400 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1401 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1402 ifp->if_ierrors++; 1403 DPRINTF(("an_rx_intr: oversized packet %d\n", len)); 1404 return; 1405 } 1406 len = 0; 1407 } 1408 1409 MGETHDR(m, M_DONTWAIT, MT_DATA); 1410 if (m == NULL) { 1411 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1412 ifp->if_ierrors++; 1413 DPRINTF(("an_rx_intr: MGET failed\n")); 1414 return; 1415 } 1416 if (off + len + AN_GAPLEN_MAX > MHLEN) { 1417 MCLGET(m, M_DONTWAIT); 1418 if ((m->m_flags & M_EXT) == 0) { 1419 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1420 m_freem(m); 1421 ifp->if_ierrors++; 1422 DPRINTF(("an_rx_intr: MCLGET failed\n")); 1423 return; 1424 } 1425 } 1426 m->m_data += off - sizeof(struct ieee80211_frame); 1427 1428 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1429 gaplen = le16toh(frmhdr.an_gaplen); 1430 if (gaplen > AN_GAPLEN_MAX) { 1431 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1432 m_freem(m); 1433 ifp->if_ierrors++; 1434 DPRINTF(("%s: gap too long\n", __func__)); 1435 return; 1436 } 1437 /* 1438 * We don't need the 16-bit mystery field (payload length?), 1439 * so read it into the region reserved for the 802.11 header. 1440 * 1441 * When Cisco Aironet 350 cards w/ firmware version 5 or 1442 * greater operate with certain Cisco 350 APs, 1443 * the "gap" is filled with the SNAP header. Read 1444 * it in after the 802.11 header. 1445 */ 1446 gap = m->m_data + sizeof(struct ieee80211_frame) - 1447 sizeof(uint16_t); 1448 an_read_bap(sc, fid, -1, gap, gaplen + sizeof(u_int16_t)); 1449 #ifdef AN_DEBUG 1450 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == 1451 (IFF_DEBUG|IFF_LINK2)) { 1452 int i; 1453 printf(" gap&len"); 1454 for (i = 0; i < gaplen + sizeof(u_int16_t); i++) 1455 printf(" %02x", gap[i]); 1456 printf("\n"); 1457 } 1458 #endif 1459 } else 1460 gaplen = 0; 1461 1462 an_read_bap(sc, fid, -1, 1463 m->m_data + sizeof(struct ieee80211_frame) + gaplen, len); 1464 m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + gaplen + 1465 len; 1466 1467 memcpy(m->m_data, &frmhdr.an_whdr, sizeof(struct ieee80211_frame)); 1468 m->m_pkthdr.rcvif = ifp; 1469 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1470 1471 wh = mtod(m, struct ieee80211_frame_min *); 1472 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1473 /* 1474 * WEP is decrypted by hardware. Clear WEP bit 1475 * header for ieee80211_input(). 1476 */ 1477 wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 1478 } 1479 1480 #ifdef AN_DEBUG 1481 if (an_debug > 1) 1482 an_dump_pkt(sc->sc_dev.dv_xname, m); 1483 #endif /* AN_DEBUG */ 1484 1485 ni = ieee80211_find_rxnode(ic, wh); 1486 ieee80211_input(ic, m, ni, frmhdr.an_rx_signal_strength, 1487 le32toh(frmhdr.an_rx_time)); 1488 ieee80211_free_node(ni); 1489 } 1490 1491 static void 1492 an_tx_intr(struct an_softc *sc, int status) 1493 { 1494 struct ifnet *ifp = &sc->sc_if; 1495 int cur, fid; 1496 1497 sc->sc_tx_timer = 0; 1498 ifp->if_flags &= ~IFF_OACTIVE; 1499 1500 fid = CSR_READ_2(sc, AN_TX_CMP_FID); 1501 CSR_WRITE_2(sc, AN_EVENT_ACK, status & (AN_EV_TX | AN_EV_TX_EXC)); 1502 1503 if (status & AN_EV_TX_EXC) 1504 ifp->if_oerrors++; 1505 else 1506 ifp->if_opackets++; 1507 1508 cur = sc->sc_txcur; 1509 if (sc->sc_txd[cur].d_fid == fid) { 1510 sc->sc_txd[cur].d_inuse = 0; 1511 DPRINTF2(("an_tx_intr: sent %x/%d\n", fid, cur)); 1512 AN_INC(cur, AN_TX_RING_CNT); 1513 sc->sc_txcur = cur; 1514 } else { 1515 for (cur = 0; cur < AN_TX_RING_CNT; cur++) { 1516 if (fid == sc->sc_txd[cur].d_fid) { 1517 sc->sc_txd[cur].d_inuse = 0; 1518 break; 1519 } 1520 } 1521 if (ifp->if_flags & IFF_DEBUG) 1522 printf("%s: tx mismatch: " 1523 "expected %x(%d), actual %x(%d)\n", 1524 sc->sc_dev.dv_xname, 1525 sc->sc_txd[sc->sc_txcur].d_fid, sc->sc_txcur, 1526 fid, cur); 1527 } 1528 1529 return; 1530 } 1531 1532 static void 1533 an_linkstat_intr(struct an_softc *sc) 1534 { 1535 struct ieee80211com *ic = &sc->sc_ic; 1536 u_int16_t status; 1537 1538 status = CSR_READ_2(sc, AN_LINKSTAT); 1539 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 1540 DPRINTF(("an_linkstat_intr: status 0x%x\n", status)); 1541 1542 if (status == AN_LINKSTAT_ASSOCIATED) { 1543 if (ic->ic_state != IEEE80211_S_RUN || 1544 ic->ic_opmode == IEEE80211_M_IBSS) 1545 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 1546 } else { 1547 if (ic->ic_opmode == IEEE80211_M_STA) 1548 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1549 } 1550 } 1551 1552 /* Must be called at proper protection level! */ 1553 static int 1554 an_cmd(struct an_softc *sc, int cmd, int val) 1555 { 1556 int i, status; 1557 1558 /* make sure that previous command completed */ 1559 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 1560 if (sc->sc_if.if_flags & IFF_DEBUG) 1561 printf("%s: command 0x%x busy\n", sc->sc_dev.dv_xname, 1562 CSR_READ_2(sc, AN_COMMAND)); 1563 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1564 } 1565 1566 CSR_WRITE_2(sc, AN_PARAM0, val); 1567 CSR_WRITE_2(sc, AN_PARAM1, 0); 1568 CSR_WRITE_2(sc, AN_PARAM2, 0); 1569 CSR_WRITE_2(sc, AN_COMMAND, cmd); 1570 1571 if (cmd == AN_CMD_FW_RESTART) { 1572 /* XXX: should sleep here */ 1573 DELAY(100*1000); 1574 } 1575 1576 for (i = 0; i < AN_TIMEOUT; i++) { 1577 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1578 break; 1579 DELAY(10); 1580 } 1581 1582 status = CSR_READ_2(sc, AN_STATUS); 1583 1584 /* clear stuck command busy if necessary */ 1585 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) 1586 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1587 1588 /* Ack the command */ 1589 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1590 1591 if (i == AN_TIMEOUT) { 1592 if (sc->sc_if.if_flags & IFF_DEBUG) 1593 printf("%s: command 0x%x param 0x%x timeout\n", 1594 sc->sc_dev.dv_xname, cmd, val); 1595 return ETIMEDOUT; 1596 } 1597 if (status & AN_STAT_CMD_RESULT) { 1598 if (sc->sc_if.if_flags & IFF_DEBUG) 1599 printf("%s: command 0x%x param 0x%x status 0x%x " 1600 "resp 0x%x 0x%x 0x%x\n", 1601 sc->sc_dev.dv_xname, cmd, val, status, 1602 CSR_READ_2(sc, AN_RESP0), CSR_READ_2(sc, AN_RESP1), 1603 CSR_READ_2(sc, AN_RESP2)); 1604 return EIO; 1605 } 1606 1607 return 0; 1608 } 1609 1610 1611 /* 1612 * Wait for firmware come up after power enabled. 1613 */ 1614 static void 1615 an_wait(struct an_softc *sc) 1616 { 1617 int i; 1618 1619 CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2); 1620 for (i = 0; i < 3*hz; i++) { 1621 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1622 break; 1623 (void)tsleep(sc, PWAIT, "anatch", 1); 1624 } 1625 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1626 } 1627 1628 static int 1629 an_seek_bap(struct an_softc *sc, int id, int off) 1630 { 1631 int i, status; 1632 1633 CSR_WRITE_2(sc, AN_SEL0, id); 1634 CSR_WRITE_2(sc, AN_OFF0, off); 1635 1636 for (i = 0; ; i++) { 1637 status = CSR_READ_2(sc, AN_OFF0); 1638 if ((status & AN_OFF_BUSY) == 0) 1639 break; 1640 if (i == AN_TIMEOUT) { 1641 printf("%s: timeout in an_seek_bap to 0x%x/0x%x\n", 1642 sc->sc_dev.dv_xname, id, off); 1643 sc->sc_bap_off = AN_OFF_ERR; /* invalidate */ 1644 return ETIMEDOUT; 1645 } 1646 DELAY(10); 1647 } 1648 if (status & AN_OFF_ERR) { 1649 printf("%s: failed in an_seek_bap to 0x%x/0x%x\n", 1650 sc->sc_dev.dv_xname, id, off); 1651 sc->sc_bap_off = AN_OFF_ERR; /* invalidate */ 1652 return EIO; 1653 } 1654 sc->sc_bap_id = id; 1655 sc->sc_bap_off = off; 1656 return 0; 1657 } 1658 1659 static int 1660 an_read_bap(struct an_softc *sc, int id, int off, void *buf, int buflen) 1661 { 1662 int error, cnt; 1663 1664 if (buflen == 0) 1665 return 0; 1666 if (off == -1) 1667 off = sc->sc_bap_off; 1668 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1669 if ((error = an_seek_bap(sc, id, off)) != 0) 1670 return EIO; 1671 } 1672 1673 cnt = (buflen + 1) / 2; 1674 CSR_READ_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt); 1675 sc->sc_bap_off += cnt * 2; 1676 return 0; 1677 } 1678 1679 static int 1680 an_write_bap(struct an_softc *sc, int id, int off, void *buf, int buflen) 1681 { 1682 int error, cnt; 1683 1684 if (buflen == 0) 1685 return 0; 1686 if (off == -1) 1687 off = sc->sc_bap_off; 1688 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1689 if ((error = an_seek_bap(sc, id, off)) != 0) 1690 return EIO; 1691 } 1692 1693 cnt = (buflen + 1) / 2; 1694 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt); 1695 sc->sc_bap_off += cnt * 2; 1696 return 0; 1697 } 1698 1699 static int 1700 an_mwrite_bap(struct an_softc *sc, int id, int off, struct mbuf *m, int totlen) 1701 { 1702 int error, len, cnt; 1703 1704 if (off == -1) 1705 off = sc->sc_bap_off; 1706 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1707 if ((error = an_seek_bap(sc, id, off)) != 0) 1708 return EIO; 1709 } 1710 1711 for (len = 0; m != NULL; m = m->m_next) { 1712 if (m->m_len == 0) 1713 continue; 1714 len = min(m->m_len, totlen); 1715 1716 if ((mtod(m, u_long) & 0x1) || (len & 0x1)) { 1717 m_copydata(m, 0, totlen, (caddr_t)&sc->sc_buf.sc_txbuf); 1718 cnt = (totlen + 1) / 2; 1719 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, 1720 sc->sc_buf.sc_val, cnt); 1721 off += cnt * 2; 1722 break; 1723 } 1724 cnt = len / 2; 1725 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, mtod(m, u_int16_t *), 1726 cnt); 1727 off += len; 1728 totlen -= len; 1729 } 1730 sc->sc_bap_off = off; 1731 return 0; 1732 } 1733 1734 static int 1735 an_alloc_fid(struct an_softc *sc, int len, int *idp) 1736 { 1737 int i; 1738 1739 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 1740 printf("%s: failed to allocate %d bytes on NIC\n", 1741 sc->sc_dev.dv_xname, len); 1742 return ENOMEM; 1743 } 1744 1745 for (i = 0; i < AN_TIMEOUT; i++) { 1746 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 1747 break; 1748 if (i == AN_TIMEOUT) { 1749 printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname); 1750 return ETIMEDOUT; 1751 } 1752 DELAY(10); 1753 } 1754 1755 *idp = CSR_READ_2(sc, AN_ALLOC_FID); 1756 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 1757 return 0; 1758 } 1759 1760 static int 1761 an_read_rid(struct an_softc *sc, int rid, void *buf, int *buflenp) 1762 { 1763 int error; 1764 u_int16_t len; 1765 1766 /* Tell the NIC to enter record read mode. */ 1767 error = an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_READ, rid); 1768 if (error) 1769 return error; 1770 1771 /* length in byte, including length itself */ 1772 error = an_read_bap(sc, rid, 0, &len, sizeof(len)); 1773 if (error) 1774 return error; 1775 1776 len = le16toh(len) - 2; 1777 if (*buflenp < len) { 1778 printf("%s: record buffer is too small, " 1779 "rid=%x, size=%d, len=%d\n", 1780 sc->sc_dev.dv_xname, rid, *buflenp, len); 1781 return ENOSPC; 1782 } 1783 *buflenp = len; 1784 return an_read_bap(sc, rid, sizeof(len), buf, len); 1785 } 1786 1787 static int 1788 an_write_rid(struct an_softc *sc, int rid, void *buf, int buflen) 1789 { 1790 int error; 1791 u_int16_t len; 1792 1793 /* length in byte, including length itself */ 1794 len = htole16(buflen + 2); 1795 1796 error = an_write_bap(sc, rid, 0, &len, sizeof(len)); 1797 if (error) 1798 return error; 1799 error = an_write_bap(sc, rid, sizeof(len), buf, buflen); 1800 if (error) 1801 return error; 1802 1803 return an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_WRITE, rid); 1804 } 1805 1806 static int 1807 an_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 1808 { 1809 struct an_softc *sc = (struct an_softc *)ic->ic_ifp->if_softc; 1810 struct ieee80211_node *ni = ic->ic_bss; 1811 enum ieee80211_state ostate; 1812 int buflen; 1813 1814 ostate = ic->ic_state; 1815 DPRINTF(("an_newstate: %s -> %s\n", ieee80211_state_name[ostate], 1816 ieee80211_state_name[nstate])); 1817 1818 switch (nstate) { 1819 case IEEE80211_S_INIT: 1820 ic->ic_flags &= ~IEEE80211_F_IBSSON; 1821 return (*sc->sc_newstate)(ic, nstate, arg); 1822 1823 case IEEE80211_S_SCAN: 1824 case IEEE80211_S_AUTH: 1825 case IEEE80211_S_ASSOC: 1826 ic->ic_state = nstate; /* NB: skip normal ieee80211 handling */ 1827 return 0; 1828 1829 case IEEE80211_S_RUN: 1830 buflen = sizeof(sc->sc_buf); 1831 an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen); 1832 IEEE80211_ADDR_COPY(ni->ni_bssid, 1833 sc->sc_buf.sc_status.an_cur_bssid); 1834 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid); 1835 ni->ni_chan = &ic->ic_channels[ 1836 le16toh(sc->sc_buf.sc_status.an_cur_channel)]; 1837 ni->ni_esslen = le16toh(sc->sc_buf.sc_status.an_ssidlen); 1838 if (ni->ni_esslen > IEEE80211_NWID_LEN) 1839 ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/ 1840 memcpy(ni->ni_essid, sc->sc_buf.sc_status.an_ssid, 1841 ni->ni_esslen); 1842 ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B]; /*XXX*/ 1843 if (ic->ic_ifp->if_flags & IFF_DEBUG) { 1844 printf("%s: ", sc->sc_dev.dv_xname); 1845 if (ic->ic_opmode == IEEE80211_M_STA) 1846 printf("associated "); 1847 else 1848 printf("synchronized "); 1849 printf("with %s ssid ", ether_sprintf(ni->ni_bssid)); 1850 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); 1851 printf(" channel %u start %uMb\n", 1852 le16toh(sc->sc_buf.sc_status.an_cur_channel), 1853 le16toh(sc->sc_buf.sc_status.an_current_tx_rate)/2); 1854 } 1855 break; 1856 1857 default: 1858 break; 1859 } 1860 return (*sc->sc_newstate)(ic, nstate, arg); 1861 } 1862