1 /* $OpenBSD: an.c,v 1.19 2001/07/08 23:38:05 fgsch Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999 5 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Bill Paul. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/dev/an/if_an.c,v 1.2 2000/01/16 06:41:49 wpaul Exp $ 35 */ 36 37 /* 38 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD. 39 * 40 * Written by Bill Paul <wpaul@ctr.columbia.edu> 41 * Electrical Engineering Department 42 * Columbia University, New York City 43 */ 44 45 /* 46 * The Aironet 4500/4800 series cards some in PCMCIA, ISA and PCI form. 47 * This driver supports all three device types (PCI devices are supported 48 * through an extra PCI shim: /sys/pci/if_an_p.c). ISA devices can be 49 * supported either using hard-coded IO port/IRQ settings or via Plug 50 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates. 51 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates. 52 * 53 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially 54 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA 55 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are 56 * a couple of important differences though: 57 * 58 * - Lucent doesn't currently offer a PCI card, however Aironet does 59 * - Lucent ISA card looks to the host like a PCMCIA controller with 60 * a PCMCIA WaveLAN card inserted. This means that even desktop 61 * machines need to be configured with PCMCIA support in order to 62 * use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand 63 * actually look like normal ISA and PCI devices to the host, so 64 * no PCMCIA controller support is needed 65 * 66 * The latter point results in a small gotcha. The Aironet PCMCIA 67 * cards can be configured for one of two operating modes depending 68 * on how the Vpp1 and Vpp2 programming voltages are set when the 69 * card is activated. In order to put the card in proper PCMCIA 70 * operation (where the CIS table is visible and the interface is 71 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be 72 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages, 73 * which leaves the card in ISA/PCI mode, which prevents it from 74 * being activated as an PCMCIA device. Consequently, /sys/pccard/pccard.c 75 * has to be patched slightly in order to enable the Vpp voltages in 76 * order to make the Aironet PCMCIA cards work. 77 * 78 * Note that some PCMCIA controller software packages for Windows NT 79 * fail to set the voltages as well. 80 * 81 * The Aironet devices can operate in both station mode and access point 82 * mode. Typically, when programmed for station mode, the card can be set 83 * to automatically perform encapsulation/decapsulation of Ethernet II 84 * and 802.3 frames within 802.11 frames so that the host doesn't have 85 * to do it itself. This driver doesn't program the card that way: the 86 * driver handles all of the encapsulation/decapsulation itself. 87 */ 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/device.h> 96 #include <sys/sockio.h> 97 #include <sys/mbuf.h> 98 #include <sys/malloc.h> 99 #include <sys/kernel.h> 100 #include <sys/proc.h> 101 #include <sys/socket.h> 102 #include <sys/timeout.h> 103 #ifdef ANCACHE 104 #include <sys/syslog.h> 105 #include <sys/sysctl.h> 106 #endif 107 108 #include <net/if.h> 109 #include <net/if_dl.h> 110 #include <net/if_media.h> 111 #include <net/if_types.h> 112 113 #ifdef INET 114 #include <netinet/in.h> 115 #include <netinet/in_systm.h> 116 #include <netinet/in_var.h> 117 #include <netinet/ip.h> 118 #include <netinet/if_ether.h> 119 #endif 120 121 #include "bpfilter.h" 122 #if NBPFILTER > 0 123 #include <net/bpf.h> 124 #endif 125 126 #include <machine/bus.h> 127 #include <machine/intr.h> 128 129 #include <dev/ic/anvar.h> 130 #include <dev/ic/anreg.h> 131 132 #define TIMEOUT(handle,func,sc,time) timeout_add(&(handle), (time)) 133 #define UNTIMEOUT(func,sc,handle) timeout_del(&(handle)) 134 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf)) 135 #define BPFATTACH(if_bpf,if,dlt,sz) 136 137 struct cfdriver an_cd = { 138 NULL, "an", DV_IFNET 139 }; 140 141 void an_reset __P((struct an_softc *)); 142 int an_ioctl __P((struct ifnet *, u_long, caddr_t)); 143 int an_init_tx_ring __P((struct an_softc *)); 144 void an_start __P((struct ifnet *)); 145 void an_watchdog __P((struct ifnet *)); 146 void an_rxeof __P((struct an_softc *)); 147 void an_txeof __P((struct an_softc *, int)); 148 149 void an_promisc __P((struct an_softc *, int)); 150 int an_cmd __P((struct an_softc *, int, int)); 151 int an_read_record __P((struct an_softc *, struct an_ltv_gen *)); 152 int an_write_record __P((struct an_softc *, struct an_ltv_gen *)); 153 int an_read_data __P((struct an_softc *, int, 154 int, caddr_t, int)); 155 int an_write_data __P((struct an_softc *, int, 156 int, caddr_t, int)); 157 int an_seek __P((struct an_softc *, int, int, int)); 158 int an_alloc_nicmem __P((struct an_softc *, int, int *)); 159 void an_stats_update __P((void *)); 160 void an_setdef __P((struct an_softc *, struct an_req *)); 161 #ifdef ANCACHE 162 void an_cache_store __P((struct an_softc *, struct ether_header *, 163 struct mbuf *, unsigned short)); 164 #endif 165 166 static __inline void 167 an_swap16(u_int16_t *p, int cnt) 168 { 169 for (; cnt--; p++) 170 *p = swap16(*p); 171 } 172 173 int 174 an_attach(sc) 175 struct an_softc *sc; 176 { 177 struct ifnet *ifp = &sc->arpcom.ac_if; 178 179 sc->an_gone = 0; 180 sc->an_associated = 0; 181 182 /* disable interrupts */ 183 CSR_WRITE_2(sc, AN_INT_EN, 0); 184 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff); 185 186 /* Reset the NIC. */ 187 an_reset(sc); 188 189 /* Load factory config */ 190 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 191 printf("%s: failed to load config data\n", ifp->if_xname); 192 return(EIO); 193 } 194 195 /* Read the current configuration */ 196 sc->an_config.an_type = AN_RID_GENCONFIG; 197 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 198 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 199 printf("%s: read record failed\n", ifp->if_xname); 200 return(EIO); 201 } 202 203 /* Read the card capabilities */ 204 sc->an_caps.an_type = AN_RID_CAPABILITIES; 205 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 206 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 207 printf("%s: read record failed\n", ifp->if_xname); 208 return(EIO); 209 } 210 211 /* Read ssid list */ 212 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 213 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 214 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 215 printf("%s: read record failed\n", ifp->if_xname); 216 return(EIO); 217 } 218 219 /* Read AP list */ 220 sc->an_aplist.an_type = AN_RID_APLIST; 221 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 222 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 223 printf("%s: read record failed\n", ifp->if_xname); 224 return(EIO); 225 } 226 227 bcopy((char *)&sc->an_caps.an_oemaddr, 228 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 229 230 printf(": address %6s\n", ether_sprintf(sc->arpcom.ac_enaddr)); 231 232 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 233 ifp->if_softc = sc; 234 ifp->if_mtu = ETHERMTU; 235 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 236 ifp->if_ioctl = an_ioctl; 237 ifp->if_start = an_start; 238 ifp->if_watchdog = an_watchdog; 239 ifp->if_baudrate = 10000000; 240 241 bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); 242 bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename, 243 sizeof(AN_DEFAULT_NODENAME) - 1); 244 245 bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1)); 246 bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1, 247 sizeof(AN_DEFAULT_NETNAME) - 1); 248 sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME); 249 250 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 251 252 sc->an_tx_rate = 0; 253 bzero((char *)&sc->an_stats, sizeof(sc->an_stats)); 254 #ifdef ANCACHE 255 sc->an_sigitems = sc->an_nextitem = 0; 256 #endif 257 258 /* 259 * Call MI attach routines. 260 */ 261 if_attach(ifp); 262 ether_ifattach(ifp); 263 timeout_set(&sc->an_stat_ch, an_stats_update, sc); 264 #if NBPFILTER > 0 265 BPFATTACH(&sc->arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, 266 sizeof(struct ether_header)); 267 #endif 268 269 shutdownhook_establish(an_shutdown, sc); 270 271 an_reset(sc); 272 an_init(sc); 273 274 return(0); 275 } 276 277 void 278 an_rxeof(sc) 279 struct an_softc *sc; 280 { 281 struct ifnet *ifp; 282 struct ether_header *eh; 283 #ifdef ANCACHE 284 struct an_rxframe rx_frame; 285 #endif 286 struct an_rxframe_802_3 rx_frame_802_3; 287 struct mbuf *m; 288 int id, error = 0; 289 290 ifp = &sc->arpcom.ac_if; 291 292 id = CSR_READ_2(sc, AN_RX_FID); 293 294 MGETHDR(m, M_DONTWAIT, MT_DATA); 295 if (m == NULL) { 296 ifp->if_ierrors++; 297 return; 298 } 299 MCLGET(m, M_DONTWAIT); 300 if (!(m->m_flags & M_EXT)) { 301 m_freem(m); 302 ifp->if_ierrors++; 303 return; 304 } 305 306 m->m_pkthdr.rcvif = ifp; 307 308 eh = mtod(m, struct ether_header *); 309 310 #ifdef ANCACHE 311 /* Read NIC frame header */ 312 if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 313 ifp->if_ierrors++; 314 return; 315 } 316 #endif 317 /* Read in the 802_3 frame header */ 318 if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3, 319 sizeof(rx_frame_802_3))) { 320 ifp->if_ierrors++; 321 return; 322 } 323 324 if (rx_frame_802_3.an_rx_802_3_status != 0) { 325 ifp->if_ierrors++; 326 return; 327 } 328 329 /* Check for insane frame length */ 330 if (letoh16(rx_frame_802_3.an_rx_802_3_payload_len) > MCLBYTES) { 331 ifp->if_ierrors++; 332 return; 333 } 334 335 m->m_pkthdr.len = m->m_len = 336 letoh16(rx_frame_802_3.an_rx_802_3_payload_len) + 12; 337 338 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr, 339 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 340 bcopy((char *)&rx_frame_802_3.an_rx_src_addr, 341 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 342 343 /* in mbuf header type is just before payload */ 344 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type), 345 letoh16(rx_frame_802_3.an_rx_802_3_payload_len)); 346 if (error) { 347 m_freem(m); 348 ifp->if_ierrors++; 349 return; 350 } 351 352 ifp->if_ipackets++; 353 354 #if NBPFILTER > 0 355 /* Handle BPF listeners. */ 356 if (ifp->if_bpf) 357 BPF_MTAP(ifp, m); 358 #endif 359 360 /* Receive packet. */ 361 #ifdef ANCACHE 362 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); 363 #endif 364 ether_input_mbuf(ifp, m); 365 } 366 367 void 368 an_txeof(sc, status) 369 struct an_softc *sc; 370 int status; 371 { 372 struct ifnet *ifp; 373 int id; 374 375 ifp = &sc->arpcom.ac_if; 376 377 ifp->if_timer = 0; 378 ifp->if_flags &= ~IFF_OACTIVE; 379 380 id = CSR_READ_2(sc, AN_TX_CMP_FID); 381 382 if (status & AN_EV_TX_EXC) 383 ifp->if_oerrors++; 384 else 385 ifp->if_opackets++; 386 387 if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons]) 388 printf("%s: id mismatch: expected %x, got %x\n", ifp->if_xname, 389 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id); 390 391 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] = 0; 392 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT); 393 } 394 395 /* 396 * We abuse the stats updater to check the current NIC status. This 397 * is important because we don't want to allow transmissions until 398 * the NIC has synchronized to the current cell (either as the master 399 * in an ad-hoc group, or as a station connected to an access point). 400 */ 401 void 402 an_stats_update(xsc) 403 void *xsc; 404 { 405 struct an_softc *sc; 406 struct ifnet *ifp; 407 int s; 408 409 s = splimp(); 410 411 sc = xsc; 412 ifp = &sc->arpcom.ac_if; 413 414 sc->an_status.an_type = AN_RID_STATUS; 415 sc->an_status.an_len = sizeof(struct an_ltv_status); 416 an_read_record(sc, (struct an_ltv_gen *)&sc->an_status); 417 418 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC) 419 sc->an_associated = 1; 420 else 421 sc->an_associated = 0; 422 423 /* Don't do this while we're transmitting */ 424 if (!(ifp->if_flags & IFF_OACTIVE)) { 425 sc->an_stats.an_len = sizeof(struct an_ltv_stats); 426 sc->an_stats.an_type = AN_RID_32BITS_CUM; 427 an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len); 428 } 429 430 splx(s); 431 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz); 432 } 433 434 int 435 an_intr(xsc) 436 void *xsc; 437 { 438 struct an_softc *sc; 439 struct ifnet *ifp; 440 u_int16_t status; 441 442 sc = (struct an_softc*)xsc; 443 444 if (sc->an_gone) 445 return 0; 446 447 ifp = &sc->arpcom.ac_if; 448 449 if (!(ifp->if_flags & IFF_UP)) { 450 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF); 451 CSR_WRITE_2(sc, AN_INT_EN, 0); 452 return 0; 453 } 454 455 /* Disable interrupts. */ 456 CSR_WRITE_2(sc, AN_INT_EN, 0); 457 458 status = CSR_READ_2(sc, AN_EVENT_STAT); 459 CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS); 460 461 if (status & AN_EV_AWAKE) { 462 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE); 463 } 464 465 if (status & AN_EV_LINKSTAT) { 466 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED) 467 sc->an_associated = 1; 468 else 469 sc->an_associated = 0; 470 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 471 } 472 473 if (status & AN_EV_RX) { 474 an_rxeof(sc); 475 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 476 } 477 478 if (status & AN_EV_TX) { 479 an_txeof(sc, status); 480 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX); 481 } 482 483 if (status & AN_EV_TX_EXC) { 484 an_txeof(sc, status); 485 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC); 486 } 487 488 if (status & AN_EV_ALLOC) 489 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 490 491 /* Re-enable interrupts. */ 492 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 493 494 if (ifp->if_snd.ifq_head != NULL) 495 an_start(ifp); 496 497 return 1; 498 } 499 500 int 501 an_cmd(sc, cmd, val) 502 struct an_softc *sc; 503 int cmd; 504 int val; 505 { 506 int i, stat; 507 508 /* make sure previous command completed */ 509 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 510 printf("%s: command busy\n", sc->sc_dev.dv_xname); 511 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 512 } 513 514 CSR_WRITE_2(sc, AN_PARAM0, val); 515 CSR_WRITE_2(sc, AN_PARAM1, 0); 516 CSR_WRITE_2(sc, AN_PARAM2, 0); 517 DELAY(10); 518 CSR_WRITE_2(sc, AN_COMMAND, cmd); 519 DELAY(10); 520 521 for (i = AN_TIMEOUT; i--; DELAY(10)) { 522 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 523 break; 524 else { 525 if (CSR_READ_2(sc, AN_COMMAND) == cmd) { 526 DELAY(10); 527 CSR_WRITE_2(sc, AN_COMMAND, cmd); 528 } 529 } 530 } 531 532 stat = CSR_READ_2(sc, AN_STATUS); 533 534 /* clear stuck command busy if needed */ 535 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 536 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 537 } 538 539 /* Ack the command */ 540 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 541 542 if (i <= 0) 543 return(ETIMEDOUT); 544 545 if (stat & AN_STAT_CMD_RESULT) 546 return(EIO); 547 548 return(0); 549 } 550 551 /* 552 * This reset sequence may look a little strange, but this is the 553 * most reliable method I've found to really kick the NIC in the 554 * head and force it to reboot correctly. 555 */ 556 void 557 an_reset(sc) 558 struct an_softc *sc; 559 { 560 if (sc->an_gone) 561 return; 562 /*printf("ena ");*/ 563 an_cmd(sc, AN_CMD_ENABLE, 0); 564 /* printf("rst ");*/ 565 an_cmd(sc, AN_CMD_FW_RESTART, 0); 566 /*printf("nop ");*/ 567 an_cmd(sc, AN_CMD_NOOP2, 0); 568 569 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) 570 printf("%s: reset failed\n", sc->sc_dev.dv_xname); 571 572 an_cmd(sc, AN_CMD_DISABLE, 0); 573 } 574 575 /* 576 * Read an LTV record from the NIC. 577 */ 578 int 579 an_read_record(sc, ltv) 580 struct an_softc *sc; 581 struct an_ltv_gen *ltv; 582 { 583 u_int16_t *ptr, len; 584 int i; 585 586 if (ltv->an_len == 0 || ltv->an_type == 0) 587 return(EINVAL); 588 589 /* Tell the NIC to enter record read mode. */ 590 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) { 591 printf("%s: RID 0x%04x access failed\n", 592 sc->sc_dev.dv_xname, ltv->an_type); 593 return(EIO); 594 } 595 596 /* Seek to the record. */ 597 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) { 598 printf("%s: RID 0x%04x seek to record failed\n", 599 sc->sc_dev.dv_xname, ltv->an_type); 600 return(EIO); 601 } 602 603 /* 604 * Read the length and record type and make sure they 605 * match what we expect (this verifies that we have enough 606 * room to hold all of the returned data). 607 */ 608 len = CSR_READ_2(sc, AN_DATA1); 609 if (len > ltv->an_len) { 610 printf("%s: RID 0x%04x record length mismatch -- expected %d, " 611 "got %d\n", sc->sc_dev.dv_xname, ltv->an_type, 612 ltv->an_len, len); 613 return(ENOSPC); 614 } 615 616 ltv->an_len = len; 617 618 /* Now read the data. */ 619 ptr = ltv->an_val; 620 for (i = 0; i < (ltv->an_len - 1) >> 1; i++) 621 ptr[i] = CSR_READ_2(sc, AN_DATA1); 622 623 #if BYTE_ORDER == BIG_ENDIAN 624 switch (ltv->an_type) { 625 case AN_RID_GENCONFIG: 626 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 627 an_swap16(<v->an_val[63], 8); /* an_nodename */ 628 break; 629 case AN_RID_SSIDLIST: 630 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 631 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 632 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 633 break; 634 case AN_RID_APLIST: 635 an_swap16(ltv->an_val, 12); 636 break; 637 case AN_RID_DRVNAME: 638 an_swap16(ltv->an_val, 8); 639 break; 640 case AN_RID_CAPABILITIES: 641 an_swap16(ltv->an_val, 2); /* an_oui */ 642 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 643 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 644 break; 645 case AN_RID_STATUS: 646 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 647 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 648 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 649 break; 650 case AN_RID_WEP_VOLATILE: 651 case AN_RID_WEP_PERMANENT: 652 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 653 an_swap16(<v->an_val[5], 6); 654 break; 655 case AN_RID_32BITS_CUM: 656 for (i = 0x60; i--; ) { 657 u_int16_t t = ltv->an_val[i * 2] ^ ltv->an_val[i * 2 + 1]; 658 ltv->an_val[i * 2] ^= t; 659 ltv->an_val[i * 2 + 1] ^= t; 660 } 661 break; 662 } 663 #endif 664 return(0); 665 } 666 667 /* 668 * Same as read, except we inject data instead of reading it. 669 */ 670 int 671 an_write_record(sc, ltv) 672 struct an_softc *sc; 673 struct an_ltv_gen *ltv; 674 { 675 u_int16_t *ptr; 676 int i; 677 678 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 679 return(EIO); 680 681 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 682 return(EIO); 683 684 #if BYTE_ORDER == BIG_ENDIAN 685 switch (ltv->an_type) { 686 case AN_RID_GENCONFIG: 687 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 688 an_swap16(<v->an_val[63], 8); /* an_nodename */ 689 break; 690 case AN_RID_SSIDLIST: 691 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 692 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 693 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 694 break; 695 case AN_RID_APLIST: 696 an_swap16(ltv->an_val, 12); 697 break; 698 case AN_RID_DRVNAME: 699 an_swap16(ltv->an_val, 8); 700 break; 701 case AN_RID_CAPABILITIES: 702 an_swap16(ltv->an_val, 2); /* an_oui */ 703 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 704 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 705 break; 706 case AN_RID_STATUS: 707 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 708 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 709 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 710 break; 711 case AN_RID_WEP_VOLATILE: 712 case AN_RID_WEP_PERMANENT: 713 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 714 an_swap16(<v->an_val[5], 6); 715 break; 716 } 717 #endif 718 719 CSR_WRITE_2(sc, AN_DATA1, ltv->an_len); 720 721 ptr = ltv->an_val; 722 for (i = 0; i < (ltv->an_len - 1) >> 1; i++) 723 CSR_WRITE_2(sc, AN_DATA1, ptr[i]); 724 725 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 726 return(EIO); 727 728 return(0); 729 } 730 731 int 732 an_seek(sc, id, off, chan) 733 struct an_softc *sc; 734 int id, off, chan; 735 { 736 int i; 737 int selreg, offreg; 738 739 switch (chan) { 740 case AN_BAP0: 741 selreg = AN_SEL0; 742 offreg = AN_OFF0; 743 break; 744 case AN_BAP1: 745 selreg = AN_SEL1; 746 offreg = AN_OFF1; 747 break; 748 default: 749 printf("%s: invalid data path: %x\n", 750 sc->sc_dev.dv_xname, chan); 751 return (EIO); 752 } 753 754 CSR_WRITE_2(sc, selreg, id); 755 CSR_WRITE_2(sc, offreg, off); 756 757 for (i = AN_TIMEOUT; i--; DELAY(10)) { 758 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 759 break; 760 } 761 762 if (i <= 0) 763 return(ETIMEDOUT); 764 765 return (0); 766 } 767 768 int 769 an_read_data(sc, id, off, buf, len) 770 struct an_softc *sc; 771 int id, off; 772 caddr_t buf; 773 int len; 774 { 775 if (off != -1 && an_seek(sc, id, off, AN_BAP1)) 776 return(EIO); 777 778 bus_space_read_raw_multi_2(sc->an_btag, sc->an_bhandle, 779 AN_DATA1, buf, len & ~1); 780 if (len & 1) 781 ((u_int8_t *)buf)[len - 1] = CSR_READ_1(sc, AN_DATA1); 782 783 return (0); 784 } 785 786 int 787 an_write_data(sc, id, off, buf, len) 788 struct an_softc *sc; 789 int id, off; 790 caddr_t buf; 791 int len; 792 { 793 if (off != -1 && an_seek(sc, id, off, AN_BAP0)) 794 return(EIO); 795 796 bus_space_write_raw_multi_2(sc->an_btag, sc->an_bhandle, 797 AN_DATA0, buf, len & ~1); 798 if (len & 1) 799 CSR_WRITE_1(sc, AN_DATA0, ((u_int8_t *)buf)[len - 1]); 800 801 return (0); 802 } 803 804 /* 805 * Allocate a region of memory inside the NIC and zero 806 * it out. 807 */ 808 int 809 an_alloc_nicmem(sc, len, id) 810 struct an_softc *sc; 811 int len; 812 int *id; 813 { 814 int i; 815 816 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 817 printf("%s: failed to allocate %d bytes on NIC\n", 818 sc->sc_dev.dv_xname, len); 819 return(ENOMEM); 820 } 821 822 for (i = AN_TIMEOUT; i--; DELAY(10)) { 823 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 824 break; 825 } 826 827 if (i <= 0) 828 return(ETIMEDOUT); 829 830 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 831 *id = CSR_READ_2(sc, AN_ALLOC_FID); 832 833 if (an_seek(sc, *id, 0, AN_BAP0)) 834 return(EIO); 835 836 bus_space_set_multi_2(sc->an_btag, sc->an_bhandle, 837 AN_DATA0, 0, len / 2); 838 CSR_WRITE_1(sc, AN_DATA0, 0); 839 840 return(0); 841 } 842 843 void 844 an_setdef(sc, areq) 845 struct an_softc *sc; 846 struct an_req *areq; 847 { 848 struct sockaddr_dl *sdl; 849 struct ifaddr *ifa; 850 struct ifnet *ifp; 851 struct an_ltv_genconfig *cfg; 852 struct an_ltv_ssidlist *ssid; 853 struct an_ltv_aplist *ap; 854 struct an_ltv_gen *sp; 855 extern struct ifaddr **ifnet_addrs; 856 857 ifp = &sc->arpcom.ac_if; 858 859 switch (areq->an_type) { 860 case AN_RID_GENCONFIG: 861 cfg = (struct an_ltv_genconfig *)areq; 862 863 ifa = ifnet_addrs[ifp->if_index]; 864 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 865 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr, 866 ETHER_ADDR_LEN); 867 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN); 868 869 bcopy((char *)cfg, (char *)&sc->an_config, 870 sizeof(struct an_ltv_genconfig)); 871 break; 872 case AN_RID_SSIDLIST: 873 ssid = (struct an_ltv_ssidlist *)areq; 874 bcopy((char *)ssid, (char *)&sc->an_ssidlist, 875 sizeof(struct an_ltv_ssidlist)); 876 break; 877 case AN_RID_APLIST: 878 ap = (struct an_ltv_aplist *)areq; 879 bcopy((char *)ap, (char *)&sc->an_aplist, 880 sizeof(struct an_ltv_aplist)); 881 break; 882 case AN_RID_TX_SPEED: 883 sp = (struct an_ltv_gen *)areq; 884 sc->an_tx_rate = sp->an_val[0]; 885 break; 886 case AN_RID_WEP_VOLATILE: 887 /* Disable the MAC */ 888 an_cmd(sc, AN_CMD_DISABLE, 0); 889 890 /* Just write the key, we dont' want to save it */ 891 an_write_record(sc, (struct an_ltv_gen *)areq); 892 893 /* Turn the MAC back on */ 894 an_cmd(sc, AN_CMD_ENABLE, 0); 895 896 break; 897 case AN_RID_WEP_PERMANENT: 898 /* Disable the MAC */ 899 an_cmd(sc, AN_CMD_DISABLE, 0); 900 901 /* Just write the key, the card will save it in this mode */ 902 an_write_record(sc, (struct an_ltv_gen *)areq); 903 904 /* Turn the MAC back on */ 905 an_cmd(sc, AN_CMD_ENABLE, 0); 906 907 break; 908 default: 909 printf("%s: unknown RID: %x\n", 910 sc->sc_dev.dv_xname, areq->an_type); 911 return; 912 } 913 914 /* Reinitialize the card. */ 915 if (ifp->if_flags & IFF_UP) 916 an_init(sc); 917 } 918 919 /* 920 * We can't change the NIC configuration while the MAC is enabled, 921 * so in order to turn on RX monitor mode, we have to turn the MAC 922 * off first. 923 */ 924 void 925 an_promisc(sc, promisc) 926 struct an_softc *sc; 927 int promisc; 928 { 929 struct an_ltv_genconfig genconf; 930 931 /* Disable the MAC. */ 932 an_cmd(sc, AN_CMD_DISABLE, 0); 933 934 /* Set RX mode. */ 935 if (promisc && 936 !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) ) { 937 sc->an_rxmode = sc->an_config.an_rxmode; 938 sc->an_config.an_rxmode |= 939 AN_RXMODE_LAN_MONITOR_CURBSS; 940 } else { 941 sc->an_config.an_rxmode = sc->an_rxmode; 942 } 943 944 /* Transfer the configuration to the NIC */ 945 genconf = sc->an_config; 946 genconf.an_len = sizeof(struct an_ltv_genconfig); 947 genconf.an_type = AN_RID_GENCONFIG; 948 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 949 printf("%s: failed to set configuration\n", 950 sc->sc_dev.dv_xname); 951 return; 952 } 953 /* Turn the MAC back on. */ 954 an_cmd(sc, AN_CMD_ENABLE, 0); 955 } 956 957 int 958 an_ioctl(ifp, command, data) 959 struct ifnet *ifp; 960 u_long command; 961 caddr_t data; 962 { 963 int s, error = 0; 964 struct an_softc *sc; 965 struct an_req areq; 966 struct ifreq *ifr; 967 struct proc *p = curproc; 968 struct ifaddr *ifa = (struct ifaddr *)data; 969 970 s = splimp(); 971 972 sc = ifp->if_softc; 973 ifr = (struct ifreq *)data; 974 975 if (sc->an_gone) { 976 splx(s); 977 return(ENODEV); 978 } 979 980 if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) { 981 splx(s); 982 return error; 983 } 984 985 switch(command) { 986 case SIOCSIFADDR: 987 ifp->if_flags |= IFF_UP; 988 switch (ifa->ifa_addr->sa_family) { 989 #ifdef INET 990 case AF_INET: 991 an_init(sc); 992 arp_ifinit(&sc->arpcom, ifa); 993 break; 994 #endif 995 default: 996 an_init(sc); 997 break; 998 } 999 break; 1000 case SIOCSIFFLAGS: 1001 if (ifp->if_flags & IFF_UP) { 1002 if (ifp->if_flags & IFF_RUNNING && 1003 ifp->if_flags & IFF_PROMISC && 1004 !(sc->an_if_flags & IFF_PROMISC)) { 1005 an_promisc(sc, 1); 1006 } else if (ifp->if_flags & IFF_RUNNING && 1007 !(ifp->if_flags & IFF_PROMISC) && 1008 sc->an_if_flags & IFF_PROMISC) { 1009 an_promisc(sc, 0); 1010 an_reset(sc); 1011 } 1012 an_init(sc); 1013 } else { 1014 if (ifp->if_flags & IFF_RUNNING) 1015 an_stop(sc); 1016 } 1017 sc->an_if_flags = ifp->if_flags; 1018 error = 0; 1019 break; 1020 case SIOCADDMULTI: 1021 case SIOCDELMULTI: 1022 /* The Aironet has no multicast filter. */ 1023 error = 0; 1024 break; 1025 case SIOCGAIRONET: 1026 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1027 if (error) 1028 break; 1029 #ifdef ANCACHE 1030 if (areq.an_type == AN_RID_ZERO_CACHE) { 1031 error = suser(p->p_ucred, &p->p_acflag); 1032 if (error) 1033 break; 1034 sc->an_sigitems = sc->an_nextitem = 0; 1035 break; 1036 } else if (areq.an_type == AN_RID_READ_CACHE) { 1037 char *pt = (char *)&areq.an_val; 1038 bcopy((char *)&sc->an_sigitems, (char *)pt, 1039 sizeof(int)); 1040 pt += sizeof(int); 1041 areq.an_len = sizeof(int) / 2; 1042 bcopy((char *)&sc->an_sigcache, (char *)pt, 1043 sizeof(struct an_sigcache) * sc->an_sigitems); 1044 areq.an_len += ((sizeof(struct an_sigcache) * 1045 sc->an_sigitems) / 2) + 1; 1046 } else 1047 #endif 1048 if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { 1049 error = EINVAL; 1050 break; 1051 } 1052 error = copyout(&areq, ifr->ifr_data, sizeof(areq)); 1053 break; 1054 case SIOCSAIRONET: 1055 error = suser(p->p_ucred, &p->p_acflag); 1056 if (error) 1057 break; 1058 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1059 if (error) 1060 break; 1061 an_setdef(sc, &areq); 1062 break; 1063 default: 1064 error = EINVAL; 1065 break; 1066 } 1067 1068 splx(s); 1069 1070 return(error); 1071 } 1072 1073 int 1074 an_init_tx_ring(sc) 1075 struct an_softc *sc; 1076 { 1077 int i; 1078 int id; 1079 1080 if (sc->an_gone) 1081 return (0); 1082 1083 for (i = 0; i < AN_TX_RING_CNT; i++) { 1084 if (an_alloc_nicmem(sc, 1518 + 0x44, &id)) 1085 return(ENOMEM); 1086 sc->an_rdata.an_tx_fids[i] = id; 1087 sc->an_rdata.an_tx_ring[i] = 0; 1088 } 1089 1090 sc->an_rdata.an_tx_prod = 0; 1091 sc->an_rdata.an_tx_cons = 0; 1092 1093 return(0); 1094 } 1095 1096 void 1097 an_init(sc) 1098 struct an_softc *sc; 1099 { 1100 struct ifnet *ifp = &sc->arpcom.ac_if; 1101 struct an_ltv_ssidlist ssid; 1102 struct an_ltv_aplist aplist; 1103 struct an_ltv_genconfig genconf; 1104 int s; 1105 1106 if (sc->an_gone) 1107 return; 1108 1109 s = splimp(); 1110 1111 if (ifp->if_flags & IFF_RUNNING) 1112 an_stop(sc); 1113 1114 sc->an_associated = 0; 1115 1116 /* Allocate the TX buffers */ 1117 if (an_init_tx_ring(sc)) { 1118 printf("%s: tx buffer allocation failed\n", 1119 sc->sc_dev.dv_xname); 1120 splx(s); 1121 return; 1122 } 1123 1124 /* Set our MAC address. */ 1125 bcopy((char *)&sc->arpcom.ac_enaddr, 1126 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN); 1127 1128 if (ifp->if_flags & IFF_BROADCAST) 1129 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1130 else 1131 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1132 1133 if (ifp->if_flags & IFF_MULTICAST) 1134 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1135 1136 /* Initialize promisc mode. */ 1137 if (ifp->if_flags & IFF_PROMISC) 1138 sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS; 1139 1140 sc->an_rxmode = sc->an_config.an_rxmode; 1141 1142 /* Set the ssid list */ 1143 ssid = sc->an_ssidlist; 1144 ssid.an_type = AN_RID_SSIDLIST; 1145 ssid.an_len = sizeof(struct an_ltv_ssidlist); 1146 if (an_write_record(sc, (struct an_ltv_gen *)&ssid)) { 1147 printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname); 1148 splx(s); 1149 return; 1150 } 1151 1152 /* Set the AP list */ 1153 aplist = sc->an_aplist; 1154 aplist.an_type = AN_RID_APLIST; 1155 aplist.an_len = sizeof(struct an_ltv_aplist); 1156 if (an_write_record(sc, (struct an_ltv_gen *)&aplist)) { 1157 printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname); 1158 splx(s); 1159 return; 1160 } 1161 1162 /* Set the configuration in the NIC */ 1163 genconf = sc->an_config; 1164 genconf.an_len = sizeof(struct an_ltv_genconfig); 1165 genconf.an_type = AN_RID_GENCONFIG; 1166 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 1167 printf("%s: failed to set configuration\n", 1168 sc->sc_dev.dv_xname); 1169 splx(s); 1170 return; 1171 } 1172 1173 /* Enable the MAC */ 1174 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1175 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname); 1176 splx(s); 1177 return; 1178 } 1179 1180 /* enable interrupts */ 1181 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1182 1183 splx(s); 1184 1185 ifp->if_flags |= IFF_RUNNING; 1186 ifp->if_flags &= ~IFF_OACTIVE; 1187 1188 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz); 1189 } 1190 1191 void 1192 an_start(ifp) 1193 struct ifnet *ifp; 1194 { 1195 struct an_softc *sc; 1196 struct mbuf *m0 = NULL; 1197 struct an_txframe_802_3 tx_frame_802_3; 1198 struct ether_header *eh; 1199 u_int16_t len; 1200 int id; 1201 int idx; 1202 unsigned char txcontrol; 1203 1204 sc = ifp->if_softc; 1205 1206 if (sc->an_gone) 1207 return; 1208 1209 if (ifp->if_flags & IFF_OACTIVE) 1210 return; 1211 1212 if (!sc->an_associated) 1213 return; 1214 1215 idx = sc->an_rdata.an_tx_prod; 1216 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3)); 1217 1218 while(sc->an_rdata.an_tx_ring[idx] == 0) { 1219 IF_DEQUEUE(&ifp->if_snd, m0); 1220 if (m0 == NULL) 1221 break; 1222 1223 id = sc->an_rdata.an_tx_fids[idx]; 1224 eh = mtod(m0, struct ether_header *); 1225 1226 bcopy((char *)&eh->ether_dhost, 1227 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN); 1228 bcopy((char *)&eh->ether_shost, 1229 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); 1230 1231 len = m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ 1232 tx_frame_802_3.an_tx_802_3_payload_len = htole16(len); 1233 1234 m_copydata(m0, sizeof(struct ether_header) - 2, len, 1235 (caddr_t)&sc->an_txbuf); 1236 1237 txcontrol=AN_TXCTL_8023; 1238 /* write the txcontrol only */ 1239 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol, 1240 sizeof(txcontrol)); 1241 1242 /* 802_3 header */ 1243 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3, 1244 sizeof(struct an_txframe_802_3)); 1245 1246 /* in mbuf header type is just before payload */ 1247 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, len); 1248 1249 /* 1250 * If there's a BPF listner, bounce a copy of 1251 * this frame to him. 1252 */ 1253 #if NBPFILTER > 0 1254 if (ifp->if_bpf) 1255 BPF_MTAP(ifp, m0); 1256 #endif 1257 1258 m_freem(m0); 1259 m0 = NULL; 1260 1261 sc->an_rdata.an_tx_ring[idx] = id; 1262 if (an_cmd(sc, AN_CMD_TX, id)) 1263 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1264 1265 AN_INC(idx, AN_TX_RING_CNT); 1266 } 1267 1268 if (m0 != NULL) 1269 ifp->if_flags |= IFF_OACTIVE; 1270 1271 sc->an_rdata.an_tx_prod = idx; 1272 1273 /* 1274 * Set a timeout in case the chip goes out to lunch. 1275 */ 1276 ifp->if_timer = 5; 1277 } 1278 1279 void 1280 an_stop(sc) 1281 struct an_softc *sc; 1282 { 1283 struct ifnet *ifp; 1284 int i; 1285 1286 if (sc->an_gone) 1287 return; 1288 1289 ifp = &sc->arpcom.ac_if; 1290 1291 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 1292 CSR_WRITE_2(sc, AN_INT_EN, 0); 1293 an_cmd(sc, AN_CMD_DISABLE, 0); 1294 1295 for (i = 0; i < AN_TX_RING_CNT; i++) 1296 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 1297 1298 UNTIMEOUT(an_stats_update, sc, sc->an_stat_ch); 1299 1300 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1301 } 1302 1303 void 1304 an_watchdog(ifp) 1305 struct ifnet *ifp; 1306 { 1307 struct an_softc *sc; 1308 1309 sc = ifp->if_softc; 1310 1311 if (sc->an_gone) 1312 return; 1313 1314 printf("%s: device timeout\n", sc->sc_dev.dv_xname); 1315 1316 an_reset(sc); 1317 an_init(sc); 1318 1319 ifp->if_oerrors++; 1320 } 1321 1322 void 1323 an_shutdown(self) 1324 void *self; 1325 { 1326 an_stop(self); 1327 } 1328 1329 #ifdef ANCACHE 1330 /* Aironet signal strength cache code. 1331 * store signal/noise/quality on per MAC src basis in 1332 * a small fixed cache. The cache wraps if > MAX slots 1333 * used. The cache may be zeroed out to start over. 1334 * Two simple filters exist to reduce computation: 1335 * 1. ip only (literally 0x800) which may be used 1336 * to ignore some packets. It defaults to ip only. 1337 * it could be used to focus on broadcast, non-IP 802.11 beacons. 1338 * 2. multicast/broadcast only. This may be used to 1339 * ignore unicast packets and only cache signal strength 1340 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 1341 * beacons and not unicast traffic. 1342 * 1343 * The cache stores (MAC src(index), IP src (major clue), signal, 1344 * quality, noise) 1345 * 1346 * No apologies for storing IP src here. It's easy and saves much 1347 * trouble elsewhere. The cache is assumed to be INET dependent, 1348 * although it need not be. 1349 * 1350 * Note: the Aironet only has a single byte of signal strength value 1351 * in the rx frame header, and it's not scaled to anything sensible. 1352 * This is kind of lame, but it's all we've got. 1353 */ 1354 1355 #ifdef documentation 1356 1357 int an_sigitems; /* number of cached entries */ 1358 struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 1359 int an_nextitem; /* index/# of entries */ 1360 1361 1362 #endif 1363 1364 /* control variables for cache filtering. Basic idea is 1365 * to reduce cost (e.g., to only Mobile-IP agent beacons 1366 * which are broadcast or multicast). Still you might 1367 * want to measure signal strength anth unicast ping packets 1368 * on a pt. to pt. ant. setup. 1369 */ 1370 /* set true if you want to limit cache items to broadcast/mcast 1371 * only packets (not unicast). Useful for mobile-ip beacons which 1372 * are broadcast/multicast at network layer. Default is all packets 1373 * so ping/unicast anll work say anth pt. to pt. antennae setup. 1374 */ 1375 #if 0 1376 static int an_cache_mcastonly = 0; 1377 SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 1378 &an_cache_mcastonly, 0, ""); 1379 1380 /* set true if you want to limit cache items to IP packets only 1381 */ 1382 static int an_cache_iponly = 1; 1383 SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 1384 &an_cache_iponly, 0, ""); 1385 #endif 1386 1387 /* 1388 * an_cache_store, per rx packet store signal 1389 * strength in MAC (src) indexed cache. 1390 */ 1391 void 1392 an_cache_store (sc, eh, m, rx_quality) 1393 struct an_softc *sc; 1394 struct ether_header *eh; 1395 struct mbuf *m; 1396 unsigned short rx_quality; 1397 { 1398 struct ip *ip = 0; 1399 int i; 1400 static int cache_slot = 0; /* use this cache entry */ 1401 static int wrapindex = 0; /* next "free" cache entry */ 1402 int saanp=0; 1403 1404 /* filters: 1405 * 1. ip only 1406 * 2. configurable filter to throw out unicast packets, 1407 * keep multicast only. 1408 */ 1409 1410 if ((ntohs(eh->ether_type) == 0x800)) 1411 saanp = 1; 1412 1413 /* filter for ip packets only 1414 */ 1415 if (sc->an_cache_iponly && !saanp) 1416 return; 1417 1418 /* filter for broadcast/multicast only */ 1419 if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) 1420 return; 1421 1422 #ifdef SIGDEBUG 1423 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 1424 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 1425 #endif 1426 1427 /* find the ip header. we want to store the ip_src address */ 1428 if (saanp) 1429 ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header)); 1430 1431 /* do a linear search for a matching MAC address 1432 * in the cache table 1433 * . MAC address is 6 bytes, 1434 * . var w_nextitem holds total number of entries already cached 1435 */ 1436 for(i = 0; i < sc->an_nextitem; i++) 1437 if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6)) 1438 /* Match!, 1439 * so we already have this entry, update the data 1440 */ 1441 break; 1442 1443 /* did we find a matching mac address? 1444 * if yes, then overwrite a previously existing cache entry 1445 */ 1446 if (i < sc->an_nextitem ) 1447 cache_slot = i; 1448 1449 /* else, have a new address entry,so 1450 * add this new entry, 1451 * if table full, then we need to replace LRU entry 1452 */ 1453 else { 1454 1455 /* check for space in cache table 1456 * note: an_nextitem also holds number of entries 1457 * added in the cache table 1458 */ 1459 if ( sc->an_nextitem < MAXANCACHE ) { 1460 cache_slot = sc->an_nextitem; 1461 sc->an_nextitem++; 1462 sc->an_sigitems = sc->an_nextitem; 1463 } 1464 /* no space found, so simply wrap anth wrap index 1465 * and "zap" the next entry 1466 */ 1467 else { 1468 if (wrapindex == MAXANCACHE) 1469 wrapindex = 0; 1470 cache_slot = wrapindex++; 1471 } 1472 } 1473 1474 /* invariant: cache_slot now points at some slot 1475 * in cache. 1476 */ 1477 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 1478 log(LOG_ERR, "an_cache_store, bad index: %d of " 1479 "[0..%d], gross cache error\n", 1480 cache_slot, MAXANCACHE); 1481 return; 1482 } 1483 1484 /* store items in cache 1485 * .ip source address 1486 * .mac src 1487 * .signal, etc. 1488 */ 1489 if (saanp) 1490 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 1491 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); 1492 1493 sc->an_sigcache[cache_slot].signal = rx_quality; 1494 } 1495 #endif 1496