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