an.c revision 1.24
1/* $NetBSD: an.c,v 1.24 2003/01/31 00:26:27 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 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form. 46 * This driver supports all three device types (PCI devices are supported 47 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be 48 * supported either using hard-coded IO port/IRQ settings or via Plug 49 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates. 50 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates. 51 * 52 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially 53 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA 54 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are 55 * a couple of important differences though: 56 * 57 * - Lucent doesn't currently offer a PCI card, however Aironet does 58 * - Lucent ISA card looks to the host like a PCMCIA controller with 59 * a PCMCIA WaveLAN card inserted. This means that even desktop 60 * machines need to be configured with PCMCIA support in order to 61 * use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand 62 * actually look like normal ISA and PCI devices to the host, so 63 * no PCMCIA controller support is needed 64 * 65 * The latter point results in a small gotcha. The Aironet PCMCIA 66 * cards can be configured for one of two operating modes depending 67 * on how the Vpp1 and Vpp2 programming voltages are set when the 68 * card is activated. In order to put the card in proper PCMCIA 69 * operation (where the CIS table is visible and the interface is 70 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be 71 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages, 72 * which leaves the card in ISA/PCI mode, which prevents it from 73 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c 74 * has to be patched slightly in order to enable the Vpp voltages in 75 * order to make the Aironet PCMCIA cards work. 76 * 77 * Note that some PCMCIA controller software packages for Windows NT 78 * fail to set the voltages as well. 79 * 80 * The Aironet devices can operate in both station mode and access point 81 * mode. Typically, when programmed for station mode, the card can be set 82 * to automatically perform encapsulation/decapsulation of Ethernet II 83 * and 802.3 frames within 802.11 frames so that the host doesn't have 84 * to do it itself. This driver doesn't program the card that way: the 85 * driver handles all of the encapsulation/decapsulation itself. 86 */ 87 88/* 89 * Ported to NetBSD from FreeBSD by Atsushi Onoe at the San Diego 90 * IETF meeting. 91 */ 92 93#include <sys/cdefs.h> 94__KERNEL_RCSID(0, "$NetBSD: an.c,v 1.24 2003/01/31 00:26:27 thorpej Exp $"); 95 96#include "opt_inet.h" 97#include "bpfilter.h" 98 99#ifdef INET 100/* 101 * It is designed for IPv4 only. 102 * no one use it and disabled for now. -- onoe 103 */ 104#undef ANCACHE /* enable signal strength cache */ 105#endif 106 107#include <sys/param.h> 108#include <sys/callout.h> 109#include <sys/systm.h> 110#include <sys/sockio.h> 111#include <sys/mbuf.h> 112#include <sys/kernel.h> 113#include <sys/ucred.h> 114#include <sys/socket.h> 115#include <sys/device.h> 116#include <sys/proc.h> 117#include <sys/md4.h> 118#ifdef ANCACHE 119#include <sys/syslog.h> 120#include <sys/sysctl.h> 121#endif 122 123#include <machine/bus.h> 124 125#include <net/if.h> 126#include <net/if_arp.h> 127#include <net/if_dl.h> 128#include <net/if_ether.h> 129#include <net/if_ieee80211.h> 130#include <net/if_types.h> 131#include <net/if_media.h> 132 133#ifdef INET 134#include <netinet/in.h> 135#include <netinet/in_systm.h> 136#include <netinet/in_var.h> 137#include <netinet/ip.h> 138#endif 139 140#if NBPFILTER > 0 141#include <net/bpf.h> 142#endif 143 144#include <dev/ic/anreg.h> 145#include <dev/ic/anvar.h> 146 147/* These are global because we need them in sys/pci/if_an_p.c. */ 148static void an_reset __P((struct an_softc *)); 149static void an_wait __P((struct an_softc *)); 150static int an_ioctl __P((struct ifnet *, u_long, caddr_t)); 151static int an_set_nwkey __P((struct an_softc *, 152 struct ieee80211_nwkey *)); 153static int an_set_nwkey_wep __P((struct an_softc *, 154 struct ieee80211_nwkey *)); 155static int an_set_nwkey_eap __P((struct an_softc *, 156 struct ieee80211_nwkey *)); 157static int an_get_nwkey __P((struct an_softc *, 158 struct ieee80211_nwkey *)); 159static int an_write_wepkey __P((struct an_softc *sc, int type, 160 struct an_wepkey *keys, int kid)); 161static int an_init __P((struct ifnet *)); 162static void an_stop __P((struct ifnet *, int)); 163static int an_init_tx_ring __P((struct an_softc *)); 164static void an_start __P((struct ifnet *)); 165static void an_watchdog __P((struct ifnet *)); 166static void an_rxeof __P((struct an_softc *)); 167static void an_txeof __P((struct an_softc *, int)); 168 169static int an_cmd __P((struct an_softc *, int, int)); 170static int an_read_record __P((struct an_softc *, struct an_ltv_gen *)); 171static int an_write_record __P((struct an_softc *, struct an_ltv_gen *)); 172static int an_read_data __P((struct an_softc *, int, 173 int, caddr_t, int)); 174static int an_write_data __P((struct an_softc *, int, 175 int, caddr_t, int)); 176static int an_seek __P((struct an_softc *, int, int, int)); 177static int an_alloc_nicmem __P((struct an_softc *, int, int *)); 178static void an_stats_update __P((void *)); 179static int an_setdef __P((struct an_softc *, struct an_req *)); 180#ifdef ANCACHE 181static void an_cache_store __P((struct an_softc *, struct ether_header *, 182 struct mbuf *, unsigned short)); 183#endif 184#ifdef IFM_IEEE80211 185static int an_media_change __P((struct ifnet *ifp)); 186static void an_media_status __P((struct ifnet *ifp, struct ifmediareq *imr)); 187#endif 188 189int 190an_attach(struct an_softc *sc) 191{ 192 struct ifnet *ifp = &sc->arpcom.ec_if; 193 int i, s; 194 struct an_ltv_wepkey *akey; 195#ifdef IFM_IEEE80211 196 int mtype; 197 struct ifmediareq imr; 198#endif 199 200 s = splnet(); 201 sc->an_associated = 0; 202 an_wait(sc); 203 204 /* Load factory config */ 205 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 206 splx(s); 207 aprint_error("%s: failed to load config data\n", 208 sc->an_dev.dv_xname); 209 return(EIO); 210 } 211 212 /* Read the current configuration */ 213 sc->an_config.an_type = AN_RID_GENCONFIG; 214 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 215 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 216 splx(s); 217 aprint_error("%s: read record failed\n", sc->an_dev.dv_xname); 218 return(EIO); 219 } 220 221 /* Read the card capabilities */ 222 sc->an_caps.an_type = AN_RID_CAPABILITIES; 223 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 224 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 225 splx(s); 226 aprint_error("%s: read record failed\n", sc->an_dev.dv_xname); 227 return(EIO); 228 } 229 230 /* Read ssid list */ 231 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 232 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 233 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 234 splx(s); 235 aprint_error("%s: read record failed\n", sc->an_dev.dv_xname); 236 return(EIO); 237 } 238 239 /* Read AP list */ 240 sc->an_aplist.an_type = AN_RID_APLIST; 241 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 242 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 243 splx(s); 244 aprint_error("%s: read record failed\n", sc->an_dev.dv_xname); 245 return(EIO); 246 } 247 248 /* Read WEP settings from persistent memory */ 249 akey = (struct an_ltv_wepkey *)&sc->an_reqbuf; 250 akey->an_type = AN_RID_WEP_VOLATILE; 251 akey->an_len = sizeof(struct an_ltv_wepkey); 252 while (an_read_record(sc, (struct an_ltv_gen *)akey) == 0) { 253 if (akey->an_key_index == 0xffff) { 254 sc->an_tx_perskey = akey->an_mac_addr[0]; 255 sc->an_tx_key = -1; 256 break; 257 } 258 if (akey->an_key_index >= IEEE80211_WEP_NKID) 259 break; 260 sc->an_perskeylen[akey->an_key_index] = akey->an_key_len; 261 sc->an_wepkeys[akey->an_key_index].an_wep_keylen = -1; 262 akey->an_type = AN_RID_WEP_PERSISTENT; /* for next key */ 263 akey->an_len = sizeof(*akey); 264 } 265 /* XXX not sure if persistent key settings should be printed here */ 266 267 aprint_normal("%s: 802.11 address: %s\n", sc->an_dev.dv_xname, 268 ether_sprintf(sc->an_caps.an_oemaddr)); 269 270 ifp->if_softc = sc; 271 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX | 272 IFF_MULTICAST | IFF_ALLMULTI; 273 ifp->if_ioctl = an_ioctl; 274 ifp->if_start = an_start; 275 ifp->if_init = an_init; 276 ifp->if_stop = an_stop; 277 ifp->if_watchdog = an_watchdog; 278 IFQ_SET_READY(&ifp->if_snd); 279 280 memcpy(ifp->if_xname, sc->an_dev.dv_xname, IFNAMSIZ); 281 282 memset(sc->an_config.an_nodename, 0, sizeof(sc->an_config.an_nodename)); 283 memcpy(sc->an_config.an_nodename, AN_DEFAULT_NODENAME, 284 sizeof(AN_DEFAULT_NODENAME) - 1); 285 286 memset(sc->an_ssidlist.an_ssid1, 0, sizeof(sc->an_ssidlist.an_ssid1)); 287 memcpy(sc->an_ssidlist.an_ssid1, AN_DEFAULT_NETNAME, 288 sizeof(AN_DEFAULT_NETNAME) - 1); 289 sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME); 290 291 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 292 293 sc->an_tx_rate = 0; 294#if 0 295 memset(&sc->an_stats, 0, sizeof(sc->an_stats)); 296#endif 297 298 /* 299 * Call MI attach routine. 300 */ 301 if_attach(ifp); 302 ether_ifattach(ifp, sc->an_caps.an_oemaddr); 303 304#ifdef IFM_IEEE80211 305 ifmedia_init(&sc->sc_media, 0, an_media_change, an_media_status); 306 ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 307 0, 0), 0, NULL); 308 ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 309 IFM_IEEE80211_ADHOC, 0), 0, NULL); 310 for (i = 0; i < sizeof(sc->an_caps.an_rates); i++) { 311 switch (sc->an_caps.an_rates[i]) { 312 case AN_RATE_1MBPS: 313 mtype = IFM_IEEE80211_DS1; 314 break; 315 case AN_RATE_2MBPS: 316 mtype = IFM_IEEE80211_DS2; 317 break; 318 case AN_RATE_5_5MBPS: 319 mtype = IFM_IEEE80211_DS5; 320 break; 321 case AN_RATE_11MBPS: 322 mtype = IFM_IEEE80211_DS11; 323 break; 324 default: 325 continue; 326 } 327 ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, mtype, 328 0, 0), 0, NULL); 329 ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_IEEE80211, mtype, 330 IFM_IEEE80211_ADHOC, 0), 0, NULL); 331 } 332 an_media_status(ifp, &imr); 333 ifmedia_set(&sc->sc_media, imr.ifm_active); 334#endif 335 callout_init(&sc->an_stat_ch); 336 splx(s); 337 338 return(0); 339} 340 341int 342an_detach(struct an_softc *sc) 343{ 344 struct ifnet *ifp = &sc->arpcom.ec_if; 345 int s; 346 347 s = splnet(); 348 an_stop(ifp, 1); 349 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 350 ether_ifdetach(ifp); 351 if_detach(ifp); 352 splx(s); 353 return 0; 354} 355 356int 357an_activate(struct device *self, enum devact act) 358{ 359 struct an_softc *sc = (struct an_softc *)self; 360 int s, error = 0; 361 362 s = splnet(); 363 switch (act) { 364 case DVACT_ACTIVATE: 365 error = EOPNOTSUPP; 366 break; 367 368 case DVACT_DEACTIVATE: 369 if_deactivate(&sc->arpcom.ec_if); 370 break; 371 } 372 splx(s); 373 374 return error; 375} 376 377void 378an_power(int why, void *arg) 379{ 380 int s; 381 struct an_softc *sc = arg; 382 struct ifnet *ifp = &sc->arpcom.ec_if; 383 384 s = splnet(); 385 switch (why) { 386 case PWR_SUSPEND: 387 case PWR_STANDBY: 388 an_stop(ifp, 1); 389 break; 390 case PWR_RESUME: 391 if (ifp->if_flags & IFF_UP) 392 an_init(ifp); 393 break; 394 case PWR_SOFTSUSPEND: 395 case PWR_SOFTSTANDBY: 396 case PWR_SOFTRESUME: 397 break; 398 } 399 splx(s); 400} 401 402void 403an_shutdown(void *arg) 404{ 405 struct an_softc *sc = arg; 406 407 an_stop(&sc->arpcom.ec_if, 1); 408 return; 409} 410 411static int 412an_setdef(struct an_softc *sc, struct an_req *areq) 413{ 414 int error; 415 struct ifnet *ifp = &sc->arpcom.ec_if; 416 struct an_ltv_genconfig *cfg; 417 struct an_ltv_gen *sp; 418 419 error = 0; 420 421 switch (areq->an_type) { 422 case AN_RID_GENCONFIG: 423 cfg = (struct an_ltv_genconfig *)areq; 424 memcpy(sc->an_caps.an_oemaddr, cfg->an_macaddr, ETHER_ADDR_LEN); 425 memcpy(LLADDR(ifp->if_sadl), cfg->an_macaddr, ETHER_ADDR_LEN); 426 memcpy(&sc->an_config, areq, sizeof(struct an_ltv_genconfig)); 427 error = ENETRESET; 428 break; 429 case AN_RID_SSIDLIST: 430 memcpy(&sc->an_ssidlist, areq, sizeof(struct an_ltv_ssidlist)); 431 error = ENETRESET; 432 break; 433 case AN_RID_APLIST: 434 memcpy(&sc->an_aplist, areq, sizeof(struct an_ltv_aplist)); 435 error = ENETRESET; 436 break; 437 case AN_RID_TX_SPEED: 438 sp = (struct an_ltv_gen *)areq; 439 sc->an_tx_rate = sp->an_val; 440 break; 441 case AN_RID_WEP_VOLATILE: 442 case AN_RID_WEP_PERSISTENT: 443 case AN_RID_LEAP_USER: 444 case AN_RID_LEAP_PASS: 445 if (!sc->sc_enabled) { 446 error = ENXIO; 447 break; 448 } 449 an_cmd(sc, AN_CMD_DISABLE, 0); 450 an_write_record(sc, (struct an_ltv_gen *)areq); 451 if (an_cmd(sc, AN_CMD_ENABLE, 0)) 452 error = EIO; 453 break; 454 default: 455 if (ifp->if_flags & IFF_DEBUG) 456 printf("%s: unknown RID: %x\n", sc->an_dev.dv_xname, 457 areq->an_type); 458 error = EINVAL; 459 break; 460 } 461 return error; 462} 463 464static int 465an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 466{ 467 int s; 468 int error = 0; 469 struct an_softc *sc; 470 struct an_req *areq; 471 struct ifreq *ifr; 472 struct ieee80211_nwid nwid; 473 struct ieee80211_power *power; 474 475 sc = ifp->if_softc; 476 ifr = (struct ifreq *)data; 477 s = splnet(); 478 479 switch (command) { 480 case SIOCSIFFLAGS: 481 if (ifp->if_flags & IFF_UP) { 482 if (sc->sc_enabled) { 483 /* 484 * To avoid rescanning another access point, 485 * do not call an_init() here. Instead, only 486 * reflect promisc mode settings. 487 */ 488 error = an_cmd(sc, AN_CMD_SET_MODE, 489 (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0); 490 } else 491 error = an_init(ifp); 492 } else if (sc->sc_enabled) 493 an_stop(ifp, 1); 494 break; 495 case SIOCGAIRONET: 496 areq = &sc->an_reqbuf; 497 error = copyin(ifr->ifr_data, areq, sizeof(struct an_req)); 498 if (error) 499 break; 500 switch (areq->an_type) { 501#ifdef ANCACHE 502 case AN_RID_ZERO_CACHE: 503 /* XXX suser()? -- should belong to SIOCSAIRONET */ 504 sc->an_sigitems = sc->an_nextitem = 0; 505 goto out; 506 case AN_RID_READ_CACHE: 507 caddr_t pt = (char *)&areq->an_val; 508 memcpy(pt, &sc->an_sigitems, sizeof(int)); 509 pt += sizeof(int); 510 areq->an_len = sizeof(int) / 2; 511 memcpy(pt, &sc->an_sigcache, 512 sizeof(struct an_sigcache) * sc->an_sigitems); 513 areq->an_len += ((sizeof(struct an_sigcache) * 514 sc->an_sigitems) / 2) + 1; 515 break; 516#endif 517 default: 518 if (an_read_record(sc, (struct an_ltv_gen *)areq)) { 519 error = EINVAL; 520 break; 521 } 522 break; 523 } 524 error = copyout(areq, ifr->ifr_data, sizeof(struct an_req)); 525 break; 526 case SIOCSAIRONET: 527 if ((error = suser(curproc->p_ucred, &curproc->p_acflag))) 528 break; 529 areq = &sc->an_reqbuf; 530 error = copyin(ifr->ifr_data, areq, sizeof(struct an_req)); 531 if (error) 532 break; 533 error = an_setdef(sc, areq); 534 break; 535 case SIOCS80211NWID: 536 error = copyin(ifr->ifr_data, &nwid, sizeof(nwid)); 537 if (error) 538 break; 539 if (nwid.i_len > IEEE80211_NWID_LEN) { 540 error = EINVAL; 541 break; 542 } 543 if (sc->an_ssidlist.an_ssid1_len == nwid.i_len && 544 memcmp(sc->an_ssidlist.an_ssid1, nwid.i_nwid, nwid.i_len) 545 == 0) 546 break; 547 memset(sc->an_ssidlist.an_ssid1, 0, IEEE80211_NWID_LEN); 548 sc->an_ssidlist.an_ssid1_len = nwid.i_len; 549 memcpy(sc->an_ssidlist.an_ssid1, nwid.i_nwid, nwid.i_len); 550 error = ENETRESET; 551 break; 552 case SIOCG80211NWID: 553 memset(&nwid, 0, sizeof(nwid)); 554 if (sc->sc_enabled && sc->an_associated) { 555 nwid.i_len = sc->an_status.an_ssidlen; 556 memcpy(nwid.i_nwid, sc->an_status.an_ssid, nwid.i_len); 557 } else { 558 nwid.i_len = sc->an_ssidlist.an_ssid1_len; 559 memcpy(nwid.i_nwid, sc->an_ssidlist.an_ssid1, 560 nwid.i_len); 561 } 562 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); 563 break; 564 case SIOCS80211NWKEY: 565 error = an_set_nwkey(sc, (struct ieee80211_nwkey *)data); 566 break; 567 case SIOCG80211NWKEY: 568 error = an_get_nwkey(sc, (struct ieee80211_nwkey *)data); 569 break; 570 case SIOCS80211POWER: 571 power = (struct ieee80211_power *)data; 572 sc->an_config.an_psave_mode = power->i_enabled ? 573 AN_PSAVE_PSP : AN_PSAVE_NONE; 574 sc->an_config.an_listen_interval = power->i_maxsleep; 575 error = ENETRESET; 576 break; 577 case SIOCG80211POWER: 578 power = (struct ieee80211_power *)data; 579 power->i_enabled = 580 sc->an_config.an_psave_mode != AN_PSAVE_NONE ? 1 : 0; 581 power->i_maxsleep = sc->an_config.an_listen_interval; 582 break; 583#ifdef IFM_IEEE80211 584 case SIOCSIFMEDIA: 585 case SIOCGIFMEDIA: 586 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 587 break; 588#endif 589 case SIOCADDMULTI: 590 case SIOCDELMULTI: 591 error = ether_ioctl(ifp, command, data); 592 if (error == ENETRESET) { 593 /* we don't have multicast filter. */ 594 error = 0; 595 } 596 break; 597 default: 598 error = ether_ioctl(ifp, command, data); 599 break; 600 } 601 if (error == ENETRESET) { 602 if (sc->sc_enabled) 603 error = an_init(ifp); 604 else 605 error = 0; 606 } 607#ifdef ANCACHE 608out: 609#endif 610 splx(s); 611 return error; 612} 613 614static int 615an_set_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 616{ 617 int error; 618 u_int16_t prevauth; 619 620 error = 0; 621 prevauth = sc->an_config.an_authtype; 622 623 switch (nwkey->i_wepon) { 624 case IEEE80211_NWKEY_OPEN: 625 sc->an_config.an_authtype = AN_AUTHTYPE_OPEN; 626 break; 627 628 case IEEE80211_NWKEY_WEP: 629 case IEEE80211_NWKEY_WEP | IEEE80211_NWKEY_PERSIST: 630 error = an_set_nwkey_wep(sc, nwkey); 631 if (error == 0 || error == ENETRESET) 632 sc->an_config.an_authtype = 633 AN_AUTHTYPE_OPEN | AN_AUTHTYPE_PRIVACY_IN_USE; 634 break; 635 636 case IEEE80211_NWKEY_EAP: 637 error = an_set_nwkey_eap(sc, nwkey); 638 if (error == 0 || error == ENETRESET) 639 sc->an_config.an_authtype = AN_AUTHTYPE_OPEN | 640 AN_AUTHTYPE_PRIVACY_IN_USE | AN_AUTHTYPE_LEAP; 641 break; 642 default: 643 error = EINVAL; 644 break; 645 } 646 if (error == 0 && prevauth != sc->an_config.an_authtype) 647 error = ENETRESET; 648 return error; 649} 650 651static int 652an_set_nwkey_wep(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 653{ 654 int i, txkey, anysetkey, needreset, error; 655 struct an_wepkey keys[IEEE80211_WEP_NKID]; 656 657 error = 0; 658 memset(keys, 0, sizeof(keys)); 659 anysetkey = needreset = 0; 660 661 /* load argument and sanity check */ 662 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 663 keys[i].an_wep_keylen = nwkey->i_key[i].i_keylen; 664 if (keys[i].an_wep_keylen < 0) 665 continue; 666 if (keys[i].an_wep_keylen != 0 && 667 keys[i].an_wep_keylen < IEEE80211_WEP_KEYLEN) 668 return EINVAL; 669 if (keys[i].an_wep_keylen > sizeof(keys[i].an_wep_key)) 670 return EINVAL; 671 if ((error = copyin(nwkey->i_key[i].i_keydat, 672 keys[i].an_wep_key, keys[i].an_wep_keylen)) != 0) 673 return error; 674 anysetkey++; 675 } 676 txkey = nwkey->i_defkid - 1; 677 if (txkey >= 0) { 678 if (txkey >= IEEE80211_WEP_NKID) 679 return EINVAL; 680 /* default key must have a valid value */ 681 if (keys[txkey].an_wep_keylen == 0 || 682 (keys[txkey].an_wep_keylen < 0 && 683 sc->an_perskeylen[txkey] == 0)) 684 return EINVAL; 685 anysetkey++; 686 } 687 if (!(nwkey->i_wepon & IEEE80211_NWKEY_PERSIST)) { 688 /* set temporary keys */ 689 sc->an_tx_key = txkey; 690 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 691 if (keys[i].an_wep_keylen < 0) 692 continue; 693 memcpy(&sc->an_wepkeys[i], &keys[i], sizeof(keys[i])); 694 } 695 } else { 696 /* set persist keys */ 697 if (anysetkey) { 698 /* prepare to write nvram */ 699 if (!sc->sc_enabled) { 700 if (sc->sc_enable) 701 (*sc->sc_enable)(sc); 702 an_wait(sc); 703 sc->sc_enabled = 1; 704 error = an_write_wepkey(sc, 705 AN_RID_WEP_PERSISTENT, keys, txkey); 706 if (sc->sc_disable) 707 (*sc->sc_disable)(sc); 708 sc->sc_enabled = 0; 709 } else { 710 an_cmd(sc, AN_CMD_DISABLE, 0); 711 error = an_write_wepkey(sc, 712 AN_RID_WEP_PERSISTENT, keys, txkey); 713 an_cmd(sc, AN_CMD_ENABLE, 0); 714 } 715 if (error) 716 return error; 717 } 718 if (txkey >= 0) 719 sc->an_tx_perskey = txkey; 720 if (sc->an_tx_key >= 0) { 721 sc->an_tx_key = -1; 722 needreset++; 723 } 724 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 725 if (sc->an_wepkeys[i].an_wep_keylen >= 0) { 726 memset(&sc->an_wepkeys[i].an_wep_key, 0, 727 sizeof(sc->an_wepkeys[i].an_wep_key)); 728 sc->an_wepkeys[i].an_wep_keylen = -1; 729 needreset++; 730 } 731 if (keys[i].an_wep_keylen >= 0) 732 sc->an_perskeylen[i] = keys[i].an_wep_keylen; 733 } 734 } 735 if (needreset) { 736 /* firmware restart to reload persistent key */ 737 an_reset(sc); 738 } 739 if (anysetkey || needreset) 740 error = ENETRESET; 741 return error; 742} 743 744static int 745an_set_nwkey_eap(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 746{ 747 int i, error; 748 struct an_ltv_leapkey *key; 749 u_int16_t unibuf[sizeof(key->an_key)]; 750 MD4_CTX ctx; 751 752 error = 0; 753 754 if (nwkey->i_key[0].i_keydat == NULL && 755 nwkey->i_key[1].i_keydat == NULL) 756 return 0; 757 if (!sc->sc_enabled) 758 return ENXIO; 759 an_cmd(sc, AN_CMD_DISABLE, 0); 760 key = (struct an_ltv_leapkey *)&sc->an_reqbuf; 761 if (nwkey->i_key[0].i_keydat != NULL) { 762 memset(key, 0, sizeof(*key)); 763 key->an_type = AN_RID_LEAP_USER; 764 key->an_len = sizeof(*key); 765 key->an_key_len = nwkey->i_key[0].i_keylen; 766 if (key->an_key_len > sizeof(key->an_key)) 767 return EINVAL; 768 if ((error = copyin(nwkey->i_key[0].i_keydat, key->an_key, 769 key->an_key_len)) != 0) 770 return error; 771 an_write_record(sc, (struct an_ltv_gen *)key); 772 } 773 if (nwkey->i_key[1].i_keydat != NULL) { 774 memset(key, 0, sizeof(*key)); 775 key->an_type = AN_RID_LEAP_PASS; 776 key->an_len = sizeof(*key); 777 key->an_key_len = nwkey->i_key[1].i_keylen; 778 if (key->an_key_len > sizeof(key->an_key)) 779 return EINVAL; 780 if ((error = copyin(nwkey->i_key[1].i_keydat, key->an_key, 781 key->an_key_len)) != 0) 782 return error; 783 /* 784 * Cisco seems to use PasswordHash and PasswordHashHash 785 * in RFC-2759 (MS-CHAP-V2). 786 */ 787 memset(unibuf, 0, sizeof(unibuf)); 788 /* XXX: convert password to unicode */ 789 for (i = 0; i < key->an_key_len; i++) 790 unibuf[i] = key->an_key[i]; 791 /* set PasswordHash */ 792 MD4Init(&ctx); 793 MD4Update(&ctx, (u_int8_t *)unibuf, key->an_key_len * 2); 794 MD4Final(key->an_key, &ctx); 795 /* set PasswordHashHash */ 796 MD4Init(&ctx); 797 MD4Update(&ctx, key->an_key, 16); 798 MD4Final(key->an_key + 16, &ctx); 799 key->an_key_len = 32; 800 an_write_record(sc, (struct an_ltv_gen *)key); 801 } 802 error = an_cmd(sc, AN_CMD_ENABLE, 0); 803 if (error) 804 printf("%s: an_set_nwkey: failed to enable MAC\n", 805 sc->an_dev.dv_xname); 806 else 807 error = ENETRESET; 808 return error; 809} 810 811static int 812an_get_nwkey(struct an_softc *sc, struct ieee80211_nwkey *nwkey) 813{ 814 int i, error; 815 816 error = 0; 817 if (sc->an_config.an_authtype & AN_AUTHTYPE_LEAP) 818 nwkey->i_wepon = IEEE80211_NWKEY_EAP; 819 else if (sc->an_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) 820 nwkey->i_wepon = IEEE80211_NWKEY_WEP; 821 else 822 nwkey->i_wepon = IEEE80211_NWKEY_OPEN; 823 if (sc->an_tx_key == -1) 824 nwkey->i_defkid = sc->an_tx_perskey + 1; 825 else 826 nwkey->i_defkid = sc->an_tx_key + 1; 827 if (nwkey->i_key[0].i_keydat == NULL) 828 return 0; 829 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 830 if (nwkey->i_key[i].i_keydat == NULL) 831 continue; 832 /* do not show any keys to non-root user */ 833 if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0) 834 break; 835 nwkey->i_key[i].i_keylen = sc->an_wepkeys[i].an_wep_keylen; 836 if (nwkey->i_key[i].i_keylen < 0) { 837 if (sc->an_perskeylen[i] == 0) 838 nwkey->i_key[i].i_keylen = 0; 839 continue; 840 } 841 if ((error = copyout(sc->an_wepkeys[i].an_wep_key, 842 nwkey->i_key[i].i_keydat, 843 sc->an_wepkeys[i].an_wep_keylen)) != 0) 844 break; 845 } 846 return error; 847} 848 849static int 850an_write_wepkey(struct an_softc *sc, int type, struct an_wepkey *keys, int kid) 851{ 852 int i, error; 853 struct an_ltv_wepkey *akey; 854 855 error = 0; 856 akey = (struct an_ltv_wepkey *)&sc->an_reqbuf; 857 memset(akey, 0, sizeof(struct an_ltv_wepkey)); 858 akey->an_type = type; 859 akey->an_len = sizeof(struct an_ltv_wepkey); 860 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 861 if (keys[i].an_wep_keylen < 0 || 862 keys[i].an_wep_keylen > sizeof(akey->an_key)) 863 continue; 864 akey->an_key_len = keys[i].an_wep_keylen; 865 akey->an_key_index = i; 866 akey->an_mac_addr[0] = 1; /* default mac */ 867 memcpy(akey->an_key, keys[i].an_wep_key, akey->an_key_len); 868 error = an_write_record(sc, (struct an_ltv_gen *)akey); 869 if (error) 870 return error; 871 } 872 if (kid >= 0) { 873 akey->an_key_index = 0xffff; 874 akey->an_mac_addr[0] = kid; 875 akey->an_key_len = 0; 876 memset(akey->an_key, 0, sizeof(akey->an_key)); 877 error = an_write_record(sc, (struct an_ltv_gen *)akey); 878 } 879 return error; 880} 881 882#ifdef IFM_IEEE80211 883static int 884an_media_change(struct ifnet *ifp) 885{ 886 struct an_softc *sc = ifp->if_softc; 887 struct ifmedia_entry *ime; 888 int error; 889 890 error = 0; 891 ime = sc->sc_media.ifm_cur; 892 switch (IFM_SUBTYPE(ime->ifm_media)) { 893 case IFM_AUTO: 894 sc->an_tx_rate = 0; 895 break; 896 case IFM_IEEE80211_DS1: 897 sc->an_tx_rate = AN_RATE_1MBPS; 898 break; 899 case IFM_IEEE80211_DS2: 900 sc->an_tx_rate = AN_RATE_2MBPS; 901 break; 902 case IFM_IEEE80211_DS5: 903 sc->an_tx_rate = AN_RATE_5_5MBPS; 904 break; 905 case IFM_IEEE80211_DS11: 906 sc->an_tx_rate = AN_RATE_11MBPS; 907 break; 908 } 909 if (ime->ifm_media & IFM_IEEE80211_ADHOC) 910 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; 911 else 912 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 913 /* 914 * XXX: how to set txrate for the firmware? 915 * There is a struct defined as an_txframe, which is used nowhere. 916 * Perhaps we need to change the transmit mode from 802.3 to native. 917 */ 918 919 /* we cannot return ENETRESET here */ 920 if (sc->sc_enabled) 921 error = an_init(ifp); 922 return error; 923} 924 925static void 926an_media_status(ifp, imr) 927 struct ifnet *ifp; 928 struct ifmediareq *imr; 929{ 930 struct an_softc *sc = ifp->if_softc; 931 932 imr->ifm_status = IFM_AVALID; 933 imr->ifm_active = IFM_IEEE80211; 934 if (sc->sc_enabled && sc->an_associated) { 935 imr->ifm_status |= IFM_ACTIVE; 936 switch (sc->an_status.an_current_tx_rate) { 937 case 0: 938 imr->ifm_active |= IFM_AUTO; 939 break; 940 case AN_RATE_1MBPS: 941 imr->ifm_active |= IFM_IEEE80211_DS1; 942 break; 943 case AN_RATE_2MBPS: 944 imr->ifm_active |= IFM_IEEE80211_DS2; 945 break; 946 case AN_RATE_5_5MBPS: 947 imr->ifm_active |= IFM_IEEE80211_DS5; 948 break; 949 case AN_RATE_11MBPS: 950 imr->ifm_active |= IFM_IEEE80211_DS11; 951 break; 952 } 953 } 954 if ((sc->an_config.an_opmode & 0x0f) == AN_OPMODE_IBSS_ADHOC) 955 imr->ifm_active |= IFM_IEEE80211_ADHOC; 956} 957#endif /* IFM_IEEE80211 */ 958 959static int 960an_init_tx_ring(struct an_softc *sc) 961{ 962 int i, id; 963 964 for (i = 0; i < AN_TX_RING_CNT; i++) { 965 if (an_alloc_nicmem(sc, 966 ETHER_MAX_LEN + ETHER_TYPE_LEN + AN_802_11_OFFSET, &id)) 967 return ENOMEM; 968 sc->an_rdata.an_tx_fids[i] = id; 969 sc->an_rdata.an_tx_ring[i] = 0; 970 } 971 972 sc->an_rdata.an_tx_prod = 0; 973 sc->an_rdata.an_tx_cons = 0; 974 return 0; 975} 976 977static int 978an_init(struct ifnet *ifp) 979{ 980 struct an_softc *sc = (struct an_softc *)ifp->if_softc; 981 982 if (sc->sc_enabled) { 983 an_stop(ifp, 0); 984 } else { 985 if (sc->sc_enable) 986 (*sc->sc_enable)(sc); 987 sc->sc_enabled = 1; 988 an_wait(sc); 989 } 990 991 sc->an_associated = 0; 992 993 /* Allocate the TX buffers */ 994 if (an_init_tx_ring(sc)) { 995 an_reset(sc); 996 if (an_init_tx_ring(sc)) { 997 printf("%s: tx buffer allocation failed\n", 998 sc->an_dev.dv_xname); 999 an_stop(ifp, 1); 1000 return ENOMEM; 1001 } 1002 } 1003 1004 /* Set our MAC address. */ 1005 memcpy(sc->an_config.an_macaddr, sc->an_caps.an_oemaddr, 1006 ETHER_ADDR_LEN); 1007 1008 if (ifp->if_flags & IFF_MULTICAST) 1009 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1010 else if (ifp->if_flags & IFF_BROADCAST) 1011 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1012 else 1013 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1014 1015 /* Set the ssid list */ 1016 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 1017 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 1018 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 1019 printf("%s: failed to set ssid list\n", sc->an_dev.dv_xname); 1020 an_stop(ifp, 1); 1021 return ENXIO; 1022 } 1023 1024 /* Set the AP list */ 1025 sc->an_aplist.an_type = AN_RID_APLIST; 1026 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 1027 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 1028 printf("%s: failed to set AP list\n", sc->an_dev.dv_xname); 1029 an_stop(ifp, 1); 1030 return ENXIO; 1031 } 1032 1033 /* Set the configuration in the NIC */ 1034 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 1035 sc->an_config.an_type = AN_RID_GENCONFIG; 1036 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 1037 printf("%s: failed to set configuration\n", sc->an_dev.dv_xname); 1038 an_stop(ifp, 1); 1039 return ENXIO; 1040 } 1041 1042 /* Set the WEP Keys */ 1043 if ((sc->an_config.an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) != 0) 1044 an_write_wepkey(sc, AN_RID_WEP_VOLATILE, sc->an_wepkeys, 1045 sc->an_tx_key); 1046 1047 /* Enable the MAC */ 1048 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1049 printf("%s: failed to enable MAC\n", sc->an_dev.dv_xname); 1050 an_stop(ifp, 1); 1051 return ENXIO; 1052 } 1053 1054 an_cmd(sc, AN_CMD_SET_MODE, (ifp->if_flags & IFF_PROMISC) ? 0xffff : 0); 1055 1056 /* enable interrupts */ 1057 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1058 1059 ifp->if_flags |= IFF_RUNNING; 1060 ifp->if_flags &= ~IFF_OACTIVE; 1061 1062 callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc); 1063 return 0; 1064} 1065 1066static void 1067an_start(struct ifnet *ifp) 1068{ 1069 struct an_softc *sc = (struct an_softc *)ifp->if_softc; 1070 struct mbuf *m0 = NULL, *m; 1071 struct an_txframe_802_3 tx_frame_802_3; 1072 struct ether_header *eh; 1073 int id, idx; 1074 u_int16_t txctl; 1075 1076 if (!sc->sc_enabled) 1077 return; 1078 1079 if (ifp->if_flags & IFF_OACTIVE) 1080 return; 1081 1082 if (!sc->an_associated) 1083 return; 1084 1085 idx = sc->an_rdata.an_tx_prod; 1086 memset(&tx_frame_802_3, 0, sizeof(tx_frame_802_3)); 1087 1088 for (;;) { 1089 IFQ_POLL(&ifp->if_snd, m0); 1090 if (m0 == NULL) 1091 break; 1092 if (sc->an_rdata.an_tx_ring[idx] != 0) 1093 break; 1094 id = sc->an_rdata.an_tx_fids[idx]; 1095 IFQ_DEQUEUE(&ifp->if_snd, m0); 1096#if NBPFILTER > 0 1097 /* 1098 * If there's a BPF listner, bounce a copy of 1099 * this frame to him. 1100 */ 1101 if (ifp->if_bpf) 1102 bpf_mtap(ifp->if_bpf, m0); 1103#endif 1104 1105 txctl = AN_TXCTL_8023; 1106 /* write the txctl only */ 1107 an_write_data(sc, id, 0x08, (caddr_t)&txctl, sizeof(txctl)); 1108 1109 eh = mtod(m0, struct ether_header *); 1110 memcpy(tx_frame_802_3.an_tx_dst_addr, eh->ether_dhost, 1111 ETHER_ADDR_LEN); 1112 memcpy(tx_frame_802_3.an_tx_src_addr, eh->ether_shost, 1113 ETHER_ADDR_LEN); 1114 tx_frame_802_3.an_tx_802_3_payload_len = 1115 m0->m_pkthdr.len - ETHER_ADDR_LEN * 2; 1116 m_adj(m0, ETHER_ADDR_LEN * 2); 1117 1118 /* 802_3 header */ 1119 an_write_data(sc, id, AN_802_3_OFFSET, 1120 (caddr_t)&tx_frame_802_3, sizeof(struct an_txframe_802_3)); 1121 for (m = m0; m != NULL; m = m->m_next) 1122 an_write_data(sc, id, -1, mtod(m, caddr_t), m->m_len); 1123 m_freem(m0); 1124 m0 = NULL; 1125 1126 sc->an_rdata.an_tx_ring[idx] = id; 1127 if (an_cmd(sc, AN_CMD_TX, id)) 1128 printf("%s: xmit failed\n", sc->an_dev.dv_xname); 1129 1130 AN_INC(idx, AN_TX_RING_CNT); 1131 } 1132 1133 if (m0 != NULL) 1134 ifp->if_flags |= IFF_OACTIVE; 1135 1136 sc->an_rdata.an_tx_prod = idx; 1137 1138 /* 1139 * Set a timeout in case the chip goes out to lunch. 1140 */ 1141 ifp->if_timer = 5; 1142} 1143 1144void 1145an_stop(struct ifnet *ifp, int disable) 1146{ 1147 struct an_softc *sc = (struct an_softc *)ifp->if_softc; 1148 int i; 1149 1150 callout_stop(&sc->an_stat_ch); 1151 1152 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1153 ifp->if_timer = 0; 1154 1155 if (!sc->sc_enabled) 1156 return; 1157 1158 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 1159 CSR_WRITE_2(sc, AN_INT_EN, 0); 1160 an_cmd(sc, AN_CMD_DISABLE, 0); 1161 1162 for (i = 0; i < AN_TX_RING_CNT; i++) 1163 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 1164 1165 if (disable) { 1166 if (sc->sc_disable) 1167 (*sc->sc_disable)(sc); 1168 sc->sc_enabled = 0; 1169 } 1170} 1171 1172static void 1173an_watchdog(struct ifnet *ifp) 1174{ 1175 struct an_softc *sc; 1176 1177 sc = ifp->if_softc; 1178 if (!sc->sc_enabled) 1179 return; 1180 1181 printf("%s: device timeout\n", sc->an_dev.dv_xname); 1182 1183 an_reset(sc); 1184 an_init(ifp); 1185 1186 ifp->if_oerrors++; 1187 return; 1188} 1189 1190/* 1191 * Low level functions 1192 */ 1193 1194static void 1195an_rxeof(struct an_softc *sc) 1196{ 1197 struct ifnet *ifp = &sc->arpcom.ec_if; 1198 struct ether_header *eh; 1199#ifdef ANCACHE 1200 struct an_rxframe rx_frame; 1201#endif 1202 struct an_rxframe_802_3 rx_frame_802_3; 1203 struct mbuf *m; 1204 int id, error = 0; 1205 1206 1207 id = CSR_READ_2(sc, AN_RX_FID); 1208 1209 MGETHDR(m, M_DONTWAIT, MT_DATA); 1210 if (m == NULL) { 1211 ifp->if_ierrors++; 1212 return; 1213 } 1214 MCLGET(m, M_DONTWAIT); 1215 if (!(m->m_flags & M_EXT)) { 1216 m_freem(m); 1217 ifp->if_ierrors++; 1218 return; 1219 } 1220 1221 m->m_pkthdr.rcvif = ifp; 1222 1223 /* Align the data after the ethernet header */ 1224 m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header)) - 1225 sizeof(struct ether_header); 1226 1227 eh = mtod(m, struct ether_header *); 1228 1229#ifdef ANCACHE 1230 /* Read NIC frame header */ 1231 if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 1232 ifp->if_ierrors++; 1233 return; 1234 } 1235#endif 1236 /* Read in the 802_3 frame header */ 1237 if (an_read_data(sc, id, AN_802_3_OFFSET, (caddr_t)&rx_frame_802_3, 1238 sizeof(rx_frame_802_3))) { 1239 ifp->if_ierrors++; 1240 return; 1241 } 1242 1243 if (rx_frame_802_3.an_rx_802_3_status != 0) { 1244 ifp->if_ierrors++; 1245 return; 1246 } 1247 1248 /* Check for insane frame length */ 1249 if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) { 1250 ifp->if_ierrors++; 1251 return; 1252 } 1253 1254 m->m_pkthdr.len = m->m_len = 1255 rx_frame_802_3.an_rx_802_3_payload_len + ETHER_ADDR_LEN * 2; 1256 1257 memcpy(&eh->ether_dhost, &rx_frame_802_3.an_rx_dst_addr, 1258 ETHER_ADDR_LEN); 1259 memcpy(&eh->ether_shost, &rx_frame_802_3.an_rx_src_addr, 1260 ETHER_ADDR_LEN); 1261 1262 /* in mbuf header type is just before payload */ 1263 error = an_read_data(sc, id, -1, (caddr_t)&(eh->ether_type), 1264 rx_frame_802_3.an_rx_802_3_payload_len); 1265 1266 if (error) { 1267 m_freem(m); 1268 ifp->if_ierrors++; 1269 return; 1270 } 1271 1272 ifp->if_ipackets++; 1273 1274 /* Receive packet. */ 1275#ifdef ANCACHE 1276 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); 1277#endif 1278#if NBPFILTER > 0 1279 if (ifp->if_bpf) 1280 bpf_mtap(ifp->if_bpf, m); 1281#endif 1282 (*ifp->if_input)(ifp, m); 1283} 1284 1285static void 1286an_txeof(struct an_softc *sc, int status) 1287{ 1288 struct ifnet *ifp = &sc->arpcom.ec_if; 1289 int i, id; 1290 1291 ifp->if_timer = 0; 1292 ifp->if_flags &= ~IFF_OACTIVE; 1293 1294 id = CSR_READ_2(sc, AN_TX_CMP_FID); 1295 1296 if (status & AN_EV_TX_EXC) 1297 ifp->if_oerrors++; 1298 else 1299 ifp->if_opackets++; 1300 1301 /* fix from Doug Ambrisko -wsr */ 1302 for (i = 0; i < AN_TX_RING_CNT; i++) { 1303 if (id == sc->an_rdata.an_tx_ring[i]) { 1304 sc->an_rdata.an_tx_ring[i] = 0; 1305 break; 1306 } 1307 } 1308 if (i != sc->an_rdata.an_tx_cons) { 1309 if (ifp->if_flags & IFF_DEBUG) 1310 printf("%s: id mismatch: id %x, " 1311 "expected %x(%d), actual %x(%d)\n", 1312 sc->an_dev.dv_xname, id, 1313 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], 1314 sc->an_rdata.an_tx_cons, id, i); 1315 } 1316 1317 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT); 1318 1319 return; 1320} 1321 1322/* 1323 * We abuse the stats updater to check the current NIC status. This 1324 * is important because we don't want to allow transmissions until 1325 * the NIC has synchronized to the current cell (either as the master 1326 * in an ad-hoc group, or as a station connected to an access point). 1327 */ 1328void 1329an_stats_update(void *xsc) 1330{ 1331 struct an_softc *sc = xsc; 1332 1333 if (sc->sc_enabled) { 1334 sc->an_status.an_type = AN_RID_STATUS; 1335 sc->an_status.an_len = sizeof(struct an_ltv_status); 1336 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_status) 1337 == 0) { 1338 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC) 1339 sc->an_associated = 1; 1340 else 1341 sc->an_associated = 0; 1342#if 0 1343 /* Don't do this while we're transmitting */ 1344 if (sc->arpcom.ec_if.if_flags & IFF_OACTIVE) { 1345 sc->an_stats.an_len = 1346 sizeof(struct an_ltv_stats); 1347 sc->an_stats.an_type = AN_RID_32BITS_CUM; 1348 an_read_record(sc, 1349 (struct an_ltv_gen *)&sc->an_stats.an_len); 1350 } 1351#endif 1352 } 1353 } 1354 callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc); 1355} 1356 1357int 1358an_intr(void *arg) 1359{ 1360 struct an_softc *sc = arg; 1361 struct ifnet *ifp = &sc->arpcom.ec_if; 1362 u_int16_t status; 1363 1364 if (!sc->sc_enabled) 1365 return 0; 1366 1367 if (!(ifp->if_flags & IFF_UP)) { 1368 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF); 1369 CSR_WRITE_2(sc, AN_INT_EN, 0); 1370 return 0; 1371 } 1372 1373 /* Disable interrupts. */ 1374 CSR_WRITE_2(sc, AN_INT_EN, 0); 1375 1376 while ((status = (CSR_READ_2(sc, AN_EVENT_STAT) & AN_INTRS)) != 0) { 1377 if (status & AN_EV_RX) { 1378 an_rxeof(sc); 1379 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 1380 status &= ~AN_EV_RX; 1381 } 1382 if (status & (AN_EV_TX | AN_EV_TX_EXC)) { 1383 an_txeof(sc, status); 1384 CSR_WRITE_2(sc, AN_EVENT_ACK, 1385 status & (AN_EV_TX | AN_EV_TX_EXC)); 1386 status &= ~(AN_EV_TX | AN_EV_TX_EXC); 1387 } 1388 if (status & AN_EV_LINKSTAT) { 1389 if (CSR_READ_2(sc, AN_LINKSTAT) == 1390 AN_LINKSTAT_ASSOCIATED) 1391 sc->an_associated = 1; 1392 else 1393 sc->an_associated = 0; 1394 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 1395 status &= ~AN_EV_LINKSTAT; 1396 } 1397#if 0 1398 if (status & AN_EV_CMD) { 1399 wakeup(sc); 1400 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1401 status &= ~AN_EV_CMD; 1402 } 1403#endif 1404 if (status) 1405 CSR_WRITE_2(sc, AN_EVENT_ACK, status); 1406 } 1407 1408 /* Re-enable interrupts. */ 1409 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1410 1411 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1412 an_start(ifp); 1413 1414 return 1; 1415} 1416 1417static int 1418an_cmd(struct an_softc *sc, int cmd, int val) 1419{ 1420 int i, stat; 1421 1422 /* make sure that previous command completed */ 1423 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 1424 if (sc->arpcom.ec_if.if_flags & IFF_DEBUG) 1425 printf("%s: command 0x%x busy\n", sc->an_dev.dv_xname, 1426 CSR_READ_2(sc, AN_COMMAND)); 1427 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1428 } 1429 1430 CSR_WRITE_2(sc, AN_PARAM0, val); 1431 CSR_WRITE_2(sc, AN_PARAM1, 0); 1432 CSR_WRITE_2(sc, AN_PARAM2, 0); 1433 CSR_WRITE_2(sc, AN_COMMAND, cmd); 1434 1435 for (i = 0; i < AN_TIMEOUT; i++) { 1436 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1437 break; 1438 /* make sure the command is accepted */ 1439 if (CSR_READ_2(sc, AN_COMMAND) == cmd) 1440 CSR_WRITE_2(sc, AN_COMMAND, cmd); 1441 DELAY(10); 1442 } 1443 1444 stat = CSR_READ_2(sc, AN_STATUS); 1445 1446 /* clear stuck command busy if necessary */ 1447 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) 1448 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 1449 1450 /* Ack the command */ 1451 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1452 1453 if (i == AN_TIMEOUT) { 1454 if (sc->arpcom.ec_if.if_flags & IFF_DEBUG) 1455 printf("%s: command 0x%x param 0x%x timeout\n", 1456 sc->an_dev.dv_xname, cmd, val); 1457 return ETIMEDOUT; 1458 } 1459 if (stat & AN_STAT_CMD_RESULT) { 1460 if (sc->arpcom.ec_if.if_flags & IFF_DEBUG) 1461 printf("%s: command 0x%x param 0x%x stat 0x%x\n", 1462 sc->an_dev.dv_xname, cmd, val, stat); 1463 return EIO; 1464 } 1465 1466 return 0; 1467} 1468 1469/* 1470 * This reset sequence may look a little strange, but this is the 1471 * most reliable method I've found to really kick the NIC in the 1472 * head and force it to reboot correctly. 1473 */ 1474static void 1475an_reset(struct an_softc *sc) 1476{ 1477 1478 if (!sc->sc_enabled) 1479 return; 1480 1481 an_cmd(sc, AN_CMD_ENABLE, 0); 1482 an_cmd(sc, AN_CMD_FW_RESTART, 0); 1483 an_cmd(sc, AN_CMD_NOOP2, 0); 1484 1485 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) 1486 printf("%s: reset failed\n", sc->an_dev.dv_xname); 1487 1488 an_cmd(sc, AN_CMD_DISABLE, 0); 1489} 1490 1491/* 1492 * Wait for firmware come up after power enabled. 1493 */ 1494static void 1495an_wait(struct an_softc *sc) 1496{ 1497 int i; 1498 1499 CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_NOOP2); 1500 for (i = 0; i < 3*hz; i++) { 1501 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 1502 break; 1503 (void)tsleep(sc, PWAIT, "anatch", 1); 1504 } 1505 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 1506} 1507 1508/* 1509 * Read an LTV record from the NIC. 1510 */ 1511static int 1512an_read_record(struct an_softc *sc, struct an_ltv_gen *ltv) 1513{ 1514 u_int16_t *ptr; 1515 int i, len; 1516 1517 if (ltv->an_len == 0 || ltv->an_type == 0) 1518 return EINVAL; 1519 1520 /* Tell the NIC to enter record read mode. */ 1521 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 1522 return EIO; 1523 1524 /* Seek to the record. */ 1525 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 1526 return EIO; 1527 1528 /* 1529 * Read the length and record type and make sure they 1530 * match what we expect (this verifies that we have enough 1531 * room to hold all of the returned data). 1532 */ 1533 len = CSR_READ_2(sc, AN_DATA1); 1534 if (len > ltv->an_len) { 1535 if (sc->arpcom.ec_if.if_flags & IFF_DEBUG) 1536 printf("%s: RID 0x%04x record length mismatch" 1537 "-- expected %d, got %d\n", sc->an_dev.dv_xname, 1538 ltv->an_type, ltv->an_len, len); 1539 return ENOSPC; 1540 } 1541 1542 ltv->an_len = len; 1543 1544 /* Now read the data. */ 1545 ptr = <v->an_val; 1546 for (i = 0; i < (ltv->an_len - 2) >> 1; i++) 1547 ptr[i] = CSR_READ_2(sc, AN_DATA1); 1548 1549 return 0; 1550} 1551 1552/* 1553 * Same as read, except we inject data instead of reading it. 1554 */ 1555static int 1556an_write_record(struct an_softc *sc, struct an_ltv_gen *ltv) 1557{ 1558 u_int16_t *ptr; 1559 int i; 1560 1561 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 1562 return EIO; 1563 1564 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 1565 return EIO; 1566 1567 CSR_WRITE_2(sc, AN_DATA1, ltv->an_len-2); 1568 1569 ptr = <v->an_val; 1570 for (i = 0; i < (ltv->an_len - 4) >> 1; i++) 1571 CSR_WRITE_2(sc, AN_DATA1, ptr[i]); 1572 1573 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 1574 return EIO; 1575 1576 return 0; 1577} 1578 1579static int 1580an_seek(struct an_softc *sc, int id, int off, int chan) 1581{ 1582 int i, selreg, offreg; 1583 1584 switch (chan) { 1585 case AN_BAP0: 1586 selreg = AN_SEL0; 1587 offreg = AN_OFF0; 1588 break; 1589 case AN_BAP1: 1590 selreg = AN_SEL1; 1591 offreg = AN_OFF1; 1592 break; 1593 default: 1594 panic("%s: invalid chan: %x", sc->an_dev.dv_xname, chan); 1595 } 1596 1597 CSR_WRITE_2(sc, selreg, id); 1598 CSR_WRITE_2(sc, offreg, off); 1599 1600 for (i = 0; i < AN_TIMEOUT; i++) { 1601 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 1602 break; 1603 DELAY(10); 1604 } 1605 if (i == AN_TIMEOUT) { 1606 if (sc->arpcom.ec_if.if_flags & IFF_DEBUG) 1607 printf("%s: seek(0x%x, 0x%x, 0x%x) timeout\n", 1608 sc->an_dev.dv_xname, id, off, chan); 1609 return ETIMEDOUT; 1610 } 1611 1612 return 0; 1613} 1614 1615static int 1616an_read_data(struct an_softc *sc, int id, int off, caddr_t buf, int len) 1617{ 1618 int i; 1619 u_int16_t *ptr; 1620 u_int8_t *ptr2; 1621 1622 if (off != -1) { 1623 if (an_seek(sc, id, off, AN_BAP1)) 1624 return EIO; 1625 } 1626 1627 ptr = (u_int16_t *)buf; 1628 for (i = 0; i < len / 2; i++) 1629 ptr[i] = CSR_READ_2(sc, AN_DATA1); 1630 i *= 2; 1631 if (i < len){ 1632 ptr2 = (u_int8_t *)buf; 1633 ptr2[i] = CSR_READ_1(sc, AN_DATA1); 1634 } 1635 1636 return 0; 1637} 1638 1639static int 1640an_write_data(struct an_softc *sc, int id, int off, caddr_t buf, int len) 1641{ 1642 int i; 1643 u_int16_t *ptr; 1644 u_int8_t *ptr2; 1645 1646 if (off != -1) { 1647 if (an_seek(sc, id, off, AN_BAP0)) 1648 return EIO; 1649 } 1650 1651 ptr = (u_int16_t *)buf; 1652 for (i = 0; i < (len / 2); i++) 1653 CSR_WRITE_2(sc, AN_DATA0, ptr[i]); 1654 i *= 2; 1655 if (i < len){ 1656 ptr2 = (u_int8_t *)buf; 1657 CSR_WRITE_1(sc, AN_DATA0, ptr2[i]); 1658 } 1659 1660 return 0; 1661} 1662 1663/* 1664 * Allocate a region of memory inside the NIC and zero 1665 * it out. 1666 */ 1667static int 1668an_alloc_nicmem(struct an_softc *sc, int len, int *id) 1669{ 1670 int i; 1671 1672 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 1673 printf("%s: failed to allocate %d bytes on NIC\n", 1674 sc->an_dev.dv_xname, len); 1675 return ENOMEM; 1676 } 1677 1678 for (i = 0; i < AN_TIMEOUT; i++) { 1679 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 1680 break; 1681 DELAY(10); 1682 } 1683 1684 if (i == AN_TIMEOUT) 1685 return(ETIMEDOUT); 1686 1687 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 1688 *id = CSR_READ_2(sc, AN_ALLOC_FID); 1689 1690 if (an_seek(sc, *id, 0, AN_BAP0)) 1691 return EIO; 1692 1693 for (i = 0; i < len / 2; i++) 1694 CSR_WRITE_2(sc, AN_DATA0, 0); 1695 1696 return 0; 1697} 1698 1699#ifdef ANCACHE 1700/* Aironet signal strength cache code. 1701 * store signal/noise/quality on per MAC src basis in 1702 * a small fixed cache. The cache wraps if > MAX slots 1703 * used. The cache may be zeroed out to start over. 1704 * Two simple filters exist to reduce computation: 1705 * 1. ip only (literally 0x800) which may be used 1706 * to ignore some packets. It defaults to ip only. 1707 * it could be used to focus on broadcast, non-IP 802.11 beacons. 1708 * 2. multicast/broadcast only. This may be used to 1709 * ignore unicast packets and only cache signal strength 1710 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 1711 * beacons and not unicast traffic. 1712 * 1713 * The cache stores (MAC src(index), IP src (major clue), signal, 1714 * quality, noise) 1715 * 1716 * No apologies for storing IP src here. It's easy and saves much 1717 * trouble elsewhere. The cache is assumed to be INET dependent, 1718 * although it need not be. 1719 * 1720 * Note: the Aironet only has a single byte of signal strength value 1721 * in the rx frame header, and it's not scaled to anything sensible. 1722 * This is kind of lame, but it's all we've got. 1723 */ 1724 1725#ifdef documentation 1726 1727int an_sigitems; /* number of cached entries */ 1728struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 1729int an_nextitem; /* index/# of entries */ 1730 1731 1732#endif 1733 1734/* control variables for cache filtering. Basic idea is 1735 * to reduce cost (e.g., to only Mobile-IP agent beacons 1736 * which are broadcast or multicast). Still you might 1737 * want to measure signal strength anth unicast ping packets 1738 * on a pt. to pt. ant. setup. 1739 */ 1740/* set true if you want to limit cache items to broadcast/mcast 1741 * only packets (not unicast). Useful for mobile-ip beacons which 1742 * are broadcast/multicast at network layer. Default is all packets 1743 * so ping/unicast anll work say anth pt. to pt. antennae setup. 1744 */ 1745static int an_cache_mcastonly = 0; 1746#if 0 1747SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 1748 &an_cache_mcastonly, 0, ""); 1749#endif 1750 1751/* set true if you want to limit cache items to IP packets only 1752*/ 1753static int an_cache_iponly = 1; 1754#if 0 1755SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 1756 &an_cache_iponly, 0, ""); 1757#endif 1758 1759/* 1760 * an_cache_store, per rx packet store signal 1761 * strength in MAC (src) indexed cache. 1762 */ 1763static 1764void an_cache_store (sc, eh, m, rx_quality) 1765 struct an_softc *sc; 1766 struct ether_header *eh; 1767 struct mbuf *m; 1768 unsigned short rx_quality; 1769{ 1770 struct ip *ip = 0; 1771 int i; 1772 static int cache_slot = 0; /* use this cache entry */ 1773 static int wrapindex = 0; /* next "free" cache entry */ 1774 int saanp=0; 1775 1776 /* filters: 1777 * 1. ip only 1778 * 2. configurable filter to throw out unicast packets, 1779 * keep multicast only. 1780 */ 1781 1782 if ((ntohs(eh->ether_type) == 0x800)) { 1783 saanp = 1; 1784 } 1785 1786 /* filter for ip packets only 1787 */ 1788 if (an_cache_iponly && !saanp) { 1789 return; 1790 } 1791 1792 /* filter for broadcast/multicast only 1793 */ 1794 if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { 1795 return; 1796 } 1797 1798#ifdef SIGDEBUG 1799 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 1800 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 1801#endif 1802 1803 /* find the ip header. we want to store the ip_src 1804 * address. 1805 */ 1806 if (saanp) { 1807 ip = (struct ip *)(mtod(m, caddr_t) + 14); 1808 } 1809 1810 /* do a linear search for a matching MAC address 1811 * in the cache table 1812 * . MAC address is 6 bytes, 1813 * . var w_nextitem holds total number of entries already cached 1814 */ 1815 for(i = 0; i < sc->an_nextitem; i++) { 1816 if (!memcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6 )) { 1817 /* Match!, 1818 * so we already have this entry, 1819 * update the data 1820 */ 1821 break; 1822 } 1823 } 1824 1825 /* did we find a matching mac address? 1826 * if yes, then overwrite a previously existing cache entry 1827 */ 1828 if (i < sc->an_nextitem ) { 1829 cache_slot = i; 1830 } 1831 /* else, have a new address entry,so 1832 * add this new entry, 1833 * if table full, then we need to replace LRU entry 1834 */ 1835 else { 1836 1837 /* check for space in cache table 1838 * note: an_nextitem also holds number of entries 1839 * added in the cache table 1840 */ 1841 if (sc->an_nextitem < MAXANCACHE ) { 1842 cache_slot = sc->an_nextitem; 1843 sc->an_nextitem++; 1844 sc->an_sigitems = sc->an_nextitem; 1845 } 1846 /* no space found, so simply wrap anth wrap index 1847 * and "zap" the next entry 1848 */ 1849 else { 1850 if (wrapindex == MAXANCACHE) { 1851 wrapindex = 0; 1852 } 1853 cache_slot = wrapindex++; 1854 } 1855 } 1856 1857 /* invariant: cache_slot now points at some slot 1858 * in cache. 1859 */ 1860 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 1861 log(LOG_ERR, "an_cache_store, bad index: %d of " 1862 "[0..%d], gross cache error\n", 1863 cache_slot, MAXANCACHE); 1864 return; 1865 } 1866 1867 /* store items in cache 1868 * .ip source address 1869 * .mac src 1870 * .signal, etc. 1871 */ 1872 if (saanp) { 1873 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 1874 } 1875 memcpy(sc->an_sigcache[cache_slot].macsrc, eh->ether_shost, 6); 1876 1877 sc->an_sigcache[cache_slot].signal = rx_quality; 1878 1879 return; 1880} 1881#endif 1882