if_an.c revision 83130
1/* 2 * Copyright (c) 1997, 1998, 1999 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/dev/an/if_an.c 83130 2001-09-06 02:40:43Z jlemon $ 33 */ 34 35/* 36 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD. 37 * 38 * Written by Bill Paul <wpaul@ctr.columbia.edu> 39 * Electrical Engineering Department 40 * Columbia University, New York City 41 */ 42 43/* 44 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form. 45 * This driver supports all three device types (PCI devices are supported 46 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be 47 * supported either using hard-coded IO port/IRQ settings or via Plug 48 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates. 49 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates. 50 * 51 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially 52 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA 53 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are 54 * a couple of important differences though: 55 * 56 * - Lucent doesn't currently offer a PCI card, however Aironet does 57 * - Lucent ISA card looks to the host like a PCMCIA controller with 58 * a PCMCIA WaveLAN card inserted. This means that even desktop 59 * machines need to be configured with PCMCIA support in order to 60 * use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand 61 * actually look like normal ISA and PCI devices to the host, so 62 * no PCMCIA controller support is needed 63 * 64 * The latter point results in a small gotcha. The Aironet PCMCIA 65 * cards can be configured for one of two operating modes depending 66 * on how the Vpp1 and Vpp2 programming voltages are set when the 67 * card is activated. In order to put the card in proper PCMCIA 68 * operation (where the CIS table is visible and the interface is 69 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be 70 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages, 71 * which leaves the card in ISA/PCI mode, which prevents it from 72 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c 73 * has to be patched slightly in order to enable the Vpp voltages in 74 * order to make the Aironet PCMCIA cards work. 75 * 76 * Note that some PCMCIA controller software packages for Windows NT 77 * fail to set the voltages as well. 78 * 79 * The Aironet devices can operate in both station mode and access point 80 * mode. Typically, when programmed for station mode, the card can be set 81 * to automatically perform encapsulation/decapsulation of Ethernet II 82 * and 802.3 frames within 802.11 frames so that the host doesn't have 83 * to do it itself. This driver doesn't program the card that way: the 84 * driver handles all of the encapsulation/decapsulation itself. 85 */ 86 87#include "opt_inet.h" 88 89#ifdef INET 90#define ANCACHE /* enable signal strength cache */ 91#endif 92 93#include <sys/param.h> 94#include <sys/systm.h> 95#include <sys/sockio.h> 96#include <sys/mbuf.h> 97#include <sys/kernel.h> 98#include <sys/socket.h> 99#ifdef ANCACHE 100#include <sys/syslog.h> 101#include <sys/sysctl.h> 102#endif 103 104#include <sys/module.h> 105#include <sys/bus.h> 106#include <machine/bus.h> 107#include <sys/rman.h> 108#include <sys/mutex.h> 109#include <machine/resource.h> 110 111#include <net/if.h> 112#include <net/if_arp.h> 113#include <net/ethernet.h> 114#include <net/if_dl.h> 115#include <net/if_types.h> 116#include <net/if_ieee80211.h> 117#include <net/if_media.h> 118 119#ifdef INET 120#include <netinet/in.h> 121#include <netinet/in_systm.h> 122#include <netinet/in_var.h> 123#include <netinet/ip.h> 124#endif 125 126#include <net/bpf.h> 127 128#include <machine/md_var.h> 129 130#include <dev/an/if_aironet_ieee.h> 131#include <dev/an/if_anreg.h> 132 133#if !defined(lint) 134static const char rcsid[] = 135 "$FreeBSD: head/sys/dev/an/if_an.c 83130 2001-09-06 02:40:43Z jlemon $"; 136#endif 137 138/* These are global because we need them in sys/pci/if_an_p.c. */ 139static void an_reset __P((struct an_softc *)); 140static int an_ioctl __P((struct ifnet *, u_long, caddr_t)); 141static void an_init __P((void *)); 142static int an_init_tx_ring __P((struct an_softc *)); 143static void an_start __P((struct ifnet *)); 144static void an_watchdog __P((struct ifnet *)); 145static void an_rxeof __P((struct an_softc *)); 146static void an_txeof __P((struct an_softc *, int)); 147 148static void an_promisc __P((struct an_softc *, int)); 149static int an_cmd __P((struct an_softc *, int, int)); 150static int an_read_record __P((struct an_softc *, struct an_ltv_gen *)); 151static int an_write_record __P((struct an_softc *, struct an_ltv_gen *)); 152static int an_read_data __P((struct an_softc *, int, 153 int, caddr_t, int)); 154static int an_write_data __P((struct an_softc *, int, 155 int, caddr_t, int)); 156static int an_seek __P((struct an_softc *, int, int, int)); 157static int an_alloc_nicmem __P((struct an_softc *, int, int *)); 158static void an_stats_update __P((void *)); 159static void an_setdef __P((struct an_softc *, struct an_req *)); 160#ifdef ANCACHE 161static void an_cache_store __P((struct an_softc *, struct ether_header *, 162 struct mbuf *, unsigned short)); 163#endif 164 165static void an_dump_record __P((struct an_softc *,struct an_ltv_gen *, 166 char *)); 167 168static int an_media_change __P((struct ifnet *)); 169static void an_media_status __P((struct ifnet *, struct ifmediareq *)); 170 171static int an_dump = 0; 172/* 173 * We probe for an Aironet 4500/4800 card by attempting to 174 * read the default SSID list. On reset, the first entry in 175 * the SSID list will contain the name "tsunami." If we don't 176 * find this, then there's no card present. 177 */ 178int an_probe(dev) 179 device_t dev; 180{ 181 struct an_softc *sc = device_get_softc(dev); 182 struct an_ltv_ssidlist ssid; 183 int error; 184 185 bzero((char *)&ssid, sizeof(ssid)); 186 187 error = an_alloc_port(dev, 0, AN_IOSIZ); 188 if (error != 0) 189 return (0); 190 191 /* can't do autoprobing */ 192 if (rman_get_start(sc->port_res) == -1) 193 return(0); 194 195 /* 196 * We need to fake up a softc structure long enough 197 * to be able to issue commands and call some of the 198 * other routines. 199 */ 200 sc->an_bhandle = rman_get_bushandle(sc->port_res); 201 sc->an_btag = rman_get_bustag(sc->port_res); 202 sc->an_unit = device_get_unit(dev); 203 204 ssid.an_len = sizeof(ssid); 205 ssid.an_type = AN_RID_SSIDLIST; 206 207 /* Make sure interrupts are disabled. */ 208 CSR_WRITE_2(sc, AN_INT_EN, 0); 209 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF); 210 211 an_reset(sc); 212 213 if (an_cmd(sc, AN_CMD_READCFG, 0)) 214 return(0); 215 216 if (an_read_record(sc, (struct an_ltv_gen *)&ssid)) 217 return(0); 218 219 /* See if the ssid matches what we expect ... but doesn't have to */ 220 if (strcmp(ssid.an_ssid1, AN_DEF_SSID)) 221 return(0); 222 223 return(AN_IOSIZ); 224} 225 226/* 227 * Allocate a port resource with the given resource id. 228 */ 229int 230an_alloc_port(dev, rid, size) 231 device_t dev; 232 int rid; 233 int size; 234{ 235 struct an_softc *sc = device_get_softc(dev); 236 struct resource *res; 237 238 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 239 0ul, ~0ul, size, RF_ACTIVE); 240 if (res) { 241 sc->port_rid = rid; 242 sc->port_res = res; 243 return (0); 244 } else { 245 return (ENOENT); 246 } 247} 248 249/* 250 * Allocate an irq resource with the given resource id. 251 */ 252int 253an_alloc_irq(dev, rid, flags) 254 device_t dev; 255 int rid; 256 int flags; 257{ 258 struct an_softc *sc = device_get_softc(dev); 259 struct resource *res; 260 261 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 262 0ul, ~0ul, 1, (RF_ACTIVE | flags)); 263 if (res) { 264 sc->irq_rid = rid; 265 sc->irq_res = res; 266 return (0); 267 } else { 268 return (ENOENT); 269 } 270} 271 272/* 273 * Release all resources 274 */ 275void 276an_release_resources(dev) 277 device_t dev; 278{ 279 struct an_softc *sc = device_get_softc(dev); 280 281 if (sc->port_res) { 282 bus_release_resource(dev, SYS_RES_IOPORT, 283 sc->port_rid, sc->port_res); 284 sc->port_res = 0; 285 } 286 if (sc->irq_res) { 287 bus_release_resource(dev, SYS_RES_IRQ, 288 sc->irq_rid, sc->irq_res); 289 sc->irq_res = 0; 290 } 291} 292 293int an_attach(sc, unit, flags) 294 struct an_softc *sc; 295 int unit; 296 int flags; 297{ 298 struct ifnet *ifp = &sc->arpcom.ac_if; 299 300 mtx_init(&sc->an_mtx, device_get_nameunit(sc->an_dev), MTX_DEF | 301 MTX_RECURSE); 302 AN_LOCK(sc); 303 304 sc->an_gone = 0; 305 sc->an_associated = 0; 306 307 /* Reset the NIC. */ 308 an_reset(sc); 309 310 /* Load factory config */ 311 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 312 printf("an%d: failed to load config data\n", sc->an_unit); 313 AN_UNLOCK(sc); 314 mtx_destroy(&sc->an_mtx); 315 return(EIO); 316 } 317 318 /* Read the current configuration */ 319 sc->an_config.an_type = AN_RID_GENCONFIG; 320 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 321 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 322 printf("an%d: read record failed\n", sc->an_unit); 323 AN_UNLOCK(sc); 324 mtx_destroy(&sc->an_mtx); 325 return(EIO); 326 } 327 328 /* Read the card capabilities */ 329 sc->an_caps.an_type = AN_RID_CAPABILITIES; 330 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 331 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 332 printf("an%d: read record failed\n", sc->an_unit); 333 AN_UNLOCK(sc); 334 mtx_destroy(&sc->an_mtx); 335 return(EIO); 336 } 337 338 /* Read ssid list */ 339 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 340 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 341 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 342 printf("an%d: read record failed\n", sc->an_unit); 343 AN_UNLOCK(sc); 344 mtx_destroy(&sc->an_mtx); 345 return(EIO); 346 } 347 348 /* Read AP list */ 349 sc->an_aplist.an_type = AN_RID_APLIST; 350 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 351 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 352 printf("an%d: read record failed\n", sc->an_unit); 353 AN_UNLOCK(sc); 354 mtx_destroy(&sc->an_mtx); 355 return(EIO); 356 } 357 358 bcopy((char *)&sc->an_caps.an_oemaddr, 359 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 360 361 printf("an%d: Ethernet address: %6D\n", sc->an_unit, 362 sc->arpcom.ac_enaddr, ":"); 363 364 ifp->if_softc = sc; 365 ifp->if_unit = sc->an_unit = unit; 366 ifp->if_name = "an"; 367 ifp->if_mtu = ETHERMTU; 368 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 369 ifp->if_ioctl = an_ioctl; 370 ifp->if_output = ether_output; 371 ifp->if_start = an_start; 372 ifp->if_watchdog = an_watchdog; 373 ifp->if_init = an_init; 374 ifp->if_baudrate = 10000000; 375 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 376 377 bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); 378 bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename, 379 sizeof(AN_DEFAULT_NODENAME) - 1); 380 381 bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1)); 382 bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1, 383 sizeof(AN_DEFAULT_NETNAME) - 1); 384 sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME); 385 386 sc->an_config.an_opmode = 387 AN_OPMODE_INFRASTRUCTURE_STATION; 388 389 sc->an_tx_rate = 0; 390 bzero((char *)&sc->an_stats, sizeof(sc->an_stats)); 391 392 ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status); 393#define ADD(m, c) ifmedia_add(&sc->an_ifmedia, (m), (c), NULL) 394 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 395 IFM_IEEE80211_ADHOC, 0), 0); 396 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); 397 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 398 IFM_IEEE80211_ADHOC, 0), 0); 399 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); 400 if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) { 401 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 402 IFM_IEEE80211_ADHOC, 0), 0); 403 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); 404 } 405 if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) { 406 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 407 IFM_IEEE80211_ADHOC, 0), 0); 408 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); 409 } 410 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 411 IFM_IEEE80211_ADHOC, 0), 0); 412 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); 413#undef ADD 414 ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 415 0, 0)); 416 417 /* 418 * Call MI attach routine. 419 */ 420 ether_ifattach(ifp, ETHER_BPF_SUPPORTED); 421 callout_handle_init(&sc->an_stat_ch); 422 AN_UNLOCK(sc); 423 424 return(0); 425} 426 427static void an_rxeof(sc) 428 struct an_softc *sc; 429{ 430 struct ifnet *ifp; 431 struct ether_header *eh; 432#ifdef ANCACHE 433 struct an_rxframe rx_frame; 434#endif 435 struct an_rxframe_802_3 rx_frame_802_3; 436 struct mbuf *m; 437 int id, error = 0; 438 439 ifp = &sc->arpcom.ac_if; 440 441 id = CSR_READ_2(sc, AN_RX_FID); 442 443 MGETHDR(m, M_DONTWAIT, MT_DATA); 444 if (m == NULL) { 445 ifp->if_ierrors++; 446 return; 447 } 448 MCLGET(m, M_DONTWAIT); 449 if (!(m->m_flags & M_EXT)) { 450 m_freem(m); 451 ifp->if_ierrors++; 452 return; 453 } 454 455 m->m_pkthdr.rcvif = ifp; 456 457 eh = mtod(m, struct ether_header *); 458 459#ifdef ANCACHE 460 /* Read NIC frame header */ 461 if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 462 ifp->if_ierrors++; 463 return; 464 } 465#endif 466 /* Read in the 802_3 frame header */ 467 if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3, 468 sizeof(rx_frame_802_3))) { 469 ifp->if_ierrors++; 470 return; 471 } 472 473 if (rx_frame_802_3.an_rx_802_3_status != 0) { 474 ifp->if_ierrors++; 475 return; 476 } 477 478 /* Check for insane frame length */ 479 if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) { 480 ifp->if_ierrors++; 481 return; 482 } 483 484 m->m_pkthdr.len = m->m_len = 485 rx_frame_802_3.an_rx_802_3_payload_len + 12; 486 487 488 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr, 489 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 490 bcopy((char *)&rx_frame_802_3.an_rx_src_addr, 491 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 492 493 /* in mbuf header type is just before payload */ 494 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type), 495 rx_frame_802_3.an_rx_802_3_payload_len); 496 497 if (error != 0) { 498 m_freem(m); 499 ifp->if_ierrors++; 500 return; 501 } 502 503 ifp->if_ipackets++; 504 505 /* Receive packet. */ 506 m_adj(m, sizeof(struct ether_header)); 507#ifdef ANCACHE 508 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); 509#endif 510 ether_input(ifp, eh, m); 511} 512 513static void an_txeof(sc, status) 514 struct an_softc *sc; 515 int status; 516{ 517 struct ifnet *ifp; 518 int id, i; 519 520 /* TX DONE enable lan monitor DJA 521 an_enable_sniff(); 522 */ 523 524 ifp = &sc->arpcom.ac_if; 525 526 ifp->if_timer = 0; 527 ifp->if_flags &= ~IFF_OACTIVE; 528 529 id = CSR_READ_2(sc, AN_TX_CMP_FID); 530 531 if (status & AN_EV_TX_EXC) { 532 ifp->if_oerrors++; 533 } else 534 ifp->if_opackets++; 535 536 for (i = 0; i < AN_TX_RING_CNT; i++) { 537 if (id == sc->an_rdata.an_tx_ring[i]) { 538 sc->an_rdata.an_tx_ring[i] = 0; 539 break; 540 } 541 } 542 543 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT); 544 545 return; 546} 547 548/* 549 * We abuse the stats updater to check the current NIC status. This 550 * is important because we don't want to allow transmissions until 551 * the NIC has synchronized to the current cell (either as the master 552 * in an ad-hoc group, or as a station connected to an access point). 553 */ 554void an_stats_update(xsc) 555 void *xsc; 556{ 557 struct an_softc *sc; 558 struct ifnet *ifp; 559 560 sc = xsc; 561 AN_LOCK(sc); 562 ifp = &sc->arpcom.ac_if; 563 564 sc->an_status.an_type = AN_RID_STATUS; 565 sc->an_status.an_len = sizeof(struct an_ltv_status); 566 an_read_record(sc, (struct an_ltv_gen *)&sc->an_status); 567 568 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC) 569 sc->an_associated = 1; 570 else 571 sc->an_associated = 0; 572 573 /* Don't do this while we're transmitting */ 574 if (ifp->if_flags & IFF_OACTIVE) { 575 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 576 AN_UNLOCK(sc); 577 return; 578 } 579 580 sc->an_stats.an_len = sizeof(struct an_ltv_stats); 581 sc->an_stats.an_type = AN_RID_32BITS_CUM; 582 an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len); 583 584 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 585 AN_UNLOCK(sc); 586 587 return; 588} 589 590void an_intr(xsc) 591 void *xsc; 592{ 593 struct an_softc *sc; 594 struct ifnet *ifp; 595 u_int16_t status; 596 597 sc = (struct an_softc*)xsc; 598 599 AN_LOCK(sc); 600 601 if (sc->an_gone) { 602 AN_UNLOCK(sc); 603 return; 604 } 605 606 ifp = &sc->arpcom.ac_if; 607 608 /* Disable interrupts. */ 609 CSR_WRITE_2(sc, AN_INT_EN, 0); 610 611 status = CSR_READ_2(sc, AN_EVENT_STAT); 612 CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS); 613 614 if (status & AN_EV_AWAKE) { 615 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE); 616 } 617 618 if (status & AN_EV_LINKSTAT) { 619 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED) 620 sc->an_associated = 1; 621 else 622 sc->an_associated = 0; 623 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 624 } 625 626 if (status & AN_EV_RX) { 627 an_rxeof(sc); 628 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 629 } 630 631 if (status & AN_EV_TX) { 632 an_txeof(sc, status); 633 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX); 634 } 635 636 if (status & AN_EV_TX_EXC) { 637 an_txeof(sc, status); 638 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC); 639 } 640 641 if (status & AN_EV_ALLOC) 642 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 643 644 /* Re-enable interrupts. */ 645 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 646 647 if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL)) 648 an_start(ifp); 649 650 AN_UNLOCK(sc); 651 652 return; 653} 654 655static int an_cmd(sc, cmd, val) 656 struct an_softc *sc; 657 int cmd; 658 int val; 659{ 660 int i, s = 0; 661 662 CSR_WRITE_2(sc, AN_PARAM0, val); 663 CSR_WRITE_2(sc, AN_PARAM1, 0); 664 CSR_WRITE_2(sc, AN_PARAM2, 0); 665 CSR_WRITE_2(sc, AN_COMMAND, cmd); 666 667 for (i = 0; i < AN_TIMEOUT; i++) { 668 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 669 break; 670 else { 671 if (CSR_READ_2(sc, AN_COMMAND) == cmd) 672 CSR_WRITE_2(sc, AN_COMMAND, cmd); 673 } 674 } 675 676 for (i = 0; i < AN_TIMEOUT; i++) { 677 CSR_READ_2(sc, AN_RESP0); 678 CSR_READ_2(sc, AN_RESP1); 679 CSR_READ_2(sc, AN_RESP2); 680 s = CSR_READ_2(sc, AN_STATUS); 681 if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE)) 682 break; 683 } 684 685 /* Ack the command */ 686 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 687 688 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) 689 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 690 691 if (i == AN_TIMEOUT) 692 return(ETIMEDOUT); 693 694 return(0); 695} 696 697/* 698 * This reset sequence may look a little strange, but this is the 699 * most reliable method I've found to really kick the NIC in the 700 * head and force it to reboot correctly. 701 */ 702static void an_reset(sc) 703 struct an_softc *sc; 704{ 705 if (sc->an_gone) 706 return; 707 708 an_cmd(sc, AN_CMD_ENABLE, 0); 709 an_cmd(sc, AN_CMD_FW_RESTART, 0); 710 an_cmd(sc, AN_CMD_NOOP2, 0); 711 712 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) 713 printf("an%d: reset failed\n", sc->an_unit); 714 715 an_cmd(sc, AN_CMD_DISABLE, 0); 716 717 return; 718} 719 720/* 721 * Read an LTV record from the NIC. 722 */ 723static int an_read_record(sc, ltv) 724 struct an_softc *sc; 725 struct an_ltv_gen *ltv; 726{ 727 u_int16_t *ptr; 728 u_int8_t *ptr2; 729 int i, len; 730 731 if (ltv->an_len < 4 || ltv->an_type == 0) 732 return(EINVAL); 733 734 /* Tell the NIC to enter record read mode. */ 735 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) { 736 printf("an%d: RID access failed\n", sc->an_unit); 737 return(EIO); 738 } 739 740 /* Seek to the record. */ 741 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) { 742 printf("an%d: seek to record failed\n", sc->an_unit); 743 return(EIO); 744 } 745 746 /* 747 * Read the length and record type and make sure they 748 * match what we expect (this verifies that we have enough 749 * room to hold all of the returned data). 750 * Length includes type but not length. 751 */ 752 len = CSR_READ_2(sc, AN_DATA1); 753 if (len > (ltv->an_len - 2)) { 754 printf("an%d: record length mismatch -- expected %d, " 755 "got %d for Rid %x\n", sc->an_unit, 756 ltv->an_len - 2, len, ltv->an_type); 757 len = ltv->an_len - 2; 758 } else { 759 ltv->an_len = len + 2; 760 } 761 762 /* Now read the data. */ 763 len -= 2; /* skip the type */ 764 ptr = <v->an_val; 765 for (i = len; i > 1; i -= 2) 766 *ptr++ = CSR_READ_2(sc, AN_DATA1); 767 if (i) { 768 ptr2 = (u_int8_t *)ptr; 769 *ptr2 = CSR_READ_1(sc, AN_DATA1); 770 } 771 if (an_dump) 772 an_dump_record(sc, ltv, "Read"); 773 774 return(0); 775} 776 777/* 778 * Same as read, except we inject data instead of reading it. 779 */ 780static int an_write_record(sc, ltv) 781 struct an_softc *sc; 782 struct an_ltv_gen *ltv; 783{ 784 u_int16_t *ptr; 785 u_int8_t *ptr2; 786 int i, len; 787 788 if (an_dump) 789 an_dump_record(sc, ltv, "Write"); 790 791 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 792 return(EIO); 793 794 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 795 return(EIO); 796 797 /* 798 * Length includes type but not length. 799 */ 800 len = ltv->an_len - 2; 801 CSR_WRITE_2(sc, AN_DATA1, len); 802 803 len -= 2; /* skip the type */ 804 ptr = <v->an_val; 805 for (i = len; i > 1; i -= 2) 806 CSR_WRITE_2(sc, AN_DATA1, *ptr++); 807 if (i) { 808 ptr2 = (u_int8_t *)ptr; 809 CSR_WRITE_1(sc, AN_DATA0, *ptr2); 810 } 811 812 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 813 return(EIO); 814 815 return(0); 816} 817 818static void an_dump_record(sc, ltv, string) 819 struct an_softc *sc; 820 struct an_ltv_gen *ltv; 821 char *string; 822{ 823 u_int8_t *ptr2; 824 int len; 825 int i; 826 int count = 0; 827 char buf[17], temp; 828 829 len = ltv->an_len - 4; 830 printf("an%d: RID %4x, Length %4d, Mode %s\n", 831 sc->an_unit, ltv->an_type, ltv->an_len - 4, string); 832 833 if (an_dump == 1 || (an_dump == ltv->an_type)) { 834 printf("an%d:\t", sc->an_unit); 835 bzero(buf,sizeof(buf)); 836 837 ptr2 = (u_int8_t *)<v->an_val; 838 for (i = len; i > 0; i--) { 839 printf("%02x ", *ptr2); 840 841 temp = *ptr2++; 842 if (temp >= ' ' && temp <= '~') 843 buf[count] = temp; 844 else if (temp >= 'A' && temp <= 'Z') 845 buf[count] = temp; 846 else 847 buf[count] = '.'; 848 if (++count == 16) { 849 count = 0; 850 printf("%s\n",buf); 851 printf("an%d:\t", sc->an_unit); 852 bzero(buf,sizeof(buf)); 853 } 854 } 855 for (; count != 16; count++) { 856 printf(" "); 857 } 858 printf(" %s\n",buf); 859 } 860} 861 862static int an_seek(sc, id, off, chan) 863 struct an_softc *sc; 864 int id, off, chan; 865{ 866 int i; 867 int selreg, offreg; 868 869 switch (chan) { 870 case AN_BAP0: 871 selreg = AN_SEL0; 872 offreg = AN_OFF0; 873 break; 874 case AN_BAP1: 875 selreg = AN_SEL1; 876 offreg = AN_OFF1; 877 break; 878 default: 879 printf("an%d: invalid data path: %x\n", sc->an_unit, chan); 880 return(EIO); 881 } 882 883 CSR_WRITE_2(sc, selreg, id); 884 CSR_WRITE_2(sc, offreg, off); 885 886 for (i = 0; i < AN_TIMEOUT; i++) { 887 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 888 break; 889 } 890 891 if (i == AN_TIMEOUT) 892 return(ETIMEDOUT); 893 894 return(0); 895} 896 897static int an_read_data(sc, id, off, buf, len) 898 struct an_softc *sc; 899 int id, off; 900 caddr_t buf; 901 int len; 902{ 903 int i; 904 u_int16_t *ptr; 905 u_int8_t *ptr2; 906 907 if (off != -1) { 908 if (an_seek(sc, id, off, AN_BAP1)) 909 return(EIO); 910 } 911 912 ptr = (u_int16_t *)buf; 913 for (i = len; i > 1; i -= 2) 914 *ptr++ = CSR_READ_2(sc, AN_DATA1); 915 if (i) { 916 ptr2 = (u_int8_t *)ptr; 917 *ptr2 = CSR_READ_1(sc, AN_DATA1); 918 } 919 920 return(0); 921} 922 923static int an_write_data(sc, id, off, buf, len) 924 struct an_softc *sc; 925 int id, off; 926 caddr_t buf; 927 int len; 928{ 929 int i; 930 u_int16_t *ptr; 931 u_int8_t *ptr2; 932 933 if (off != -1) { 934 if (an_seek(sc, id, off, AN_BAP0)) 935 return(EIO); 936 } 937 938 ptr = (u_int16_t *)buf; 939 for (i = len; i > 1; i -= 2) 940 CSR_WRITE_2(sc, AN_DATA0, *ptr++); 941 if (i) { 942 ptr2 = (u_int8_t *)ptr; 943 CSR_WRITE_1(sc, AN_DATA0, *ptr2); 944 } 945 946 return(0); 947} 948 949/* 950 * Allocate a region of memory inside the NIC and zero 951 * it out. 952 */ 953static int an_alloc_nicmem(sc, len, id) 954 struct an_softc *sc; 955 int len; 956 int *id; 957{ 958 int i; 959 960 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 961 printf("an%d: failed to allocate %d bytes on NIC\n", 962 sc->an_unit, len); 963 return(ENOMEM); 964 } 965 966 for (i = 0; i < AN_TIMEOUT; i++) { 967 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 968 break; 969 } 970 971 if (i == AN_TIMEOUT) 972 return(ETIMEDOUT); 973 974 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 975 *id = CSR_READ_2(sc, AN_ALLOC_FID); 976 977 if (an_seek(sc, *id, 0, AN_BAP0)) 978 return(EIO); 979 980 for (i = 0; i < len / 2; i++) 981 CSR_WRITE_2(sc, AN_DATA0, 0); 982 983 return(0); 984} 985 986static void an_setdef(sc, areq) 987 struct an_softc *sc; 988 struct an_req *areq; 989{ 990 struct sockaddr_dl *sdl; 991 struct ifaddr *ifa; 992 struct ifnet *ifp; 993 struct an_ltv_genconfig *cfg; 994 struct an_ltv_ssidlist *ssid; 995 struct an_ltv_aplist *ap; 996 struct an_ltv_gen *sp; 997 998 ifp = &sc->arpcom.ac_if; 999 1000 switch (areq->an_type) { 1001 case AN_RID_GENCONFIG: 1002 cfg = (struct an_ltv_genconfig *)areq; 1003 1004 ifa = ifaddr_byindex(ifp->if_index); 1005 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1006 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr, 1007 ETHER_ADDR_LEN); 1008 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN); 1009 1010 bcopy((char *)cfg, (char *)&sc->an_config, 1011 sizeof(struct an_ltv_genconfig)); 1012 break; 1013 case AN_RID_SSIDLIST: 1014 ssid = (struct an_ltv_ssidlist *)areq; 1015 bcopy((char *)ssid, (char *)&sc->an_ssidlist, 1016 sizeof(struct an_ltv_ssidlist)); 1017 break; 1018 case AN_RID_APLIST: 1019 ap = (struct an_ltv_aplist *)areq; 1020 bcopy((char *)ap, (char *)&sc->an_aplist, 1021 sizeof(struct an_ltv_aplist)); 1022 break; 1023 case AN_RID_TX_SPEED: 1024 sp = (struct an_ltv_gen *)areq; 1025 sc->an_tx_rate = sp->an_val; 1026 break; 1027 case AN_RID_WEP_TEMP: 1028 /* Disable the MAC. */ 1029 an_cmd(sc, AN_CMD_DISABLE, 0); 1030 1031 /* Just write the Key, we don't want to save it */ 1032 an_write_record(sc, (struct an_ltv_gen *)areq); 1033 1034 /* Turn the MAC back on. */ 1035 an_cmd(sc, AN_CMD_ENABLE, 0); 1036 1037 break; 1038 case AN_RID_WEP_PERM: 1039 1040 /* Disable the MAC. */ 1041 an_cmd(sc, AN_CMD_DISABLE, 0); 1042 1043 /* Just write the Key, the card will save it in this mode */ 1044 an_write_record(sc, (struct an_ltv_gen *)areq); 1045 1046 /* Turn the MAC back on. */ 1047 an_cmd(sc, AN_CMD_ENABLE, 0); 1048 1049 break; 1050 default: 1051 printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type); 1052 return; 1053 break; 1054 } 1055 1056 1057 /* Reinitialize the card. */ 1058 if (ifp->if_flags) 1059 an_init(sc); 1060 1061 return; 1062} 1063 1064/* 1065 * We can't change the NIC configuration while the MAC is enabled, 1066 * so in order to turn on RX monitor mode, we have to turn the MAC 1067 * off first. 1068 */ 1069static void an_promisc(sc, promisc) 1070 struct an_softc *sc; 1071 int promisc; 1072{ 1073 an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0); 1074 1075 return; 1076} 1077 1078static int an_ioctl(ifp, command, data) 1079 struct ifnet *ifp; 1080 u_long command; 1081 caddr_t data; 1082{ 1083 int error = 0; 1084 int len; 1085 int i; 1086 struct an_softc *sc; 1087 struct an_req areq; 1088 struct ifreq *ifr; 1089 struct proc *p = curproc; 1090 struct ieee80211req *ireq; 1091 u_int8_t tmpstr[IEEE80211_NWID_LEN*2]; 1092 u_int8_t *tmpptr; 1093 struct an_ltv_genconfig *config; 1094 struct an_ltv_key *key; 1095 struct an_ltv_status *status; 1096 struct an_ltv_ssidlist *ssids; 1097 1098 sc = ifp->if_softc; 1099 AN_LOCK(sc); 1100 ifr = (struct ifreq *)data; 1101 ireq = (struct ieee80211req *)data; 1102 1103 config = (struct an_ltv_genconfig *)&areq; 1104 key = (struct an_ltv_key *)&areq; 1105 status = (struct an_ltv_status *)&areq; 1106 ssids = (struct an_ltv_ssidlist *)&areq; 1107 1108 if (sc->an_gone) { 1109 error = ENODEV; 1110 goto out; 1111 } 1112 1113 switch(command) { 1114 case SIOCSIFADDR: 1115 case SIOCGIFADDR: 1116 case SIOCSIFMTU: 1117 error = ether_ioctl(ifp, command, data); 1118 break; 1119 case SIOCSIFFLAGS: 1120 if (ifp->if_flags & IFF_UP) { 1121 if (ifp->if_flags & IFF_RUNNING && 1122 ifp->if_flags & IFF_PROMISC && 1123 !(sc->an_if_flags & IFF_PROMISC)) { 1124 an_promisc(sc, 1); 1125 } else if (ifp->if_flags & IFF_RUNNING && 1126 !(ifp->if_flags & IFF_PROMISC) && 1127 sc->an_if_flags & IFF_PROMISC) { 1128 an_promisc(sc, 0); 1129 } else 1130 an_init(sc); 1131 } else { 1132 if (ifp->if_flags & IFF_RUNNING) 1133 an_stop(sc); 1134 } 1135 sc->an_if_flags = ifp->if_flags; 1136 error = 0; 1137 break; 1138 case SIOCSIFMEDIA: 1139 case SIOCGIFMEDIA: 1140 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command); 1141 break; 1142 case SIOCADDMULTI: 1143 case SIOCDELMULTI: 1144 /* The Aironet has no multicast filter. */ 1145 error = 0; 1146 break; 1147 case SIOCGAIRONET: 1148 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1149 if (error != 0) 1150 break; 1151#ifdef ANCACHE 1152 if (areq.an_type == AN_RID_ZERO_CACHE) { 1153 sc->an_sigitems = sc->an_nextitem = 0; 1154 break; 1155 } else if (areq.an_type == AN_RID_READ_CACHE) { 1156 char *pt = (char *)&areq.an_val; 1157 bcopy((char *)&sc->an_sigitems, (char *)pt, 1158 sizeof(int)); 1159 pt += sizeof(int); 1160 areq.an_len = sizeof(int) / 2; 1161 bcopy((char *)&sc->an_sigcache, (char *)pt, 1162 sizeof(struct an_sigcache) * sc->an_sigitems); 1163 areq.an_len += ((sizeof(struct an_sigcache) * 1164 sc->an_sigitems) / 2) + 1; 1165 } else 1166#endif 1167 if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { 1168 error = EINVAL; 1169 break; 1170 } 1171 error = copyout(&areq, ifr->ifr_data, sizeof(areq)); 1172 break; 1173 case SIOCSAIRONET: 1174 if ((error = suser(p))) 1175 goto out; 1176 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1177 if (error != 0) 1178 break; 1179 an_setdef(sc, &areq); 1180 break; 1181 case SIOCG80211: 1182 areq.an_len = sizeof(areq); 1183 switch(ireq->i_type) { 1184 case IEEE80211_IOC_SSID: 1185 if (ireq->i_val == -1) { 1186 areq.an_type = AN_RID_STATUS; 1187 if (an_read_record(sc, 1188 (struct an_ltv_gen *)&areq)) { 1189 error = EINVAL; 1190 break; 1191 } 1192 len = status->an_ssidlen; 1193 tmpptr = status->an_ssid; 1194 } else if (ireq->i_val >= 0) { 1195 areq.an_type = AN_RID_SSIDLIST; 1196 if (an_read_record(sc, 1197 (struct an_ltv_gen *)&areq)) { 1198 error = EINVAL; 1199 break; 1200 } 1201 if (ireq->i_val == 0) { 1202 len = ssids->an_ssid1_len; 1203 tmpptr = ssids->an_ssid1; 1204 } else if (ireq->i_val == 1) { 1205 len = ssids->an_ssid2_len; 1206 tmpptr = ssids->an_ssid3; 1207 } else if (ireq->i_val == 1) { 1208 len = ssids->an_ssid3_len; 1209 tmpptr = ssids->an_ssid3; 1210 } else { 1211 error = EINVAL; 1212 break; 1213 } 1214 } else { 1215 error = EINVAL; 1216 break; 1217 } 1218 if (len > IEEE80211_NWID_LEN) { 1219 error = EINVAL; 1220 break; 1221 } 1222 ireq->i_len = len; 1223 bzero(tmpstr, IEEE80211_NWID_LEN); 1224 bcopy(tmpptr, tmpstr, len); 1225 error = copyout(tmpstr, ireq->i_data, 1226 IEEE80211_NWID_LEN); 1227 break; 1228 case IEEE80211_IOC_NUMSSIDS: 1229 ireq->i_val = 3; 1230 break; 1231 case IEEE80211_IOC_WEP: 1232 areq.an_type = AN_RID_ACTUALCFG; 1233 if (an_read_record(sc, 1234 (struct an_ltv_gen *)&areq)) { 1235 error = EINVAL; 1236 break; 1237 } 1238 if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) { 1239 if (config->an_authtype & 1240 AN_AUTHTYPE_ALLOW_UNENCRYPTED) 1241 ireq->i_val = IEEE80211_WEP_MIXED; 1242 else 1243 ireq->i_val = IEEE80211_WEP_ON; 1244 1245 } else { 1246 ireq->i_val = IEEE80211_WEP_OFF; 1247 } 1248 break; 1249 case IEEE80211_IOC_WEPKEY: 1250 /* 1251 * XXX: I'm not entierly convinced this is 1252 * correct, but it's what is implemented in 1253 * ancontrol so it will have to do until we get 1254 * access to actual Cisco code. 1255 */ 1256 if (ireq->i_val < 0 || ireq->i_val > 7) { 1257 error = EINVAL; 1258 break; 1259 } 1260 len = 0; 1261 if (ireq->i_val < 4) { 1262 areq.an_type = AN_RID_WEP_TEMP; 1263 for (i = 0; i < 5; i++) { 1264 if (an_read_record(sc, 1265 (struct an_ltv_gen *)&areq)) { 1266 error = EINVAL; 1267 break; 1268 } 1269 if (key->kindex == 0xffff) 1270 break; 1271 if (key->kindex == ireq->i_val) 1272 len = key->klen; 1273 /* Required to get next entry */ 1274 areq.an_type = AN_RID_WEP_PERM; 1275 } 1276 if (error != 0) 1277 break; 1278 } 1279 /* We aren't allowed to read the value of the 1280 * key from the card so we just output zeros 1281 * like we would if we could read the card, but 1282 * denied the user access. 1283 */ 1284 bzero(tmpstr, len); 1285 ireq->i_len = len; 1286 error = copyout(tmpstr, ireq->i_data, len); 1287 break; 1288 case IEEE80211_IOC_NUMWEPKEYS: 1289 ireq->i_val = 8; 1290 break; 1291 case IEEE80211_IOC_WEPTXKEY: 1292 /* 1293 * For some strange reason, you have to read all 1294 * keys before you can read the txkey. 1295 */ 1296 areq.an_type = AN_RID_WEP_TEMP; 1297 for (i = 0; i < 5; i++) { 1298 if (an_read_record(sc, 1299 (struct an_ltv_gen *)&areq)) { 1300 error = EINVAL; 1301 break; 1302 } 1303 if (key->kindex == 0xffff) 1304 break; 1305 /* Required to get next entry */ 1306 areq.an_type = AN_RID_WEP_PERM; 1307 } 1308 if (error != 0) 1309 break; 1310 1311 areq.an_type = AN_RID_WEP_PERM; 1312 key->kindex = 0xffff; 1313 if (an_read_record(sc, 1314 (struct an_ltv_gen *)&areq)) { 1315 error = EINVAL; 1316 break; 1317 } 1318 ireq->i_val = key->mac[0]; 1319 break; 1320 case IEEE80211_IOC_AUTHMODE: 1321 areq.an_type = AN_RID_ACTUALCFG; 1322 if (an_read_record(sc, 1323 (struct an_ltv_gen *)&areq)) { 1324 error = EINVAL; 1325 break; 1326 } 1327 if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1328 AN_AUTHTYPE_NONE) { 1329 ireq->i_val = IEEE80211_AUTH_NONE; 1330 } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1331 AN_AUTHTYPE_OPEN) { 1332 ireq->i_val = IEEE80211_AUTH_OPEN; 1333 } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1334 AN_AUTHTYPE_SHAREDKEY) { 1335 ireq->i_val = IEEE80211_AUTH_SHARED; 1336 } else 1337 error = EINVAL; 1338 break; 1339 case IEEE80211_IOC_STATIONNAME: 1340 areq.an_type = AN_RID_ACTUALCFG; 1341 if (an_read_record(sc, 1342 (struct an_ltv_gen *)&areq)) { 1343 error = EINVAL; 1344 break; 1345 } 1346 ireq->i_len = sizeof(config->an_nodename); 1347 tmpptr = config->an_nodename; 1348 bzero(tmpstr, IEEE80211_NWID_LEN); 1349 bcopy(tmpptr, tmpstr, ireq->i_len); 1350 error = copyout(tmpstr, ireq->i_data, 1351 IEEE80211_NWID_LEN); 1352 break; 1353 case IEEE80211_IOC_CHANNEL: 1354 areq.an_type = AN_RID_STATUS; 1355 if (an_read_record(sc, 1356 (struct an_ltv_gen *)&areq)) { 1357 error = EINVAL; 1358 break; 1359 } 1360 ireq->i_val = status->an_cur_channel; 1361 break; 1362 case IEEE80211_IOC_POWERSAVE: 1363 areq.an_type = AN_RID_ACTUALCFG; 1364 if (an_read_record(sc, 1365 (struct an_ltv_gen *)&areq)) { 1366 error = EINVAL; 1367 break; 1368 } 1369 if (config->an_psave_mode == AN_PSAVE_NONE) { 1370 ireq->i_val = IEEE80211_POWERSAVE_OFF; 1371 } else if (config->an_psave_mode == AN_PSAVE_CAM) { 1372 ireq->i_val = IEEE80211_POWERSAVE_CAM; 1373 } else if (config->an_psave_mode == AN_PSAVE_PSP) { 1374 ireq->i_val = IEEE80211_POWERSAVE_PSP; 1375 } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) { 1376 ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM; 1377 } else 1378 error = EINVAL; 1379 break; 1380 case IEEE80211_IOC_POWERSAVESLEEP: 1381 areq.an_type = AN_RID_ACTUALCFG; 1382 if (an_read_record(sc, 1383 (struct an_ltv_gen *)&areq)) { 1384 error = EINVAL; 1385 break; 1386 } 1387 ireq->i_val = config->an_listen_interval; 1388 break; 1389 } 1390 break; 1391 case SIOCS80211: 1392 if ((error = suser(p))) 1393 goto out; 1394 areq.an_len = sizeof(areq); 1395 /* 1396 * We need a config structure for everything but the WEP 1397 * key management and SSIDs so we get it now so avoid 1398 * duplicating this code every time. 1399 */ 1400 if (ireq->i_type != IEEE80211_IOC_SSID && 1401 ireq->i_type != IEEE80211_IOC_WEPKEY && 1402 ireq->i_type != IEEE80211_IOC_WEPTXKEY) { 1403 areq.an_type = AN_RID_GENCONFIG; 1404 if (an_read_record(sc, 1405 (struct an_ltv_gen *)&areq)) { 1406 error = EINVAL; 1407 break; 1408 } 1409 } 1410 switch(ireq->i_type) { 1411 case IEEE80211_IOC_SSID: 1412 areq.an_type = AN_RID_SSIDLIST; 1413 if (an_read_record(sc, 1414 (struct an_ltv_gen *)&areq)) { 1415 error = EINVAL; 1416 break; 1417 } 1418 if (ireq->i_len > IEEE80211_NWID_LEN) { 1419 error = EINVAL; 1420 break; 1421 } 1422 switch (ireq->i_val) { 1423 case 0: 1424 error = copyin(ireq->i_data, 1425 ssids->an_ssid1, ireq->i_len); 1426 ssids->an_ssid1_len = ireq->i_len; 1427 break; 1428 case 1: 1429 error = copyin(ireq->i_data, 1430 ssids->an_ssid2, ireq->i_len); 1431 ssids->an_ssid2_len = ireq->i_len; 1432 break; 1433 case 2: 1434 error = copyin(ireq->i_data, 1435 ssids->an_ssid3, ireq->i_len); 1436 ssids->an_ssid3_len = ireq->i_len; 1437 break; 1438 default: 1439 error = EINVAL; 1440 break; 1441 } 1442 break; 1443 case IEEE80211_IOC_WEP: 1444 switch (ireq->i_val) { 1445 case IEEE80211_WEP_OFF: 1446 config->an_authtype &= 1447 ~(AN_AUTHTYPE_PRIVACY_IN_USE | 1448 AN_AUTHTYPE_ALLOW_UNENCRYPTED); 1449 break; 1450 case IEEE80211_WEP_ON: 1451 config->an_authtype |= 1452 AN_AUTHTYPE_PRIVACY_IN_USE; 1453 config->an_authtype &= 1454 ~AN_AUTHTYPE_ALLOW_UNENCRYPTED; 1455 break; 1456 case IEEE80211_WEP_MIXED: 1457 config->an_authtype |= 1458 AN_AUTHTYPE_PRIVACY_IN_USE | 1459 AN_AUTHTYPE_ALLOW_UNENCRYPTED; 1460 break; 1461 default: 1462 error = EINVAL; 1463 break; 1464 } 1465 break; 1466 case IEEE80211_IOC_WEPKEY: 1467 if (ireq->i_val < 0 || ireq->i_val > 7 || 1468 ireq->i_len > 13) { 1469 error = EINVAL; 1470 break; 1471 } 1472 error = copyin(ireq->i_data, tmpstr, 13); 1473 if (error != 0) 1474 break; 1475 bzero(&areq, sizeof(struct an_ltv_key)); 1476 areq.an_len = sizeof(struct an_ltv_key); 1477 key->mac[0] = 1; /* The others are 0. */ 1478 key->kindex = ireq->i_val % 4; 1479 if (ireq->i_val < 4) 1480 areq.an_type = AN_RID_WEP_TEMP; 1481 else 1482 areq.an_type = AN_RID_WEP_PERM; 1483 key->klen = ireq->i_len; 1484 bcopy(tmpstr, key->key, key->klen); 1485 break; 1486 case IEEE80211_IOC_WEPTXKEY: 1487 if (ireq->i_val < 0 || ireq->i_val > 3) { 1488 error = EINVAL; 1489 break; 1490 } 1491 bzero(&areq, sizeof(struct an_ltv_key)); 1492 areq.an_len = sizeof(struct an_ltv_key); 1493 areq.an_type = AN_RID_WEP_PERM; 1494 key->kindex = 0xffff; 1495 key->mac[0] = ireq->i_val; 1496 break; 1497 case IEEE80211_IOC_AUTHMODE: 1498 switch (ireq->i_val) { 1499 case IEEE80211_AUTH_NONE: 1500 config->an_authtype = AN_AUTHTYPE_NONE | 1501 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1502 break; 1503 case IEEE80211_AUTH_OPEN: 1504 config->an_authtype = AN_AUTHTYPE_OPEN | 1505 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1506 break; 1507 case IEEE80211_AUTH_SHARED: 1508 config->an_authtype = AN_AUTHTYPE_SHAREDKEY | 1509 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1510 break; 1511 default: 1512 error = EINVAL; 1513 } 1514 break; 1515 case IEEE80211_IOC_STATIONNAME: 1516 if (ireq->i_len > 16) { 1517 error = EINVAL; 1518 break; 1519 } 1520 bzero(config->an_nodename, 16); 1521 error = copyin(ireq->i_data, 1522 config->an_nodename, ireq->i_len); 1523 break; 1524 case IEEE80211_IOC_CHANNEL: 1525 /* 1526 * The actual range is 1-14, but if you set it 1527 * to 0 you get the default so we let that work 1528 * too. 1529 */ 1530 if (ireq->i_val < 0 || ireq->i_val >14) { 1531 error = EINVAL; 1532 break; 1533 } 1534 config->an_ds_channel = ireq->i_val; 1535 break; 1536 case IEEE80211_IOC_POWERSAVE: 1537 switch (ireq->i_val) { 1538 case IEEE80211_POWERSAVE_OFF: 1539 config->an_psave_mode = AN_PSAVE_NONE; 1540 break; 1541 case IEEE80211_POWERSAVE_CAM: 1542 config->an_psave_mode = AN_PSAVE_CAM; 1543 break; 1544 case IEEE80211_POWERSAVE_PSP: 1545 config->an_psave_mode = AN_PSAVE_PSP; 1546 break; 1547 case IEEE80211_POWERSAVE_PSP_CAM: 1548 config->an_psave_mode = AN_PSAVE_PSP_CAM; 1549 break; 1550 default: 1551 error = EINVAL; 1552 break; 1553 } 1554 break; 1555 case IEEE80211_IOC_POWERSAVESLEEP: 1556 config->an_listen_interval = ireq->i_val; 1557 break; 1558 } 1559 1560 if (!error) 1561 an_setdef(sc, &areq); 1562 break; 1563 default: 1564 error = EINVAL; 1565 break; 1566 } 1567out: 1568 AN_UNLOCK(sc); 1569 1570 return(error != 0); 1571} 1572 1573static int an_init_tx_ring(sc) 1574 struct an_softc *sc; 1575{ 1576 int i; 1577 int id; 1578 1579 if (sc->an_gone) 1580 return (0); 1581 1582 for (i = 0; i < AN_TX_RING_CNT; i++) { 1583 if (an_alloc_nicmem(sc, 1518 + 1584 0x44, &id)) 1585 return(ENOMEM); 1586 sc->an_rdata.an_tx_fids[i] = id; 1587 sc->an_rdata.an_tx_ring[i] = 0; 1588 } 1589 1590 sc->an_rdata.an_tx_prod = 0; 1591 sc->an_rdata.an_tx_cons = 0; 1592 1593 return(0); 1594} 1595 1596static void an_init(xsc) 1597 void *xsc; 1598{ 1599 struct an_softc *sc = xsc; 1600 struct ifnet *ifp = &sc->arpcom.ac_if; 1601 1602 AN_LOCK(sc); 1603 1604 if (sc->an_gone) { 1605 AN_UNLOCK(sc); 1606 return; 1607 } 1608 1609 if (ifp->if_flags & IFF_RUNNING) 1610 an_stop(sc); 1611 1612 sc->an_associated = 0; 1613 1614 /* Allocate the TX buffers */ 1615 if (an_init_tx_ring(sc)) { 1616 an_reset(sc); 1617 if (an_init_tx_ring(sc)) { 1618 printf("an%d: tx buffer allocation " 1619 "failed\n", sc->an_unit); 1620 AN_UNLOCK(sc); 1621 return; 1622 } 1623 } 1624 1625 /* Set our MAC address. */ 1626 bcopy((char *)&sc->arpcom.ac_enaddr, 1627 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN); 1628 1629 if (ifp->if_flags & IFF_BROADCAST) 1630 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1631 else 1632 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1633 1634 if (ifp->if_flags & IFF_MULTICAST) 1635 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1636 1637 /* Initialize promisc mode. */ 1638 /* Kills card DJA can't TX packet in sniff mode 1639 if (ifp->if_flags & IFF_PROMISC) 1640 sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS; 1641 */ 1642 1643 sc->an_rxmode = sc->an_config.an_rxmode; 1644 1645 /* Set the ssid list */ 1646 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 1647 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 1648 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 1649 printf("an%d: failed to set ssid list\n", sc->an_unit); 1650 AN_UNLOCK(sc); 1651 return; 1652 } 1653 1654 /* Set the AP list */ 1655 sc->an_aplist.an_type = AN_RID_APLIST; 1656 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 1657 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 1658 printf("an%d: failed to set AP list\n", sc->an_unit); 1659 AN_UNLOCK(sc); 1660 return; 1661 } 1662 1663 /* Set the configuration in the NIC */ 1664 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 1665 sc->an_config.an_type = AN_RID_GENCONFIG; 1666 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 1667 printf("an%d: failed to set configuration\n", sc->an_unit); 1668 AN_UNLOCK(sc); 1669 return; 1670 } 1671 1672 /* Enable the MAC */ 1673 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1674 printf("an%d: failed to enable MAC\n", sc->an_unit); 1675 AN_UNLOCK(sc); 1676 return; 1677 } 1678 1679 if (ifp->if_flags & IFF_PROMISC) 1680 an_cmd(sc, AN_CMD_SET_MODE, 0xffff); 1681 1682 /* enable interrupts */ 1683 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1684 1685 ifp->if_flags |= IFF_RUNNING; 1686 ifp->if_flags &= ~IFF_OACTIVE; 1687 1688 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 1689 AN_UNLOCK(sc); 1690 1691 return; 1692} 1693 1694static void an_start(ifp) 1695 struct ifnet *ifp; 1696{ 1697 struct an_softc *sc; 1698 struct mbuf *m0 = NULL; 1699 struct an_txframe_802_3 tx_frame_802_3; 1700 struct ether_header *eh; 1701 int id; 1702 int idx; 1703 unsigned char txcontrol; 1704 1705 sc = ifp->if_softc; 1706 1707 if (sc->an_gone) 1708 return; 1709 1710 if (ifp->if_flags & IFF_OACTIVE) 1711 return; 1712 1713 if (!sc->an_associated) 1714 return; 1715 1716 idx = sc->an_rdata.an_tx_prod; 1717 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3)); 1718 1719 while(sc->an_rdata.an_tx_ring[idx] == 0) { 1720 IF_DEQUEUE(&ifp->if_snd, m0); 1721 if (m0 == NULL) 1722 break; 1723 1724 id = sc->an_rdata.an_tx_fids[idx]; 1725 eh = mtod(m0, struct ether_header *); 1726 1727 bcopy((char *)&eh->ether_dhost, 1728 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN); 1729 bcopy((char *)&eh->ether_shost, 1730 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); 1731 1732 tx_frame_802_3.an_tx_802_3_payload_len = 1733 m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ 1734 1735 m_copydata(m0, sizeof(struct ether_header) - 2 , 1736 tx_frame_802_3.an_tx_802_3_payload_len, 1737 (caddr_t)&sc->an_txbuf); 1738 1739 txcontrol = AN_TXCTL_8023; 1740 /* write the txcontrol only */ 1741 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol, 1742 sizeof(txcontrol)); 1743 1744 /* 802_3 header */ 1745 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3, 1746 sizeof(struct an_txframe_802_3)); 1747 1748 /* in mbuf header type is just before payload */ 1749 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, 1750 tx_frame_802_3.an_tx_802_3_payload_len); 1751 1752 /* 1753 * If there's a BPF listner, bounce a copy of 1754 * this frame to him. 1755 */ 1756 if (ifp->if_bpf) 1757 bpf_mtap(ifp, m0); 1758 1759 m_freem(m0); 1760 m0 = NULL; 1761 1762 sc->an_rdata.an_tx_ring[idx] = id; 1763 if (an_cmd(sc, AN_CMD_TX, id)) 1764 printf("an%d: xmit failed\n", sc->an_unit); 1765 1766 AN_INC(idx, AN_TX_RING_CNT); 1767 } 1768 1769 if (m0 != NULL) 1770 ifp->if_flags |= IFF_OACTIVE; 1771 1772 sc->an_rdata.an_tx_prod = idx; 1773 1774 /* 1775 * Set a timeout in case the chip goes out to lunch. 1776 */ 1777 ifp->if_timer = 5; 1778 1779 return; 1780} 1781 1782void an_stop(sc) 1783 struct an_softc *sc; 1784{ 1785 struct ifnet *ifp; 1786 int i; 1787 1788 AN_LOCK(sc); 1789 1790 if (sc->an_gone) { 1791 AN_UNLOCK(sc); 1792 return; 1793 } 1794 1795 ifp = &sc->arpcom.ac_if; 1796 1797 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 1798 CSR_WRITE_2(sc, AN_INT_EN, 0); 1799 an_cmd(sc, AN_CMD_DISABLE, 0); 1800 1801 for (i = 0; i < AN_TX_RING_CNT; i++) 1802 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 1803 1804 untimeout(an_stats_update, sc, sc->an_stat_ch); 1805 1806 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1807 1808 AN_UNLOCK(sc); 1809 1810 return; 1811} 1812 1813static void an_watchdog(ifp) 1814 struct ifnet *ifp; 1815{ 1816 struct an_softc *sc; 1817 1818 sc = ifp->if_softc; 1819 AN_LOCK(sc); 1820 1821 if (sc->an_gone) { 1822 AN_UNLOCK(sc); 1823 return; 1824 } 1825 1826 printf("an%d: device timeout\n", sc->an_unit); 1827 1828 an_reset(sc); 1829 an_init(sc); 1830 1831 ifp->if_oerrors++; 1832 AN_UNLOCK(sc); 1833 1834 return; 1835} 1836 1837void an_shutdown(dev) 1838 device_t dev; 1839{ 1840 struct an_softc *sc; 1841 1842 sc = device_get_softc(dev); 1843 an_stop(sc); 1844 1845 return; 1846} 1847 1848#ifdef ANCACHE 1849/* Aironet signal strength cache code. 1850 * store signal/noise/quality on per MAC src basis in 1851 * a small fixed cache. The cache wraps if > MAX slots 1852 * used. The cache may be zeroed out to start over. 1853 * Two simple filters exist to reduce computation: 1854 * 1. ip only (literally 0x800) which may be used 1855 * to ignore some packets. It defaults to ip only. 1856 * it could be used to focus on broadcast, non-IP 802.11 beacons. 1857 * 2. multicast/broadcast only. This may be used to 1858 * ignore unicast packets and only cache signal strength 1859 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 1860 * beacons and not unicast traffic. 1861 * 1862 * The cache stores (MAC src(index), IP src (major clue), signal, 1863 * quality, noise) 1864 * 1865 * No apologies for storing IP src here. It's easy and saves much 1866 * trouble elsewhere. The cache is assumed to be INET dependent, 1867 * although it need not be. 1868 * 1869 * Note: the Aironet only has a single byte of signal strength value 1870 * in the rx frame header, and it's not scaled to anything sensible. 1871 * This is kind of lame, but it's all we've got. 1872 */ 1873 1874#ifdef documentation 1875 1876int an_sigitems; /* number of cached entries */ 1877struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 1878int an_nextitem; /* index/# of entries */ 1879 1880 1881#endif 1882 1883/* control variables for cache filtering. Basic idea is 1884 * to reduce cost (e.g., to only Mobile-IP agent beacons 1885 * which are broadcast or multicast). Still you might 1886 * want to measure signal strength anth unicast ping packets 1887 * on a pt. to pt. ant. setup. 1888 */ 1889/* set true if you want to limit cache items to broadcast/mcast 1890 * only packets (not unicast). Useful for mobile-ip beacons which 1891 * are broadcast/multicast at network layer. Default is all packets 1892 * so ping/unicast anll work say anth pt. to pt. antennae setup. 1893 */ 1894static int an_cache_mcastonly = 0; 1895SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 1896 &an_cache_mcastonly, 0, ""); 1897 1898/* set true if you want to limit cache items to IP packets only 1899*/ 1900static int an_cache_iponly = 1; 1901SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 1902 &an_cache_iponly, 0, ""); 1903 1904/* 1905 * an_cache_store, per rx packet store signal 1906 * strength in MAC (src) indexed cache. 1907 */ 1908static 1909void an_cache_store (sc, eh, m, rx_quality) 1910 struct an_softc *sc; 1911 struct ether_header *eh; 1912 struct mbuf *m; 1913 unsigned short rx_quality; 1914{ 1915 struct ip *ip = 0; 1916 int i; 1917 static int cache_slot = 0; /* use this cache entry */ 1918 static int wrapindex = 0; /* next "free" cache entry */ 1919 int saanp = 0; 1920 1921 /* filters: 1922 * 1. ip only 1923 * 2. configurable filter to throw out unicast packets, 1924 * keep multicast only. 1925 */ 1926 1927 if ((ntohs(eh->ether_type) == 0x800)) { 1928 saanp = 1; 1929 } 1930 1931 /* filter for ip packets only 1932 */ 1933 if ( an_cache_iponly && !saanp) { 1934 return; 1935 } 1936 1937 /* filter for broadcast/multicast only 1938 */ 1939 if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { 1940 return; 1941 } 1942 1943#ifdef SIGDEBUG 1944 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 1945 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 1946#endif 1947 1948 /* find the ip header. we want to store the ip_src 1949 * address. 1950 */ 1951 if (saanp) { 1952 ip = mtod(m, struct ip *); 1953 } 1954 1955 /* do a linear search for a matching MAC address 1956 * in the cache table 1957 * . MAC address is 6 bytes, 1958 * . var w_nextitem holds total number of entries already cached 1959 */ 1960 for (i = 0; i < sc->an_nextitem; i++) { 1961 if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6 )) { 1962 /* Match!, 1963 * so we already have this entry, 1964 * update the data 1965 */ 1966 break; 1967 } 1968 } 1969 1970 /* did we find a matching mac address? 1971 * if yes, then overwrite a previously existing cache entry 1972 */ 1973 if (i < sc->an_nextitem ) { 1974 cache_slot = i; 1975 } 1976 /* else, have a new address entry,so 1977 * add this new entry, 1978 * if table full, then we need to replace LRU entry 1979 */ 1980 else { 1981 1982 /* check for space in cache table 1983 * note: an_nextitem also holds number of entries 1984 * added in the cache table 1985 */ 1986 if ( sc->an_nextitem < MAXANCACHE ) { 1987 cache_slot = sc->an_nextitem; 1988 sc->an_nextitem++; 1989 sc->an_sigitems = sc->an_nextitem; 1990 } 1991 /* no space found, so simply wrap anth wrap index 1992 * and "zap" the next entry 1993 */ 1994 else { 1995 if (wrapindex == MAXANCACHE) { 1996 wrapindex = 0; 1997 } 1998 cache_slot = wrapindex++; 1999 } 2000 } 2001 2002 /* invariant: cache_slot now points at some slot 2003 * in cache. 2004 */ 2005 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 2006 log(LOG_ERR, "an_cache_store, bad index: %d of " 2007 "[0..%d], gross cache error\n", 2008 cache_slot, MAXANCACHE); 2009 return; 2010 } 2011 2012 /* store items in cache 2013 * .ip source address 2014 * .mac src 2015 * .signal, etc. 2016 */ 2017 if (saanp) { 2018 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 2019 } 2020 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); 2021 2022 sc->an_sigcache[cache_slot].signal = rx_quality; 2023 2024 return; 2025} 2026#endif 2027 2028static int an_media_change(ifp) 2029 struct ifnet *ifp; 2030{ 2031 struct an_softc *sc = ifp->if_softc; 2032 int otype = sc->an_config.an_opmode; 2033 int orate = sc->an_tx_rate; 2034 2035 if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) 2036 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; 2037 else 2038 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 2039 2040 switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) { 2041 case IFM_IEEE80211_DS1: 2042 sc->an_tx_rate = AN_RATE_1MBPS; 2043 break; 2044 case IFM_IEEE80211_DS2: 2045 sc->an_tx_rate = AN_RATE_2MBPS; 2046 break; 2047 case IFM_IEEE80211_DS5: 2048 sc->an_tx_rate = AN_RATE_5_5MBPS; 2049 break; 2050 case IFM_IEEE80211_DS11: 2051 sc->an_tx_rate = AN_RATE_11MBPS; 2052 break; 2053 case IFM_AUTO: 2054 sc->an_tx_rate = 0; 2055 break; 2056 } 2057 2058 if (otype != sc->an_config.an_opmode || 2059 orate != sc->an_tx_rate) 2060 an_init(sc); 2061 2062 return(0); 2063} 2064 2065static void an_media_status(ifp, imr) 2066 struct ifnet *ifp; 2067 struct ifmediareq *imr; 2068{ 2069 struct an_ltv_status status; 2070 struct an_softc *sc = ifp->if_softc; 2071 2072 status.an_len = sizeof(status); 2073 status.an_type = AN_RID_STATUS; 2074 if (an_read_record(sc, (struct an_ltv_gen *)&status)) { 2075 /* If the status read fails, just lie. */ 2076 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 2077 imr->ifm_status = IFM_AVALID|IFM_ACTIVE; 2078 } 2079 2080 if (sc->an_tx_rate == 0) { 2081 imr->ifm_active = IFM_IEEE80211|IFM_AUTO; 2082 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 2083 imr->ifm_active |= IFM_IEEE80211_ADHOC; 2084 switch(status.an_current_tx_rate) { 2085 case AN_RATE_1MBPS: 2086 imr->ifm_active |= IFM_IEEE80211_DS1; 2087 break; 2088 case AN_RATE_2MBPS: 2089 imr->ifm_active |= IFM_IEEE80211_DS2; 2090 break; 2091 case AN_RATE_5_5MBPS: 2092 imr->ifm_active |= IFM_IEEE80211_DS5; 2093 break; 2094 case AN_RATE_11MBPS: 2095 imr->ifm_active |= IFM_IEEE80211_DS11; 2096 break; 2097 } 2098 } else { 2099 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 2100 } 2101 2102 imr->ifm_status = IFM_AVALID; 2103 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 2104 imr->ifm_status |= IFM_ACTIVE; 2105 else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 2106 imr->ifm_status |= IFM_ACTIVE; 2107} 2108