1 /* $NetBSD: an.c,v 1.35 2005/06/22 06:15:51 dyoung 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.35 2005/06/22 06:15:51 dyoung 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 return 0; 324 } 325 326 #ifdef AN_DEBUG 327 /* 328 * Setup sysctl(3) MIB, hw.an.* 329 * 330 * TBD condition CTLFLAG_PERMANENT on being an LKM or not 331 */ 332 SYSCTL_SETUP(sysctl_an, "sysctl an(4) subtree setup") 333 { 334 int rc; 335 const struct sysctlnode *cnode, *rnode; 336 337 if ((rc = sysctl_createv(clog, 0, NULL, &rnode, 338 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, 339 NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) 340 goto err; 341 342 if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, 343 CTLFLAG_PERMANENT, CTLTYPE_NODE, "an", 344 "Cisco/Aironet 802.11 controls", 345 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) 346 goto err; 347 348 /* control debugging printfs */ 349 if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, 350 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 351 "debug", SYSCTL_DESCR("Enable Cisco/Aironet debugging output"), 352 an_sysctl_verify_debug, 0, &an_debug, 0, 353 CTL_CREATE, CTL_EOL)) != 0) 354 goto err; 355 356 return; 357 err: 358 printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 359 } 360 361 static int 362 an_sysctl_verify(SYSCTLFN_ARGS, int lower, int upper) 363 { 364 int error, t; 365 struct sysctlnode node; 366 367 node = *rnode; 368 t = *(int*)rnode->sysctl_data; 369 node.sysctl_data = &t; 370 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 371 if (error || newp == NULL) 372 return (error); 373 374 if (t < lower || t > upper) 375 return (EINVAL); 376 377 *(int*)rnode->sysctl_data = t; 378 379 return (0); 380 } 381 382 static int 383 an_sysctl_verify_debug(SYSCTLFN_ARGS) 384 { 385 return an_sysctl_verify(SYSCTLFN_CALL(rnode), 0, 2); 386 } 387 #endif /* AN_DEBUG */ 388 389 int 390 an_detach(struct an_softc *sc) 391 { 392 struct ieee80211com *ic = &sc->sc_ic; 393 struct ifnet *ifp = &sc->sc_if; 394 int s; 395 396 if (!sc->sc_attached) 397 return 0; 398 399 s = splnet(); 400 sc->sc_invalid = 1; 401 an_stop(ifp, 1); 402 ieee80211_ifdetach(ic); 403 if_detach(ifp); 404 splx(s); 405 return 0; 406 } 407 408 int 409 an_activate(struct device *self, enum devact act) 410 { 411 struct an_softc *sc = (struct an_softc *)self; 412 int s, error = 0; 413 414 s = splnet(); 415 switch (act) { 416 case DVACT_ACTIVATE: 417 error = EOPNOTSUPP; 418 break; 419 420 case DVACT_DEACTIVATE: 421 sc->sc_invalid = 1; 422 if_deactivate(&sc->sc_if); 423 break; 424 } 425 splx(s); 426 427 return error; 428 } 429 430 void 431 an_power(int why, void *arg) 432 { 433 int s; 434 struct an_softc *sc = arg; 435 struct ifnet *ifp = &sc->sc_if; 436 437 s = splnet(); 438 switch (why) { 439 case PWR_SUSPEND: 440 case PWR_STANDBY: 441 an_stop(ifp, 1); 442 break; 443 case PWR_RESUME: 444 if (ifp->if_flags & IFF_UP) { 445 an_init(ifp); 446 (void)an_intr(sc); 447 } 448 break; 449 case PWR_SOFTSUSPEND: 450 case PWR_SOFTSTANDBY: 451 case PWR_SOFTRESUME: 452 break; 453 } 454 splx(s); 455 } 456 457 void 458 an_shutdown(struct an_softc *sc) 459 { 460 461 if (sc->sc_attached) 462 an_stop(&sc->sc_if, 1); 463 } 464 465 int 466 an_intr(void *arg) 467 { 468 struct an_softc *sc = arg; 469 struct ifnet *ifp = &sc->sc_if; 470 int i; 471 u_int16_t status; 472 473 if (!sc->sc_enabled || sc->sc_invalid || 474 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || 475 (ifp->if_flags & IFF_RUNNING) == 0) 476 return 0; 477 478 if ((ifp->if_flags & IFF_UP) == 0) { 479 CSR_WRITE_2(sc, AN_INT_EN, 0); 480 CSR_WRITE_2(sc, AN_EVENT_ACK, ~0); 481 return 1; 482 } 483 484 /* maximum 10 loops per interrupt */ 485 for (i = 0; i < 10; i++) { 486 if (!sc->sc_enabled || sc->sc_invalid) 487 return 1; 488 if (CSR_READ_2(sc, AN_SW0) != AN_MAGIC) { 489 DPRINTF(("an_intr: magic number changed: %x\n", 490 CSR_READ_2(sc, AN_SW0))); 491 sc->sc_invalid = 1; 492 return 1; 493 } 494 status = CSR_READ_2(sc, AN_EVENT_STAT); 495 CSR_WRITE_2(sc, AN_EVENT_ACK, status & ~(AN_INTRS)); 496 if ((status & AN_INTRS) == 0) 497 break; 498 499 if (status & AN_EV_RX) 500 an_rx_intr(sc); 501 502 if (status & (AN_EV_TX | AN_EV_TX_EXC)) 503 an_tx_intr(sc, status); 504 505 if (status & AN_EV_LINKSTAT) 506 an_linkstat_intr(sc); 507 508 if ((ifp->if_flags & IFF_OACTIVE) == 0 && 509 sc->sc_ic.ic_state == IEEE80211_S_RUN && 510 !IFQ_IS_EMPTY(&ifp->if_snd)) 511 an_start(ifp); 512 } 513 514 return 1; 515 } 516 517 static int 518 an_init(struct ifnet *ifp) 519 { 520 struct an_softc *sc = ifp->if_softc; 521 struct ieee80211com *ic = &sc->sc_ic; 522 int i, error, fid; 523 524 DPRINTF(("an_init: enabled %d\n", sc->sc_enabled)); 525 if (!sc->sc_enabled) { 526 if (sc->sc_enable) 527 (*sc->sc_enable)(sc); 528 an_wait(sc); 529 sc->sc_enabled = 1; 530 } else { 531 an_stop(ifp, 0); 532 if ((error = an_reset(sc)) != 0) { 533 printf("%s: failed to reset\n", ifp->if_xname); 534 an_stop(ifp, 1); 535 return error; 536 } 537 } 538 CSR_WRITE_2(sc, AN_SW0, AN_MAGIC); 539 540 /* Allocate the TX buffers */ 541 for (i = 0; i < AN_TX_RING_CNT; i++) { 542 if ((error = an_alloc_fid(sc, AN_TX_MAX_LEN, &fid)) != 0) { 543 printf("%s: failed to allocate nic memory\n", 544 ifp->if_xname); 545 an_stop(ifp, 1); 546 return error; 547 } 548 DPRINTF2(("an_init: txbuf %d allocated %x\n", i, fid)); 549 sc->sc_txd[i].d_fid = fid; 550 sc->sc_txd[i].d_inuse = 0; 551 } 552 sc->sc_txcur = sc->sc_txnext = 0; 553 554 IEEE80211_ADDR_COPY(sc->sc_config.an_macaddr, ic->ic_myaddr); 555 sc->sc_config.an_scanmode = htole16(AN_SCANMODE_ACTIVE); 556 sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_OPEN); /*XXX*/ 557 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 558 sc->sc_config.an_authtype |= 559 htole16(AN_AUTHTYPE_PRIVACY_IN_USE); 560 if (sc->sc_use_leap) 561 sc->sc_config.an_authtype |= 562 htole16(AN_AUTHTYPE_LEAP); 563 } 564 sc->sc_config.an_listen_interval = htole16(ic->ic_lintval); 565 sc->sc_config.an_beacon_period = htole16(ic->ic_lintval); 566 if (ic->ic_flags & IEEE80211_F_PMGTON) 567 sc->sc_config.an_psave_mode = htole16(AN_PSAVE_PSP); 568 else 569 sc->sc_config.an_psave_mode = htole16(AN_PSAVE_CAM); 570 sc->sc_config.an_ds_channel = 571 htole16(ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 572 573 switch (ic->ic_opmode) { 574 case IEEE80211_M_STA: 575 sc->sc_config.an_opmode = 576 htole16(AN_OPMODE_INFRASTRUCTURE_STATION); 577 sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR); 578 break; 579 case IEEE80211_M_IBSS: 580 sc->sc_config.an_opmode = htole16(AN_OPMODE_IBSS_ADHOC); 581 sc->sc_config.an_rxmode = htole16(AN_RXMODE_BC_MC_ADDR); 582 break; 583 case IEEE80211_M_MONITOR: 584 sc->sc_config.an_opmode = 585 htole16(AN_OPMODE_INFRASTRUCTURE_STATION); 586 sc->sc_config.an_rxmode = 587 htole16(AN_RXMODE_80211_MONITOR_ANYBSS); 588 sc->sc_config.an_authtype = htole16(AN_AUTHTYPE_NONE); 589 if (ic->ic_flags & IEEE80211_F_PRIVACY) 590 sc->sc_config.an_authtype |= 591 htole16(AN_AUTHTYPE_PRIVACY_IN_USE | 592 AN_AUTHTYPE_ALLOW_UNENCRYPTED); 593 break; 594 default: 595 printf("%s: bad opmode %d\n", ifp->if_xname, ic->ic_opmode); 596 an_stop(ifp, 1); 597 return EIO; 598 } 599 sc->sc_config.an_rxmode |= htole16(AN_RXMODE_NO_8023_HEADER); 600 601 /* Set the ssid list */ 602 memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_ssidlist)); 603 sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid_len = 604 htole16(ic->ic_des_esslen); 605 if (ic->ic_des_esslen) 606 memcpy(sc->sc_buf.sc_ssidlist.an_entry[0].an_ssid, 607 ic->ic_des_essid, ic->ic_des_esslen); 608 if (an_write_rid(sc, AN_RID_SSIDLIST, &sc->sc_buf, 609 sizeof(sc->sc_buf.sc_ssidlist)) != 0) { 610 printf("%s: failed to write ssid list\n", ifp->if_xname); 611 an_stop(ifp, 1); 612 return error; 613 } 614 615 /* Set the AP list */ 616 memset(&sc->sc_buf, 0, sizeof(sc->sc_buf.sc_aplist)); 617 (void)an_write_rid(sc, AN_RID_APLIST, &sc->sc_buf, 618 sizeof(sc->sc_buf.sc_aplist)); 619 620 /* Set the encapsulation */ 621 for (i = 0; i < AN_ENCAP_NENTS; i++) { 622 sc->sc_buf.sc_encap.an_entry[i].an_ethertype = htole16(0); 623 sc->sc_buf.sc_encap.an_entry[i].an_action = 624 htole16(AN_RXENCAP_RFC1024 | AN_TXENCAP_RFC1024); 625 } 626 (void)an_write_rid(sc, AN_RID_ENCAP, &sc->sc_buf, 627 sizeof(sc->sc_buf.sc_encap)); 628 629 /* Set the WEP Keys */ 630 if (ic->ic_flags & IEEE80211_F_PRIVACY) 631 an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->sc_wepkeys, 632 sc->sc_tx_key); 633 634 /* Set the configuration */ 635 #ifdef AN_DEBUG 636 if (an_debug) { 637 printf("write config:\n"); 638 for (i = 0; i < sizeof(sc->sc_config) / 2; i++) 639 printf(" %04x", ((u_int16_t *)&sc->sc_config)[i]); 640 printf("\n"); 641 } 642 #endif 643 if (an_write_rid(sc, AN_RID_GENCONFIG, &sc->sc_config, 644 sizeof(sc->sc_config)) != 0) { 645 printf("%s: failed to write config\n", ifp->if_xname); 646 an_stop(ifp, 1); 647 return error; 648 } 649 650 /* Enable the MAC */ 651 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 652 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname); 653 an_stop(ifp, 1); 654 return ENXIO; 655 } 656 if (ifp->if_flags & IFF_PROMISC) 657 an_cmd(sc, AN_CMD_SET_MODE, 0xffff); 658 659 ifp->if_flags |= IFF_RUNNING; 660 ifp->if_flags &= ~IFF_OACTIVE; 661 ic->ic_state = IEEE80211_S_INIT; 662 if (ic->ic_opmode == IEEE80211_M_MONITOR) 663 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 664 665 /* enable interrupts */ 666 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 667 return 0; 668 } 669 670 static void 671 an_stop(struct ifnet *ifp, int disable) 672 { 673 struct an_softc *sc = ifp->if_softc; 674 int i, s; 675 676 if (!sc->sc_enabled) 677 return; 678 679 DPRINTF(("an_stop: disable %d\n", disable)); 680 681 s = splnet(); 682 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 683 if (!sc->sc_invalid) { 684 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 685 CSR_WRITE_2(sc, AN_INT_EN, 0); 686 an_cmd(sc, AN_CMD_DISABLE, 0); 687 688 for (i = 0; i < AN_TX_RING_CNT; i++) 689 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->sc_txd[i].d_fid); 690 } 691 692 sc->sc_tx_timer = 0; 693 ifp->if_timer = 0; 694 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 695 696 if (disable) { 697 if (sc->sc_disable) 698 (*sc->sc_disable)(sc); 699 sc->sc_enabled = 0; 700 } 701 splx(s); 702 } 703 704 static void 705 an_start(struct ifnet *ifp) 706 { 707 struct an_softc *sc = (struct an_softc *)ifp->if_softc; 708 struct ieee80211com *ic = &sc->sc_ic; 709 struct ieee80211_node *ni; 710 struct ieee80211_frame *wh; 711 struct an_txframe frmhdr; 712 struct ether_header *eh; 713 struct mbuf *m; 714 u_int16_t len; 715 int cur, fid; 716 717 if (!sc->sc_enabled || sc->sc_invalid) { 718 DPRINTF(("an_start: noop: enabled %d invalid %d\n", 719 sc->sc_enabled, sc->sc_invalid)); 720 return; 721 } 722 723 memset(&frmhdr, 0, sizeof(frmhdr)); 724 cur = sc->sc_txnext; 725 for (;;) { 726 if (ic->ic_state != IEEE80211_S_RUN) { 727 DPRINTF(("an_start: not running %d\n", ic->ic_state)); 728 break; 729 } 730 IFQ_POLL(&ifp->if_snd, m); 731 if (m == NULL) { 732 DPRINTF2(("an_start: no pending mbuf\n")); 733 break; 734 } 735 if (sc->sc_txd[cur].d_inuse) { 736 DPRINTF2(("an_start: %x/%d busy\n", 737 sc->sc_txd[cur].d_fid, cur)); 738 ifp->if_flags |= IFF_OACTIVE; 739 break; 740 } 741 IFQ_DEQUEUE(&ifp->if_snd, m); 742 ifp->if_opackets++; 743 #if NBPFILTER > 0 744 if (ifp->if_bpf) 745 bpf_mtap(ifp->if_bpf, m); 746 #endif 747 eh = mtod(m, struct ether_header *); 748 ni = ieee80211_find_txnode(ic, eh->ether_dhost); 749 if (ni == NULL) { 750 /* NB: ieee80211_find_txnode does stat+msg */ 751 goto bad; 752 } 753 if ((m = ieee80211_encap(ic, m, ni)) == NULL) 754 goto bad; 755 ieee80211_free_node(ni); 756 #if NBPFILTER > 0 757 if (ic->ic_rawbpf) 758 bpf_mtap(ic->ic_rawbpf, m); 759 #endif 760 761 wh = mtod(m, struct ieee80211_frame *); 762 if (ic->ic_flags & IEEE80211_F_PRIVACY) 763 wh->i_fc[1] |= IEEE80211_FC1_WEP; 764 m_copydata(m, 0, sizeof(struct ieee80211_frame), 765 (caddr_t)&frmhdr.an_whdr); 766 767 /* insert payload length in front of llc/snap */ 768 len = htons(m->m_pkthdr.len - sizeof(struct ieee80211_frame)); 769 m_adj(m, sizeof(struct ieee80211_frame) - sizeof(len)); 770 if (mtod(m, u_long) & 0x01) 771 memcpy(mtod(m, caddr_t), &len, sizeof(len)); 772 else 773 *mtod(m, u_int16_t *) = len; 774 775 /* 776 * XXX Aironet firmware apparently convert the packet 777 * with longer than 1500 bytes in length into LLC/SNAP. 778 * If we have 1500 bytes in ethernet payload, it is 779 * 1508 bytes including LLC/SNAP and will be inserted 780 * additional LLC/SNAP header with 1501-1508 in its 781 * ethertype !! 782 * So we skip LLC/SNAP header and force firmware to 783 * convert it to LLC/SNAP again. 784 */ 785 m_adj(m, sizeof(struct llc)); 786 787 frmhdr.an_tx_ctl = htole16(AN_TXCTL_80211); 788 frmhdr.an_tx_payload_len = htole16(m->m_pkthdr.len); 789 frmhdr.an_gaplen = htole16(AN_TXGAP_802_11); 790 791 if (ic->ic_fixed_rate != -1) 792 frmhdr.an_tx_rate = 793 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ 794 ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 795 else 796 frmhdr.an_tx_rate = 0; 797 798 #ifdef AN_DEBUG 799 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == 800 (IFF_DEBUG|IFF_LINK2)) { 801 ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr, 802 sizeof(struct ieee80211_frame), -1, 0); 803 printf(" txctl 0x%x plen %u\n", 804 le16toh(frmhdr.an_tx_ctl), 805 le16toh(frmhdr.an_tx_payload_len)); 806 } 807 #endif 808 if (sizeof(frmhdr) + AN_TXGAP_802_11 + sizeof(len) + 809 m->m_pkthdr.len > AN_TX_MAX_LEN) 810 goto bad; 811 812 fid = sc->sc_txd[cur].d_fid; 813 if (an_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) 814 goto bad; 815 /* dummy write to avoid seek. */ 816 an_write_bap(sc, fid, -1, &frmhdr, AN_TXGAP_802_11); 817 an_mwrite_bap(sc, fid, -1, m, m->m_pkthdr.len); 818 m_freem(m); 819 820 DPRINTF2(("an_start: send %d byte via %x/%d\n", 821 ntohs(len) + sizeof(struct ieee80211_frame), 822 fid, cur)); 823 sc->sc_txd[cur].d_inuse = 1; 824 if (an_cmd(sc, AN_CMD_TX, fid)) { 825 printf("%s: xmit failed\n", ifp->if_xname); 826 sc->sc_txd[cur].d_inuse = 0; 827 continue; 828 } 829 sc->sc_tx_timer = 5; 830 ifp->if_timer = 1; 831 AN_INC(cur, AN_TX_RING_CNT); 832 sc->sc_txnext = cur; 833 continue; 834 bad: 835 ifp->if_oerrors++; 836 m_freem(m); 837 } 838 } 839 840 static int 841 an_reset(struct an_softc *sc) 842 { 843 844 DPRINTF(("an_reset\n")); 845 846 if (!sc->sc_enabled) 847 return ENXIO; 848 849 an_cmd(sc, AN_CMD_ENABLE, 0); 850 an_cmd(sc, AN_CMD_FW_RESTART, 0); 851 an_cmd(sc, AN_CMD_NOOP2, 0); 852 853 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) { 854 printf("%s: reset failed\n", sc->sc_dev.dv_xname); 855 return ETIMEDOUT; 856 } 857 858 an_cmd(sc, AN_CMD_DISABLE, 0); 859 return 0; 860 } 861 862 static void 863 an_watchdog(struct ifnet *ifp) 864 { 865 struct an_softc *sc = ifp->if_softc; 866 867 if (!sc->sc_enabled) 868 return; 869 870 if (sc->sc_tx_timer) { 871 if (--sc->sc_tx_timer == 0) { 872 printf("%s: device timeout\n", ifp->if_xname); 873 ifp->if_oerrors++; 874 an_init(ifp); 875 return; 876 } 877 ifp->if_timer = 1; 878 } 879 ieee80211_watchdog(&sc->sc_ic); 880 } 881 882 static int 883 an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 884 { 885 struct an_softc *sc = ifp->if_softc; 886 int s, error = 0; 887 888 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) 889 return ENXIO; 890 891 s = splnet(); 892 893 switch (command) { 894 case SIOCSIFFLAGS: 895 if (ifp->if_flags & IFF_UP) { 896 if (sc->sc_enabled) { 897 /* 898 * To avoid rescanning another access point, 899 * do not call an_init() here. Instead, only 900 * reflect promisc mode settings. 901 */ 902 error = an_cmd(sc, AN_CMD_SET_MODE, 903 (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0); 904 } else 905 error = an_init(ifp); 906 } else if (sc->sc_enabled) 907 an_stop(ifp, 1); 908 break; 909 case SIOCADDMULTI: 910 case SIOCDELMULTI: 911 error = ether_ioctl(ifp, command, data); 912 if (error == ENETRESET) { 913 /* we don't have multicast filter. */ 914 error = 0; 915 } 916 break; 917 case SIOCS80211NWKEY: 918 error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data); 919 break; 920 case SIOCG80211NWKEY: 921 error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data); 922 break; 923 default: 924 error = ieee80211_ioctl(&sc->sc_ic, command, data); 925 break; 926 } 927 if (error == ENETRESET) { 928 if (sc->sc_enabled) 929 error = an_init(ifp); 930 else 931 error = 0; 932 } 933 splx(s); 934 return error; 935 } 936 937 /* TBD factor with ieee80211_media_change */ 938 static int 939 an_media_change(struct ifnet *ifp) 940 { 941 struct an_softc *sc = ifp->if_softc; 942 struct ieee80211com *ic = &sc->sc_ic; 943 struct ifmedia_entry *ime; 944 enum ieee80211_opmode newmode; 945 int i, rate, error = 0; 946 947 ime = ic->ic_media.ifm_cur; 948 if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { 949 i = -1; 950 } else { 951 struct ieee80211_rateset *rs = 952 &ic->ic_sup_rates[IEEE80211_MODE_11B]; 953 rate = ieee80211_media2rate(ime->ifm_media); 954 if (rate == 0) 955 return EINVAL; 956 for (i = 0; i < rs->rs_nrates; i++) { 957 if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate) 958 break; 959 } 960 if (i == rs->rs_nrates) 961 return EINVAL; 962 } 963 if (ic->ic_fixed_rate != i) { 964 ic->ic_fixed_rate = i; 965 error = ENETRESET; 966 } 967 968 if (ime->ifm_media & IFM_IEEE80211_ADHOC) 969 newmode = IEEE80211_M_IBSS; 970 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) 971 newmode = IEEE80211_M_HOSTAP; 972 else if (ime->ifm_media & IFM_IEEE80211_MONITOR) 973 newmode = IEEE80211_M_MONITOR; 974 else 975 newmode = IEEE80211_M_STA; 976 if (ic->ic_opmode != newmode) { 977 ic->ic_opmode = newmode; 978 error = ENETRESET; 979 } 980 if (error == ENETRESET) { 981 if (sc->sc_enabled) 982 error = an_init(ifp); 983 else 984 error = 0; 985 } 986 ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media); 987 988 return error; 989 } 990 991 static void 992 an_media_status(struct ifnet *ifp, struct ifmediareq *imr) 993 { 994 struct an_softc *sc = ifp->if_softc; 995 struct ieee80211com *ic = &sc->sc_ic; 996 int rate, buflen; 997 998 if (sc->sc_enabled == 0) { 999 imr->ifm_active = IFM_IEEE80211 | IFM_NONE; 1000 imr->ifm_status = 0; 1001 return; 1002 } 1003 1004 imr->ifm_status = IFM_AVALID; 1005 imr->ifm_active = IFM_IEEE80211; 1006 if (ic->ic_state == IEEE80211_S_RUN) 1007 imr->ifm_status |= IFM_ACTIVE; 1008 buflen = sizeof(sc->sc_buf); 1009 if (ic->ic_fixed_rate != -1) 1010 rate = ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ 1011 ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 1012 else if (an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen) != 0) 1013 rate = 0; 1014 else 1015 rate = le16toh(sc->sc_buf.sc_status.an_current_tx_rate); 1016 imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B); 1017 switch (ic->ic_opmode) { 1018 case IEEE80211_M_STA: 1019 break; 1020 case IEEE80211_M_IBSS: 1021 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1022 break; 1023 case IEEE80211_M_HOSTAP: 1024 imr->ifm_active |= IFM_IEEE80211_HOSTAP; 1025 break; 1026 case IEEE80211_M_MONITOR: 1027 imr->ifm_active |= IFM_IEEE80211_MONITOR; 1028 break; 1029 default: 1030 break; 1031 } 1032 } 1033 1034 static int 1035 an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1036 { 1037 int error; 1038 struct ieee80211com *ic = &sc->sc_ic; 1039 u_int16_t prevauth; 1040 1041 error = 0; 1042 prevauth = sc->sc_config.an_authtype; 1043 1044 switch (nwkey->i_wepon) { 1045 case IEEE80211_NWKEY_OPEN: 1046 sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN; 1047 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1048 break; 1049 1050 case IEEE80211_NWKEY_WEP: 1051 case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST: 1052 error = an_set_nwkey_wep(sc, nwkey); 1053 if (error == 0 || error == ENETRESET) { 1054 sc->sc_config.an_authtype = 1055 AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE; 1056 ic->ic_flags |= IEEE80211_F_PRIVACY; 1057 } 1058 break; 1059 1060 case IEEE80211_NWKEY_EAP: 1061 error = an_set_nwkey_eap(sc, nwkey); 1062 if (error == 0 || error == ENETRESET) { 1063 sc->sc_config.an_authtype = AN_AUTHTYPE_OPEN | 1064 AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP; 1065 ic->ic_flags |= IEEE80211_F_PRIVACY; 1066 } 1067 break; 1068 default: 1069 error = EINVAL; 1070 break; 1071 } 1072 if (error == 0 && prevauth != sc->sc_config.an_authtype) 1073 error = ENETRESET; 1074 return error; 1075 } 1076 1077 static int 1078 an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1079 { 1080 int i, txkey, anysetkey, needreset, error; 1081 struct an_wepkey keys[IEEE80211_WEP_NKID]; 1082 1083 error = 0; 1084 memset(keys, 0, sizeof(keys)); 1085 anysetkey = needreset = 0; 1086 1087 /* load argument and sanity check */ 1088 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1089 keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen; 1090 if (keys[i].an_wep_keylen < 0) 1091 continue; 1092 if (keys[i].an_wep_keylen != 0 && 1093 keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN) 1094 return EINVAL; 1095 if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key)) 1096 return EINVAL; 1097 if ((error = copyin(nwkey->i_key[i].i_keydat, 1098 keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0) 1099 return error; 1100 anysetkey++; 1101 } 1102 txkey = nwkey->i_defkid - 1; 1103 if (txkey >= 0) { 1104 if (txkey >= IEEE80211_WEP_NKID) 1105 return EINVAL; 1106 /* default key must have a valid value */ 1107 if (keys[txkey].an_wep_keylen == 0 || 1108 (keys[txkey].an_wep_keylen < 0 && 1109 sc->sc_perskeylen[txkey] == 0)) 1110 return EINVAL; 1111 anysetkey++; 1112 } 1113 DPRINTF(("an_set_nwkey_wep: %s: %sold(%d:%d,%d,%d,%d) " 1114 "pers(%d:%d,%d,%d,%d) new(%d:%d,%d,%d,%d)\n", 1115 sc->sc_dev.dv_xname, 1116 ((nwkey->i_wepon & IEEE80211_NWKEY_PERSIST) ? "persist: " : ""), 1117 sc->sc_tx_key, 1118 sc->sc_wepkeys[0].an_wep_keylen, sc->sc_wepkeys[1].an_wep_keylen, 1119 sc->sc_wepkeys[2].an_wep_keylen, sc->sc_wepkeys[3].an_wep_keylen, 1120 sc->sc_tx_perskey, 1121 sc->sc_perskeylen[0], sc->sc_perskeylen[1], 1122 sc->sc_perskeylen[2], sc->sc_perskeylen[3], 1123 txkey, 1124 keys[0].an_wep_keylen, keys[1].an_wep_keylen, 1125 keys[2].an_wep_keylen, keys[3].an_wep_keylen)); 1126 if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) { 1127 /* set temporary keys */ 1128 sc->sc_tx_key = txkey; 1129 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1130 if (keys[i].an_wep_keylen < 0) 1131 continue; 1132 memcpy(&sc->sc_wepkeys[i], &keys[i], sizeof(keys[i])); 1133 } 1134 } else { 1135 /* set persist keys */ 1136 if (anysetkey) { 1137 /* prepare to write nvram */ 1138 if (!sc->sc_enabled) { 1139 if (sc->sc_enable) 1140 (*sc->sc_enable)(sc); 1141 an_wait(sc); 1142 sc->sc_enabled = 1; 1143 error = an_write_wepkey(sc, 1144 AN_RID_WEP_PERSISTENT, keys, txkey); 1145 if (sc->sc_disable) 1146 (*sc->sc_disable)(sc); 1147 sc->sc_enabled = 0; 1148 } else { 1149 an_cmd(sc, AN_CMD_DISABLE, 0); 1150 error = an_write_wepkey(sc, 1151 AN_RID_WEP_PERSISTENT, keys, txkey); 1152 an_cmd(sc, AN_CMD_ENABLE, 0); 1153 } 1154 if (error) 1155 return error; 1156 } 1157 if (txkey >= 0) 1158 sc->sc_tx_perskey = txkey; 1159 if (sc->sc_tx_key >= 0) { 1160 sc->sc_tx_key = -1; 1161 needreset++; 1162 } 1163 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1164 if (sc->sc_wepkeys[i].an_wep_keylen >= 0) { 1165 memset(&sc->sc_wepkeys[i].an_wep_key, 0, 1166 sizeof(sc->sc_wepkeys[i].an_wep_key)); 1167 sc->sc_wepkeys[i].an_wep_keylen = -1; 1168 needreset++; 1169 } 1170 if (keys[i].an_wep_keylen >= 0) 1171 sc->sc_perskeylen[i] = keys[i].an_wep_keylen; 1172 } 1173 } 1174 if (needreset) { 1175 /* firmware restart to reload persistent key */ 1176 an_reset(sc); 1177 } 1178 if (anysetkey || needreset) 1179 error = ENETRESET; 1180 return error; 1181 } 1182 1183 static int 1184 an_set_nwkey_eap(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1185 { 1186 int i, error, len; 1187 struct ifnet *ifp = &sc->sc_if; 1188 struct an_rid_leapkey *key; 1189 u_int16_t unibuf[sizeof(key->an_key)]; 1190 static const int leap_rid[] = { AN_RID_LEAP_PASS, AN_RID_LEAP_USER }; 1191 MD4_CTX ctx; 1192 1193 error = 0; 1194 1195 if (nwkey->i_key[0].i_keydat == NULL && 1196 nwkey->i_key[1].i_keydat == NULL) 1197 return 0; 1198 if (!sc->sc_enabled) 1199 return ENXIO; 1200 an_cmd(sc, AN_CMD_DISABLE, 0); 1201 key = &sc->sc_buf.sc_leapkey; 1202 for (i = 0; i < 2; i++) { 1203 if (nwkey->i_key[i].i_keydat == NULL) 1204 continue; 1205 len = nwkey->i_key[i].i_keylen; 1206 if (len > sizeof(key->an_key)) 1207 return EINVAL; 1208 memset(key, 0, sizeof(*key)); 1209 key->an_key_len = htole16(len); 1210 if ((error = copyin(nwkey->i_key[i].i_keydat, key->an_key, 1211 len)) != 0) 1212 return error; 1213 if (i == 1) { 1214 /* 1215 * Cisco seems to use PasswordHash and PasswordHashHash 1216 * in RFC-2759 (MS-CHAP-V2). 1217 */ 1218 memset(unibuf, 0, sizeof(unibuf)); 1219 /* XXX: convert password to unicode */ 1220 for (i = 0; i < len; i++) 1221 unibuf[i] = key->an_key[i]; 1222 /* set PasswordHash */ 1223 MD4Init(&ctx); 1224 MD4Update(&ctx, (u_int8_t *)unibuf, len * 2); 1225 MD4Final(key->an_key, &ctx); 1226 /* set PasswordHashHash */ 1227 MD4Init(&ctx); 1228 MD4Update(&ctx, key->an_key, 16); 1229 MD4Final(key->an_key + 16, &ctx); 1230 key->an_key_len = htole16(32); 1231 } 1232 if ((error = an_write_rid(sc, leap_rid[i], key, 1233 sizeof(*key))) != 0) { 1234 printf("%s: LEAP set failed\n", ifp->if_xname); 1235 return error; 1236 } 1237 } 1238 error = an_cmd(sc, AN_CMD_ENABLE, 0); 1239 if (error) 1240 printf("%s: an_set_nwkey: failed to enable MAC\n", 1241 ifp->if_xname); 1242 else 1243 error = ENETRESET; 1244 return error; 1245 } 1246 1247 static int 1248 an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 1249 { 1250 int i, error; 1251 1252 error = 0; 1253 if (sc->sc_config.an_authtype & AN_AUTHTYPE_LEAP) 1254 nwkey->i_wepon = IEEE80211_NWKEY_EAP; 1255 else if (sc->sc_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) 1256 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 1257 else 1258 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 1259 if (sc->sc_tx_key == -1) 1260 nwkey->i_defkid = sc->sc_tx_perskey + 1; 1261 else 1262 nwkey->i_defkid = sc->sc_tx_key + 1; 1263 if (nwkey->i_key[0].i_keydat == NULL) 1264 return 0; 1265 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1266 if (nwkey->i_key[i].i_keydat == NULL) 1267 continue; 1268 /* do not show any keys to non-root user */ 1269 if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0) 1270 break; 1271 nwkey->i_key[i].i_keylen = sc->sc_wepkeys[i].an_wep_keylen; 1272 if (nwkey->i_key[i].i_keylen < 0) { 1273 if (sc->sc_perskeylen[i] == 0) 1274 nwkey->i_key[i].i_keylen = 0; 1275 continue; 1276 } 1277 if ((error = copyout(sc->sc_wepkeys[i].an_wep_key, 1278 nwkey->i_key[i].i_keydat, 1279 sc->sc_wepkeys[i].an_wep_keylen)) != 0) 1280 break; 1281 } 1282 return error; 1283 } 1284 1285 static int 1286 an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid) 1287 { 1288 int i, error; 1289 struct an_rid_wepkey *akey; 1290 1291 error = 0; 1292 akey = &sc->sc_buf.sc_wepkey; 1293 memset(akey, 0, sizeof(struct an_rid_wepkey)); 1294 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1295 if (keys[i].an_wep_keylen < 0 || 1296 keys[i].an_wep_keylen > sizeof(akey->an_key)) 1297 continue; 1298 akey->an_key_len = htole16(keys[i].an_wep_keylen); 1299 akey->an_key_index = htole16(i); 1300 akey->an_mac_addr[0] = 1; /* default mac */ 1301 memcpy(akey->an_key, keys[i].an_wep_key, keys[i].an_wep_keylen); 1302 if ((error = an_write_rid(sc, type, akey, sizeof(*akey))) != 0) 1303 return error; 1304 } 1305 if (kid >= 0) { 1306 akey->an_key_index = htole16(0xffff); 1307 akey->an_mac_addr[0] = kid; 1308 akey->an_key_len = htole16(0); 1309 memset(akey->an_key, 0, sizeof(akey->an_key)); 1310 error = an_write_rid(sc, type, akey, sizeof(*akey)); 1311 } 1312 return error; 1313 } 1314 1315 #ifdef AN_DEBUG 1316 static void 1317 an_dump_pkt(const char *devname, struct mbuf *m) 1318 { 1319 int col, col0, i; 1320 uint8_t *pkt = mtod(m, uint8_t *); 1321 const char *delim = ""; 1322 int delimw = 0; 1323 1324 printf("%s: pkt ", devname); 1325 col = col0 = strlen(devname) + strlen(": pkt "); 1326 for (i = 0; i < m->m_len; i++) { 1327 printf("%s%02x", delim, pkt[i]); 1328 delim = ":"; 1329 delimw = 1; 1330 col += delimw + 2; 1331 if (col >= 72) { 1332 printf("\n%*s", col0, ""); 1333 col = col0; 1334 delim = ""; 1335 delimw = 0; 1336 } 1337 } 1338 if (col != 0) 1339 printf("\n"); 1340 } 1341 #endif /* AN_DEBUG */ 1342 1343 /* 1344 * Low level functions 1345 */ 1346 1347 static void 1348 an_rx_intr(struct an_softc *sc) 1349 { 1350 struct ieee80211com *ic = &sc->sc_ic; 1351 struct ifnet *ifp = &sc->sc_if; 1352 struct ieee80211_frame_min *wh; 1353 struct ieee80211_node *ni; 1354 struct an_rxframe frmhdr; 1355 struct mbuf *m; 1356 u_int16_t status; 1357 int fid, gaplen, len, off; 1358 uint8_t *gap; 1359 1360 fid = CSR_READ_2(sc, AN_RX_FID); 1361 1362 /* First read in the frame header */ 1363 if (an_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) { 1364 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1365 ifp->if_ierrors++; 1366 DPRINTF(("an_rx_intr: read fid %x failed\n", fid)); 1367 return; 1368 } 1369 1370 #ifdef AN_DEBUG 1371 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) { 1372 ieee80211_dump_pkt((u_int8_t *)&frmhdr.an_whdr, 1373 sizeof(struct ieee80211_frame), frmhdr.an_rx_rate, 1374 frmhdr.an_rx_signal_strength); 1375 printf(" time 0x%x status 0x%x plen %u chan %u" 1376 " plcp %02x %02x %02x %02x gap %u\n", 1377 le32toh(frmhdr.an_rx_time), le16toh(frmhdr.an_rx_status), 1378 le16toh(frmhdr.an_rx_payload_len), frmhdr.an_rx_chan, 1379 frmhdr.an_plcp_hdr[0], frmhdr.an_plcp_hdr[1], 1380 frmhdr.an_plcp_hdr[2], frmhdr.an_plcp_hdr[3], 1381 le16toh(frmhdr.an_gaplen)); 1382 } 1383 #endif 1384 1385 status = le16toh(frmhdr.an_rx_status); 1386 if ((status & AN_STAT_ERRSTAT) != 0 && 1387 ic->ic_opmode != IEEE80211_M_MONITOR) { 1388 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1389 ifp->if_ierrors++; 1390 DPRINTF(("an_rx_intr: fid %x status %x\n", fid, status)); 1391 return; 1392 } 1393 1394 /* the payload length field includes a 16-bit "mystery field" */ 1395 len = le16toh(frmhdr.an_rx_payload_len) - sizeof(uint16_t); 1396 off = ALIGN(sizeof(struct ieee80211_frame)); 1397 1398 if (off + len > MCLBYTES) { 1399 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1400 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1401 ifp->if_ierrors++; 1402 DPRINTF(("an_rx_intr: oversized packet %d\n", len)); 1403 return; 1404 } 1405 len = 0; 1406 } 1407 1408 MGETHDR(m, M_DONTWAIT, MT_DATA); 1409 if (m == NULL) { 1410 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1411 ifp->if_ierrors++; 1412 DPRINTF(("an_rx_intr: MGET failed\n")); 1413 return; 1414 } 1415 if (off + len + AN_GAPLEN_MAX > MHLEN) { 1416 MCLGET(m, M_DONTWAIT); 1417 if ((m->m_flags & M_EXT) == 0) { 1418 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1419 m_freem(m); 1420 ifp->if_ierrors++; 1421 DPRINTF(("an_rx_intr: MCLGET failed\n")); 1422 return; 1423 } 1424 } 1425 m->m_data += off - sizeof(struct ieee80211_frame); 1426 1427 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1428 gaplen = le16toh(frmhdr.an_gaplen); 1429 if (gaplen > AN_GAPLEN_MAX) { 1430 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1431 m_freem(m); 1432 ifp->if_ierrors++; 1433 DPRINTF(("%s: gap too long\n", __func__)); 1434 return; 1435 } 1436 /* 1437 * We don't need the 16-bit mystery field (payload length?), 1438 * so read it into the region reserved for the 802.11 header. 1439 * 1440 * When Cisco Aironet 350 cards w/ firmware version 5 or 1441 * greater operate with certain Cisco 350 APs, 1442 * the "gap" is filled with the SNAP header. Read 1443 * it in after the 802.11 header. 1444 */ 1445 gap = m->m_data + sizeof(struct ieee80211_frame) - 1446 sizeof(uint16_t); 1447 an_read_bap(sc, fid, -1, gap, gaplen + sizeof(u_int16_t)); 1448 #ifdef AN_DEBUG 1449 if ((ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == 1450 (IFF_DEBUG|IFF_LINK2)) { 1451 int i; 1452 printf(" gap&len"); 1453 for (i = 0; i < gaplen + sizeof(u_int16_t); i++) 1454 printf(" %02x", gap[i]); 1455 printf("\n"); 1456 } 1457 #endif 1458 } else 1459 gaplen = 0; 1460 1461 an_read_bap(sc, fid, -1, 1462 m->m_data + sizeof(struct ieee80211_frame) + gaplen, len); 1463 m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + gaplen + 1464 len; 1465 1466 memcpy(m->m_data, &frmhdr.an_whdr, sizeof(struct ieee80211_frame)); 1467 m->m_pkthdr.rcvif = ifp; 1468 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1469 1470 wh = mtod(m, struct ieee80211_frame_min *); 1471 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1472 /* 1473 * WEP is decrypted by hardware. Clear WEP bit 1474 * header for ieee80211_input(). 1475 */ 1476 wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 1477 } 1478 1479 #ifdef AN_DEBUG 1480 if (an_debug > 1) 1481 an_dump_pkt(sc->sc_dev.dv_xname, m); 1482 #endif /* AN_DEBUG */ 1483 1484 ni = ieee80211_find_rxnode(ic, wh); 1485 ieee80211_input(ic, m, ni, frmhdr.an_rx_signal_strength, 1486 le32toh(frmhdr.an_rx_time)); 1487 ieee80211_free_node(ni); 1488 } 1489 1490 static void 1491 an_tx_intr(struct an_softc *sc, int status) 1492 { 1493 struct ifnet *ifp = &sc->sc_if; 1494 int cur, fid; 1495 1496 sc->sc_tx_timer = 0; 1497 ifp->if_flags &= ~IFF_OACTIVE; 1498 1499 fid = CSR_READ_2(sc, AN_TX_CMP_FID); 1500 CSR_WRITE_2(sc, AN_EVENT_ACK, status & (AN_EV_TX | AN_EV_TX_EXC)); 1501 1502 if (status & AN_EV_TX_EXC) 1503 ifp->if_oerrors++; 1504 else 1505 ifp->if_opackets++; 1506 1507 cur = sc->sc_txcur; 1508 if (sc->sc_txd[cur].d_fid == fid) { 1509 sc->sc_txd[cur].d_inuse = 0; 1510 DPRINTF2(("an_tx_intr: sent %x/%d\n", fid, cur)); 1511 AN_INC(cur, AN_TX_RING_CNT); 1512 sc->sc_txcur = cur; 1513 } else { 1514 for (cur = 0; cur < AN_TX_RING_CNT; cur++) { 1515 if (fid == sc->sc_txd[cur].d_fid) { 1516 sc->sc_txd[cur].d_inuse = 0; 1517 break; 1518 } 1519 } 1520 if (ifp->if_flags & IFF_DEBUG) 1521 printf("%s: tx mismatch: " 1522 "expected %x(%d), actual %x(%d)\n", 1523 sc->sc_dev.dv_xname, 1524 sc->sc_txd[sc->sc_txcur].d_fid, sc->sc_txcur, 1525 fid, cur); 1526 } 1527 1528 return; 1529 } 1530 1531 static void 1532 an_linkstat_intr(struct an_softc *sc) 1533 { 1534 struct ieee80211com *ic = &sc->sc_ic; 1535 u_int16_t status; 1536 1537 status = CSR_READ_2(sc, AN_LINKSTAT); 1538 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 1539 DPRINTF(("an_linkstat_intr: status 0x%x\n", status)); 1540 1541 if (status == AN_LINKSTAT_ASSOCIATED) { 1542 if (ic->ic_state != IEEE80211_S_RUN || 1543 ic->ic_opmode == IEEE80211_M_IBSS) 1544 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 1545 } else { 1546 if (ic->ic_opmode == IEEE80211_M_STA) 1547 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1548 } 1549 } 1550 1551 /* Must be called at proper protection level! */ 1552 static int 1553 an_cmd(struct an_softc *sc, int cmd, int val) 1554 { 1555 int i, status; 1556 1557 /* make sure that previous command completed */ 1558 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 1559 if (sc->sc_if.if_flags & IFF_DEBUG) 1560 printf("%s: command 0x%x busy\n", sc->sc_dev.dv_xname, 1561 CSR_READ_2(sc, AN_COMMAND)); 1562 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1563 } 1564 1565 CSR_WRITE_2(sc, AN_PARAM0, val); 1566 CSR_WRITE_2(sc, AN_PARAM1, 0); 1567 CSR_WRITE_2(sc, AN_PARAM2, 0); 1568 CSR_WRITE_2(sc, AN_COMMAND, cmd); 1569 1570 if (cmd == AN_CMD_FW_RESTART) { 1571 /* XXX: should sleep here */ 1572 DELAY(100*1000); 1573 } 1574 1575 for (i = 0; i < AN_TIMEOUT; i++) { 1576 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1577 break; 1578 DELAY(10); 1579 } 1580 1581 status = CSR_READ_2(sc, AN_STATUS); 1582 1583 /* clear stuck command busy if necessary */ 1584 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) 1585 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1586 1587 /* Ack the command */ 1588 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1589 1590 if (i == AN_TIMEOUT) { 1591 if (sc->sc_if.if_flags & IFF_DEBUG) 1592 printf("%s: command 0x%x param 0x%x timeout\n", 1593 sc->sc_dev.dv_xname, cmd, val); 1594 return ETIMEDOUT; 1595 } 1596 if (status & AN_STAT_CMD_RESULT) { 1597 if (sc->sc_if.if_flags & IFF_DEBUG) 1598 printf("%s: command 0x%x param 0x%x status 0x%x " 1599 "resp 0x%x 0x%x 0x%x\n", 1600 sc->sc_dev.dv_xname, cmd, val, status, 1601 CSR_READ_2(sc, AN_RESP0), CSR_READ_2(sc, AN_RESP1), 1602 CSR_READ_2(sc, AN_RESP2)); 1603 return EIO; 1604 } 1605 1606 return 0; 1607 } 1608 1609 1610 /* 1611 * Wait for firmware come up after power enabled. 1612 */ 1613 static void 1614 an_wait(struct an_softc *sc) 1615 { 1616 int i; 1617 1618 CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2); 1619 for (i = 0; i < 3*hz; i++) { 1620 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1621 break; 1622 (void)tsleep(sc, PWAIT, "anatch", 1); 1623 } 1624 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1625 } 1626 1627 static int 1628 an_seek_bap(struct an_softc *sc, int id, int off) 1629 { 1630 int i, status; 1631 1632 CSR_WRITE_2(sc, AN_SEL0, id); 1633 CSR_WRITE_2(sc, AN_OFF0, off); 1634 1635 for (i = 0; ; i++) { 1636 status = CSR_READ_2(sc, AN_OFF0); 1637 if ((status & AN_OFF_BUSY) == 0) 1638 break; 1639 if (i == AN_TIMEOUT) { 1640 printf("%s: timeout in an_seek_bap to 0x%x/0x%x\n", 1641 sc->sc_dev.dv_xname, id, off); 1642 sc->sc_bap_off = AN_OFF_ERR; /* invalidate */ 1643 return ETIMEDOUT; 1644 } 1645 DELAY(10); 1646 } 1647 if (status & AN_OFF_ERR) { 1648 printf("%s: failed in an_seek_bap to 0x%x/0x%x\n", 1649 sc->sc_dev.dv_xname, id, off); 1650 sc->sc_bap_off = AN_OFF_ERR; /* invalidate */ 1651 return EIO; 1652 } 1653 sc->sc_bap_id = id; 1654 sc->sc_bap_off = off; 1655 return 0; 1656 } 1657 1658 static int 1659 an_read_bap(struct an_softc *sc, int id, int off, void *buf, int buflen) 1660 { 1661 int error, cnt; 1662 1663 if (buflen == 0) 1664 return 0; 1665 if (off == -1) 1666 off = sc->sc_bap_off; 1667 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1668 if ((error = an_seek_bap(sc, id, off)) != 0) 1669 return EIO; 1670 } 1671 1672 cnt = (buflen + 1) / 2; 1673 CSR_READ_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt); 1674 sc->sc_bap_off += cnt * 2; 1675 return 0; 1676 } 1677 1678 static int 1679 an_write_bap(struct an_softc *sc, int id, int off, void *buf, int buflen) 1680 { 1681 int error, cnt; 1682 1683 if (buflen == 0) 1684 return 0; 1685 if (off == -1) 1686 off = sc->sc_bap_off; 1687 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1688 if ((error = an_seek_bap(sc, id, off)) != 0) 1689 return EIO; 1690 } 1691 1692 cnt = (buflen + 1) / 2; 1693 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, (u_int16_t *)buf, cnt); 1694 sc->sc_bap_off += cnt * 2; 1695 return 0; 1696 } 1697 1698 static int 1699 an_mwrite_bap(struct an_softc *sc, int id, int off, struct mbuf *m, int totlen) 1700 { 1701 int error, len, cnt; 1702 1703 if (off == -1) 1704 off = sc->sc_bap_off; 1705 if (id != sc->sc_bap_id || off != sc->sc_bap_off) { 1706 if ((error = an_seek_bap(sc, id, off)) != 0) 1707 return EIO; 1708 } 1709 1710 for (len = 0; m != NULL; m = m->m_next) { 1711 if (m->m_len == 0) 1712 continue; 1713 len = min(m->m_len, totlen); 1714 1715 if ((mtod(m, u_long) & 0x1) || (len & 0x1)) { 1716 m_copydata(m, 0, totlen, (caddr_t)&sc->sc_buf.sc_txbuf); 1717 cnt = (totlen + 1) / 2; 1718 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, 1719 sc->sc_buf.sc_val, cnt); 1720 off += cnt * 2; 1721 break; 1722 } 1723 cnt = len / 2; 1724 CSR_WRITE_MULTI_STREAM_2(sc, AN_DATA0, mtod(m, u_int16_t *), 1725 cnt); 1726 off += len; 1727 totlen -= len; 1728 } 1729 sc->sc_bap_off = off; 1730 return 0; 1731 } 1732 1733 static int 1734 an_alloc_fid(struct an_softc *sc, int len, int *idp) 1735 { 1736 int i; 1737 1738 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 1739 printf("%s: failed to allocate %d bytes on NIC\n", 1740 sc->sc_dev.dv_xname, len); 1741 return ENOMEM; 1742 } 1743 1744 for (i = 0; i < AN_TIMEOUT; i++) { 1745 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 1746 break; 1747 if (i == AN_TIMEOUT) { 1748 printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname); 1749 return ETIMEDOUT; 1750 } 1751 DELAY(10); 1752 } 1753 1754 *idp = CSR_READ_2(sc, AN_ALLOC_FID); 1755 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 1756 return 0; 1757 } 1758 1759 static int 1760 an_read_rid(struct an_softc *sc, int rid, void *buf, int *buflenp) 1761 { 1762 int error; 1763 u_int16_t len; 1764 1765 /* Tell the NIC to enter record read mode. */ 1766 error = an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_READ, rid); 1767 if (error) 1768 return error; 1769 1770 /* length in byte, including length itself */ 1771 error = an_read_bap(sc, rid, 0, &len, sizeof(len)); 1772 if (error) 1773 return error; 1774 1775 len = le16toh(len) - 2; 1776 if (*buflenp < len) { 1777 printf("%s: record buffer is too small, " 1778 "rid=%x, size=%d, len=%d\n", 1779 sc->sc_dev.dv_xname, rid, *buflenp, len); 1780 return ENOSPC; 1781 } 1782 *buflenp = len; 1783 return an_read_bap(sc, rid, sizeof(len), buf, len); 1784 } 1785 1786 static int 1787 an_write_rid(struct an_softc *sc, int rid, void *buf, int buflen) 1788 { 1789 int error; 1790 u_int16_t len; 1791 1792 /* length in byte, including length itself */ 1793 len = htole16(buflen + 2); 1794 1795 error = an_write_bap(sc, rid, 0, &len, sizeof(len)); 1796 if (error) 1797 return error; 1798 error = an_write_bap(sc, rid, sizeof(len), buf, buflen); 1799 if (error) 1800 return error; 1801 1802 return an_cmd(sc, AN_CMD_ACCESS | AN_ACCESS_WRITE, rid); 1803 } 1804 1805 static int 1806 an_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 1807 { 1808 struct an_softc *sc = (struct an_softc *)ic->ic_ifp->if_softc; 1809 struct ieee80211_node *ni = ic->ic_bss; 1810 enum ieee80211_state ostate; 1811 int buflen; 1812 1813 ostate = ic->ic_state; 1814 DPRINTF(("an_newstate: %s -> %s\n", ieee80211_state_name[ostate], 1815 ieee80211_state_name[nstate])); 1816 1817 switch (nstate) { 1818 case IEEE80211_S_INIT: 1819 ic->ic_flags &= ~IEEE80211_F_IBSSON; 1820 return (*sc->sc_newstate)(ic, nstate, arg); 1821 1822 case IEEE80211_S_RUN: 1823 buflen = sizeof(sc->sc_buf); 1824 an_read_rid(sc, AN_RID_STATUS, &sc->sc_buf, &buflen); 1825 IEEE80211_ADDR_COPY(ni->ni_bssid, 1826 sc->sc_buf.sc_status.an_cur_bssid); 1827 IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid); 1828 ni->ni_chan = &ic->ic_channels[ 1829 le16toh(sc->sc_buf.sc_status.an_cur_channel)]; 1830 ni->ni_esslen = le16toh(sc->sc_buf.sc_status.an_ssidlen); 1831 if (ni->ni_esslen > IEEE80211_NWID_LEN) 1832 ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/ 1833 memcpy(ni->ni_essid, sc->sc_buf.sc_status.an_ssid, 1834 ni->ni_esslen); 1835 ni->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B]; /*XXX*/ 1836 if (ic->ic_ifp->if_flags & IFF_DEBUG) { 1837 printf("%s: ", sc->sc_dev.dv_xname); 1838 if (ic->ic_opmode == IEEE80211_M_STA) 1839 printf("associated "); 1840 else 1841 printf("synchronized "); 1842 printf("with %s ssid ", ether_sprintf(ni->ni_bssid)); 1843 ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); 1844 printf(" channel %u start %uMb\n", 1845 le16toh(sc->sc_buf.sc_status.an_cur_channel), 1846 le16toh(sc->sc_buf.sc_status.an_current_tx_rate)/2); 1847 } 1848 break; 1849 1850 default: 1851 break; 1852 } 1853 ic->ic_state = nstate; 1854 /* skip standard ieee80211 handling */ 1855 return 0; 1856 } 1857