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