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