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