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