1 /* $OpenBSD: an.c,v 1.21 2002/01/02 18:34:11 mickey 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.21 2001/09/10 02:05:09 brooks 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 int an_media_change __P((struct ifnet *)); 166 void an_media_status __P((struct ifnet *, struct ifmediareq *)); 167 168 static __inline void 169 an_swap16(u_int16_t *p, int cnt) 170 { 171 for (; cnt--; p++) 172 *p = swap16(*p); 173 } 174 175 int 176 an_attach(sc) 177 struct an_softc *sc; 178 { 179 struct ifnet *ifp = &sc->arpcom.ac_if; 180 181 sc->an_gone = 0; 182 sc->an_associated = 0; 183 184 /* disable interrupts */ 185 CSR_WRITE_2(sc, AN_INT_EN, 0); 186 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff); 187 188 /* Reset the NIC. */ 189 an_reset(sc); 190 191 /* Load factory config */ 192 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 193 printf("%s: failed to load config data\n", ifp->if_xname); 194 return(EIO); 195 } 196 197 /* Read the current configuration */ 198 sc->an_config.an_type = AN_RID_GENCONFIG; 199 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 200 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 201 printf("%s: read record failed\n", ifp->if_xname); 202 return(EIO); 203 } 204 205 /* Read the card capabilities */ 206 sc->an_caps.an_type = AN_RID_CAPABILITIES; 207 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 208 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 209 printf("%s: read record failed\n", ifp->if_xname); 210 return(EIO); 211 } 212 213 /* Read ssid list */ 214 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 215 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 216 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 217 printf("%s: read record failed\n", ifp->if_xname); 218 return(EIO); 219 } 220 221 /* Read AP list */ 222 sc->an_aplist.an_type = AN_RID_APLIST; 223 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 224 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 225 printf("%s: read record failed\n", ifp->if_xname); 226 return(EIO); 227 } 228 229 bcopy((char *)&sc->an_caps.an_oemaddr, 230 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 231 232 printf(": address %6s\n", ether_sprintf(sc->arpcom.ac_enaddr)); 233 234 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 235 ifp->if_softc = sc; 236 ifp->if_mtu = ETHERMTU; 237 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 238 ifp->if_ioctl = an_ioctl; 239 ifp->if_start = an_start; 240 ifp->if_watchdog = an_watchdog; 241 ifp->if_baudrate = 10000000; 242 243 bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); 244 bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename, 245 sizeof(AN_DEFAULT_NODENAME) - 1); 246 247 bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1)); 248 bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1, 249 sizeof(AN_DEFAULT_NETNAME) - 1); 250 sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME); 251 252 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 253 254 sc->an_tx_rate = 0; 255 bzero((char *)&sc->an_stats, sizeof(sc->an_stats)); 256 #ifdef ANCACHE 257 sc->an_sigitems = sc->an_nextitem = 0; 258 #endif 259 260 ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status); 261 #define ADD(m, c) ifmedia_add(&sc->an_ifmedia, (m), (c), NULL) 262 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 263 IFM_IEEE80211_ADHOC, 0), 0); 264 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); 265 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 266 IFM_IEEE80211_ADHOC, 0), 0); 267 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); 268 if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) { 269 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 270 IFM_IEEE80211_ADHOC, 0), 0); 271 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); 272 } 273 if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) { 274 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 275 IFM_IEEE80211_ADHOC, 0), 0); 276 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); 277 } 278 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 279 IFM_IEEE80211_ADHOC, 0), 0); 280 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); 281 #undef ADD 282 ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 283 0, 0)); 284 285 /* 286 * Call MI attach routines. 287 */ 288 if_attach(ifp); 289 ether_ifattach(ifp); 290 timeout_set(&sc->an_stat_ch, an_stats_update, sc); 291 #if NBPFILTER > 0 292 BPFATTACH(&sc->arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, 293 sizeof(struct ether_header)); 294 #endif 295 296 shutdownhook_establish(an_shutdown, sc); 297 298 an_reset(sc); 299 an_init(sc); 300 301 return(0); 302 } 303 304 void 305 an_rxeof(sc) 306 struct an_softc *sc; 307 { 308 struct ifnet *ifp; 309 struct ether_header *eh; 310 #ifdef ANCACHE 311 struct an_rxframe rx_frame; 312 #endif 313 struct an_rxframe_802_3 rx_frame_802_3; 314 struct mbuf *m; 315 int id, error = 0; 316 317 ifp = &sc->arpcom.ac_if; 318 319 id = CSR_READ_2(sc, AN_RX_FID); 320 321 MGETHDR(m, M_DONTWAIT, MT_DATA); 322 if (m == NULL) { 323 ifp->if_ierrors++; 324 return; 325 } 326 MCLGET(m, M_DONTWAIT); 327 if (!(m->m_flags & M_EXT)) { 328 m_freem(m); 329 ifp->if_ierrors++; 330 return; 331 } 332 333 m->m_pkthdr.rcvif = ifp; 334 335 eh = mtod(m, struct ether_header *); 336 337 #ifdef ANCACHE 338 /* Read NIC frame header */ 339 if (an_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 340 ifp->if_ierrors++; 341 return; 342 } 343 #endif 344 /* Read in the 802_3 frame header */ 345 if (an_read_data(sc, id, 0x34, (caddr_t)&rx_frame_802_3, 346 sizeof(rx_frame_802_3))) { 347 ifp->if_ierrors++; 348 return; 349 } 350 351 if (rx_frame_802_3.an_rx_802_3_status != 0) { 352 ifp->if_ierrors++; 353 return; 354 } 355 356 /* Check for insane frame length */ 357 if (letoh16(rx_frame_802_3.an_rx_802_3_payload_len) > MCLBYTES) { 358 ifp->if_ierrors++; 359 return; 360 } 361 362 m->m_pkthdr.len = m->m_len = 363 letoh16(rx_frame_802_3.an_rx_802_3_payload_len) + 12; 364 365 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr, 366 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 367 bcopy((char *)&rx_frame_802_3.an_rx_src_addr, 368 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 369 370 /* in mbuf header type is just before payload */ 371 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type), 372 letoh16(rx_frame_802_3.an_rx_802_3_payload_len)); 373 if (error) { 374 m_freem(m); 375 ifp->if_ierrors++; 376 return; 377 } 378 379 ifp->if_ipackets++; 380 381 #if NBPFILTER > 0 382 /* Handle BPF listeners. */ 383 if (ifp->if_bpf) 384 BPF_MTAP(ifp, m); 385 #endif 386 387 /* Receive packet. */ 388 #ifdef ANCACHE 389 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); 390 #endif 391 ether_input_mbuf(ifp, m); 392 } 393 394 void 395 an_txeof(sc, status) 396 struct an_softc *sc; 397 int status; 398 { 399 struct ifnet *ifp; 400 int id; 401 402 ifp = &sc->arpcom.ac_if; 403 404 ifp->if_timer = 0; 405 ifp->if_flags &= ~IFF_OACTIVE; 406 407 id = CSR_READ_2(sc, AN_TX_CMP_FID); 408 409 if (status & AN_EV_TX_EXC) 410 ifp->if_oerrors++; 411 else 412 ifp->if_opackets++; 413 414 if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons]) 415 printf("%s: id mismatch: expected %x, got %x\n", ifp->if_xname, 416 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id); 417 418 sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] = 0; 419 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT); 420 } 421 422 /* 423 * We abuse the stats updater to check the current NIC status. This 424 * is important because we don't want to allow transmissions until 425 * the NIC has synchronized to the current cell (either as the master 426 * in an ad-hoc group, or as a station connected to an access point). 427 */ 428 void 429 an_stats_update(xsc) 430 void *xsc; 431 { 432 struct an_softc *sc; 433 struct ifnet *ifp; 434 int s; 435 436 s = splimp(); 437 438 sc = xsc; 439 ifp = &sc->arpcom.ac_if; 440 441 sc->an_status.an_type = AN_RID_STATUS; 442 sc->an_status.an_len = sizeof(struct an_ltv_status); 443 an_read_record(sc, (struct an_ltv_gen *)&sc->an_status); 444 445 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC) 446 sc->an_associated = 1; 447 else 448 sc->an_associated = 0; 449 450 /* Don't do this while we're transmitting */ 451 if (!(ifp->if_flags & IFF_OACTIVE)) { 452 sc->an_stats.an_len = sizeof(struct an_ltv_stats); 453 sc->an_stats.an_type = AN_RID_32BITS_CUM; 454 an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len); 455 } 456 457 splx(s); 458 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz); 459 } 460 461 int 462 an_intr(xsc) 463 void *xsc; 464 { 465 struct an_softc *sc; 466 struct ifnet *ifp; 467 u_int16_t status; 468 469 sc = (struct an_softc*)xsc; 470 471 if (sc->an_gone) 472 return 0; 473 474 ifp = &sc->arpcom.ac_if; 475 476 if (!(ifp->if_flags & IFF_UP)) { 477 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF); 478 CSR_WRITE_2(sc, AN_INT_EN, 0); 479 return 0; 480 } 481 482 /* Disable interrupts. */ 483 CSR_WRITE_2(sc, AN_INT_EN, 0); 484 485 status = CSR_READ_2(sc, AN_EVENT_STAT); 486 CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS); 487 488 if (status & AN_EV_AWAKE) { 489 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE); 490 } 491 492 if (status & AN_EV_LINKSTAT) { 493 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED) 494 sc->an_associated = 1; 495 else 496 sc->an_associated = 0; 497 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 498 } 499 500 if (status & AN_EV_RX) { 501 an_rxeof(sc); 502 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 503 } 504 505 if (status & AN_EV_TX) { 506 an_txeof(sc, status); 507 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX); 508 } 509 510 if (status & AN_EV_TX_EXC) { 511 an_txeof(sc, status); 512 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC); 513 } 514 515 if (status & AN_EV_ALLOC) 516 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 517 518 /* Re-enable interrupts. */ 519 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 520 521 if (ifp->if_snd.ifq_head != NULL) 522 an_start(ifp); 523 524 return 1; 525 } 526 527 int 528 an_cmd(sc, cmd, val) 529 struct an_softc *sc; 530 int cmd; 531 int val; 532 { 533 int i, stat; 534 535 /* make sure previous command completed */ 536 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 537 printf("%s: command busy\n", sc->sc_dev.dv_xname); 538 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 539 } 540 541 CSR_WRITE_2(sc, AN_PARAM0, val); 542 CSR_WRITE_2(sc, AN_PARAM1, 0); 543 CSR_WRITE_2(sc, AN_PARAM2, 0); 544 DELAY(10); 545 CSR_WRITE_2(sc, AN_COMMAND, cmd); 546 DELAY(10); 547 548 for (i = AN_TIMEOUT; i--; DELAY(10)) { 549 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 550 break; 551 else { 552 if (CSR_READ_2(sc, AN_COMMAND) == cmd) { 553 DELAY(10); 554 CSR_WRITE_2(sc, AN_COMMAND, cmd); 555 } 556 } 557 } 558 559 stat = CSR_READ_2(sc, AN_STATUS); 560 561 /* clear stuck command busy if needed */ 562 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 563 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 564 } 565 566 /* Ack the command */ 567 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 568 569 if (i <= 0) 570 return(ETIMEDOUT); 571 572 if (stat & AN_STAT_CMD_RESULT) 573 return(EIO); 574 575 return(0); 576 } 577 578 /* 579 * This reset sequence may look a little strange, but this is the 580 * most reliable method I've found to really kick the NIC in the 581 * head and force it to reboot correctly. 582 */ 583 void 584 an_reset(sc) 585 struct an_softc *sc; 586 { 587 if (sc->an_gone) 588 return; 589 /*printf("ena ");*/ 590 an_cmd(sc, AN_CMD_ENABLE, 0); 591 /* printf("rst ");*/ 592 an_cmd(sc, AN_CMD_FW_RESTART, 0); 593 /*printf("nop ");*/ 594 an_cmd(sc, AN_CMD_NOOP2, 0); 595 596 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) 597 printf("%s: reset failed\n", sc->sc_dev.dv_xname); 598 599 an_cmd(sc, AN_CMD_DISABLE, 0); 600 } 601 602 /* 603 * Read an LTV record from the NIC. 604 */ 605 int 606 an_read_record(sc, ltv) 607 struct an_softc *sc; 608 struct an_ltv_gen *ltv; 609 { 610 u_int16_t *ptr, len; 611 int i; 612 u_int16_t ltv_data_length; 613 614 if (ltv->an_len < 4 || ltv->an_type == 0) 615 return(EINVAL); 616 617 /* Tell the NIC to enter record read mode. */ 618 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) { 619 printf("%s: RID 0x%04x access failed\n", 620 sc->sc_dev.dv_xname, ltv->an_type); 621 return(EIO); 622 } 623 624 /* Seek to the record. */ 625 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) { 626 printf("%s: RID 0x%04x seek to record failed\n", 627 sc->sc_dev.dv_xname, ltv->an_type); 628 return(EIO); 629 } 630 631 /* 632 * Read the length to make sure it 633 * matches what we expect (this verifies that we have enough 634 * room to hold all of the returned data). 635 */ 636 len = CSR_READ_2(sc, AN_DATA1); 637 638 /* 639 * Work out record's data length, which is struct length - type word 640 * as we have just read the length. 641 */ 642 ltv_data_length = ltv->an_len - sizeof(u_int16_t); 643 644 if (len > ltv_data_length) { 645 printf("%s: RID 0x%04x record length mismatch -- expected %d, " 646 "got %d\n", sc->sc_dev.dv_xname, ltv->an_type, 647 ltv_data_length, len); 648 return(ENOSPC); 649 } 650 651 /* Now read the data. */ 652 ptr = ltv->an_val; 653 for (i = 0; i < (len - 1) >> 1; i++) 654 ptr[i] = CSR_READ_2(sc, AN_DATA1); 655 656 #if BYTE_ORDER == BIG_ENDIAN 657 switch (ltv->an_type) { 658 case AN_RID_GENCONFIG: 659 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 660 an_swap16(<v->an_val[63], 8); /* an_nodename */ 661 break; 662 case AN_RID_SSIDLIST: 663 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 664 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 665 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 666 break; 667 case AN_RID_APLIST: 668 an_swap16(ltv->an_val, 12); 669 break; 670 case AN_RID_DRVNAME: 671 an_swap16(ltv->an_val, 8); 672 break; 673 case AN_RID_CAPABILITIES: 674 an_swap16(ltv->an_val, 2); /* an_oui */ 675 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 676 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 677 break; 678 case AN_RID_STATUS: 679 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 680 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 681 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 682 break; 683 case AN_RID_WEP_VOLATILE: 684 case AN_RID_WEP_PERMANENT: 685 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 686 an_swap16(<v->an_val[5], 6); 687 break; 688 case AN_RID_32BITS_CUM: 689 for (i = 0x60; i--; ) { 690 u_int16_t t = ltv->an_val[i * 2] ^ ltv->an_val[i * 2 + 1]; 691 ltv->an_val[i * 2] ^= t; 692 ltv->an_val[i * 2 + 1] ^= t; 693 } 694 break; 695 } 696 #endif 697 return(0); 698 } 699 700 /* 701 * Same as read, except we inject data instead of reading it. 702 */ 703 int 704 an_write_record(sc, ltv) 705 struct an_softc *sc; 706 struct an_ltv_gen *ltv; 707 { 708 u_int16_t *ptr; 709 int i; 710 711 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 712 return(EIO); 713 714 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 715 return(EIO); 716 717 #if BYTE_ORDER == BIG_ENDIAN 718 switch (ltv->an_type) { 719 case AN_RID_GENCONFIG: 720 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 721 an_swap16(<v->an_val[63], 8); /* an_nodename */ 722 break; 723 case AN_RID_SSIDLIST: 724 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 725 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 726 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 727 break; 728 case AN_RID_APLIST: 729 an_swap16(ltv->an_val, 12); 730 break; 731 case AN_RID_DRVNAME: 732 an_swap16(ltv->an_val, 8); 733 break; 734 case AN_RID_CAPABILITIES: 735 an_swap16(ltv->an_val, 2); /* an_oui */ 736 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 737 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 738 break; 739 case AN_RID_STATUS: 740 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 741 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 742 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 743 break; 744 case AN_RID_WEP_VOLATILE: 745 case AN_RID_WEP_PERMANENT: 746 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 747 an_swap16(<v->an_val[5], 6); 748 break; 749 } 750 #endif 751 752 CSR_WRITE_2(sc, AN_DATA1, ltv->an_len); 753 754 ptr = ltv->an_val; 755 for (i = 0; i < (ltv->an_len - 1) >> 1; i++) 756 CSR_WRITE_2(sc, AN_DATA1, ptr[i]); 757 758 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 759 return(EIO); 760 761 return(0); 762 } 763 764 int 765 an_seek(sc, id, off, chan) 766 struct an_softc *sc; 767 int id, off, chan; 768 { 769 int i; 770 int selreg, offreg; 771 772 switch (chan) { 773 case AN_BAP0: 774 selreg = AN_SEL0; 775 offreg = AN_OFF0; 776 break; 777 case AN_BAP1: 778 selreg = AN_SEL1; 779 offreg = AN_OFF1; 780 break; 781 default: 782 printf("%s: invalid data path: %x\n", 783 sc->sc_dev.dv_xname, chan); 784 return (EIO); 785 } 786 787 CSR_WRITE_2(sc, selreg, id); 788 CSR_WRITE_2(sc, offreg, off); 789 790 for (i = AN_TIMEOUT; i--; DELAY(10)) { 791 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 792 break; 793 } 794 795 if (i <= 0) 796 return(ETIMEDOUT); 797 798 return (0); 799 } 800 801 int 802 an_read_data(sc, id, off, buf, len) 803 struct an_softc *sc; 804 int id, off; 805 caddr_t buf; 806 int len; 807 { 808 if (off != -1 && an_seek(sc, id, off, AN_BAP1)) 809 return(EIO); 810 811 bus_space_read_raw_multi_2(sc->an_btag, sc->an_bhandle, 812 AN_DATA1, buf, len & ~1); 813 if (len & 1) 814 ((u_int8_t *)buf)[len - 1] = CSR_READ_1(sc, AN_DATA1); 815 816 return (0); 817 } 818 819 int 820 an_write_data(sc, id, off, buf, len) 821 struct an_softc *sc; 822 int id, off; 823 caddr_t buf; 824 int len; 825 { 826 if (off != -1 && an_seek(sc, id, off, AN_BAP0)) 827 return(EIO); 828 829 bus_space_write_raw_multi_2(sc->an_btag, sc->an_bhandle, 830 AN_DATA0, buf, len & ~1); 831 if (len & 1) 832 CSR_WRITE_1(sc, AN_DATA0, ((u_int8_t *)buf)[len - 1]); 833 834 return (0); 835 } 836 837 /* 838 * Allocate a region of memory inside the NIC and zero 839 * it out. 840 */ 841 int 842 an_alloc_nicmem(sc, len, id) 843 struct an_softc *sc; 844 int len; 845 int *id; 846 { 847 int i; 848 849 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 850 printf("%s: failed to allocate %d bytes on NIC\n", 851 sc->sc_dev.dv_xname, len); 852 return(ENOMEM); 853 } 854 855 for (i = AN_TIMEOUT; i--; DELAY(10)) { 856 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 857 break; 858 } 859 860 if (i <= 0) 861 return(ETIMEDOUT); 862 863 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 864 *id = CSR_READ_2(sc, AN_ALLOC_FID); 865 866 if (an_seek(sc, *id, 0, AN_BAP0)) 867 return(EIO); 868 869 bus_space_set_multi_2(sc->an_btag, sc->an_bhandle, 870 AN_DATA0, 0, len / 2); 871 CSR_WRITE_1(sc, AN_DATA0, 0); 872 873 return(0); 874 } 875 876 void 877 an_setdef(sc, areq) 878 struct an_softc *sc; 879 struct an_req *areq; 880 { 881 struct sockaddr_dl *sdl; 882 struct ifaddr *ifa; 883 struct ifnet *ifp; 884 struct an_ltv_genconfig *cfg; 885 struct an_ltv_ssidlist *ssid; 886 struct an_ltv_aplist *ap; 887 struct an_ltv_gen *sp; 888 extern struct ifaddr **ifnet_addrs; 889 890 ifp = &sc->arpcom.ac_if; 891 892 switch (areq->an_type) { 893 case AN_RID_GENCONFIG: 894 cfg = (struct an_ltv_genconfig *)areq; 895 896 ifa = ifnet_addrs[ifp->if_index]; 897 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 898 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr, 899 ETHER_ADDR_LEN); 900 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN); 901 902 bcopy((char *)cfg, (char *)&sc->an_config, 903 sizeof(struct an_ltv_genconfig)); 904 break; 905 case AN_RID_SSIDLIST: 906 ssid = (struct an_ltv_ssidlist *)areq; 907 bcopy((char *)ssid, (char *)&sc->an_ssidlist, 908 sizeof(struct an_ltv_ssidlist)); 909 break; 910 case AN_RID_APLIST: 911 ap = (struct an_ltv_aplist *)areq; 912 bcopy((char *)ap, (char *)&sc->an_aplist, 913 sizeof(struct an_ltv_aplist)); 914 break; 915 case AN_RID_TX_SPEED: 916 sp = (struct an_ltv_gen *)areq; 917 sc->an_tx_rate = sp->an_val[0]; 918 break; 919 case AN_RID_WEP_VOLATILE: 920 /* Disable the MAC */ 921 an_cmd(sc, AN_CMD_DISABLE, 0); 922 923 /* Just write the key, we dont' want to save it */ 924 an_write_record(sc, (struct an_ltv_gen *)areq); 925 926 /* Turn the MAC back on */ 927 an_cmd(sc, AN_CMD_ENABLE, 0); 928 929 break; 930 case AN_RID_WEP_PERMANENT: 931 /* Disable the MAC */ 932 an_cmd(sc, AN_CMD_DISABLE, 0); 933 934 /* Just write the key, the card will save it in this mode */ 935 an_write_record(sc, (struct an_ltv_gen *)areq); 936 937 /* Turn the MAC back on */ 938 an_cmd(sc, AN_CMD_ENABLE, 0); 939 940 break; 941 default: 942 printf("%s: unknown RID: %x\n", 943 sc->sc_dev.dv_xname, areq->an_type); 944 return; 945 } 946 947 /* Reinitialize the card. */ 948 if (ifp->if_flags & IFF_UP) 949 an_init(sc); 950 } 951 952 /* 953 * We can't change the NIC configuration while the MAC is enabled, 954 * so in order to turn on RX monitor mode, we have to turn the MAC 955 * off first. 956 */ 957 void 958 an_promisc(sc, promisc) 959 struct an_softc *sc; 960 int promisc; 961 { 962 struct an_ltv_genconfig genconf; 963 964 /* Disable the MAC. */ 965 an_cmd(sc, AN_CMD_DISABLE, 0); 966 967 /* Set RX mode. */ 968 if (promisc && 969 !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) ) { 970 sc->an_rxmode = sc->an_config.an_rxmode; 971 sc->an_config.an_rxmode |= 972 AN_RXMODE_LAN_MONITOR_CURBSS; 973 } else { 974 sc->an_config.an_rxmode = sc->an_rxmode; 975 } 976 977 /* Transfer the configuration to the NIC */ 978 genconf = sc->an_config; 979 genconf.an_len = sizeof(struct an_ltv_genconfig); 980 genconf.an_type = AN_RID_GENCONFIG; 981 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 982 printf("%s: failed to set configuration\n", 983 sc->sc_dev.dv_xname); 984 return; 985 } 986 /* Turn the MAC back on. */ 987 an_cmd(sc, AN_CMD_ENABLE, 0); 988 } 989 990 int 991 an_ioctl(ifp, command, data) 992 struct ifnet *ifp; 993 u_long command; 994 caddr_t data; 995 { 996 int s, error = 0; 997 struct an_softc *sc; 998 struct an_req areq; 999 struct ifreq *ifr; 1000 struct proc *p = curproc; 1001 struct ifaddr *ifa = (struct ifaddr *)data; 1002 1003 s = splimp(); 1004 1005 sc = ifp->if_softc; 1006 ifr = (struct ifreq *)data; 1007 1008 if (sc->an_gone) { 1009 splx(s); 1010 return(ENODEV); 1011 } 1012 1013 if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) { 1014 splx(s); 1015 return error; 1016 } 1017 1018 switch(command) { 1019 case SIOCSIFADDR: 1020 ifp->if_flags |= IFF_UP; 1021 switch (ifa->ifa_addr->sa_family) { 1022 #ifdef INET 1023 case AF_INET: 1024 an_init(sc); 1025 arp_ifinit(&sc->arpcom, ifa); 1026 break; 1027 #endif 1028 default: 1029 an_init(sc); 1030 break; 1031 } 1032 break; 1033 case SIOCSIFFLAGS: 1034 if (ifp->if_flags & IFF_UP) { 1035 if (ifp->if_flags & IFF_RUNNING && 1036 ifp->if_flags & IFF_PROMISC && 1037 !(sc->an_if_flags & IFF_PROMISC)) { 1038 an_promisc(sc, 1); 1039 } else if (ifp->if_flags & IFF_RUNNING && 1040 !(ifp->if_flags & IFF_PROMISC) && 1041 sc->an_if_flags & IFF_PROMISC) { 1042 an_promisc(sc, 0); 1043 an_reset(sc); 1044 } 1045 an_init(sc); 1046 } else { 1047 if (ifp->if_flags & IFF_RUNNING) 1048 an_stop(sc); 1049 } 1050 sc->an_if_flags = ifp->if_flags; 1051 error = 0; 1052 break; 1053 case SIOCSIFMEDIA: 1054 case SIOCGIFMEDIA: 1055 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command); 1056 break; 1057 case SIOCADDMULTI: 1058 case SIOCDELMULTI: 1059 /* The Aironet has no multicast filter. */ 1060 error = 0; 1061 break; 1062 case SIOCGAIRONET: 1063 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1064 if (error) 1065 break; 1066 #ifdef ANCACHE 1067 if (areq.an_type == AN_RID_ZERO_CACHE) { 1068 error = suser(p->p_ucred, &p->p_acflag); 1069 if (error) 1070 break; 1071 sc->an_sigitems = sc->an_nextitem = 0; 1072 break; 1073 } else if (areq.an_type == AN_RID_READ_CACHE) { 1074 char *pt = (char *)&areq.an_val; 1075 bcopy((char *)&sc->an_sigitems, (char *)pt, 1076 sizeof(int)); 1077 pt += sizeof(int); 1078 areq.an_len = sizeof(int) / 2; 1079 bcopy((char *)&sc->an_sigcache, (char *)pt, 1080 sizeof(struct an_sigcache) * sc->an_sigitems); 1081 areq.an_len += ((sizeof(struct an_sigcache) * 1082 sc->an_sigitems) / 2) + 1; 1083 } else 1084 #endif 1085 if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { 1086 error = EINVAL; 1087 break; 1088 } 1089 error = copyout(&areq, ifr->ifr_data, sizeof(areq)); 1090 break; 1091 case SIOCSAIRONET: 1092 error = suser(p->p_ucred, &p->p_acflag); 1093 if (error) 1094 break; 1095 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1096 if (error) 1097 break; 1098 an_setdef(sc, &areq); 1099 break; 1100 default: 1101 error = EINVAL; 1102 break; 1103 } 1104 1105 splx(s); 1106 1107 return(error); 1108 } 1109 1110 int 1111 an_init_tx_ring(sc) 1112 struct an_softc *sc; 1113 { 1114 int i; 1115 int id; 1116 1117 if (sc->an_gone) 1118 return (0); 1119 1120 for (i = 0; i < AN_TX_RING_CNT; i++) { 1121 if (an_alloc_nicmem(sc, 1518 + 0x44, &id)) 1122 return(ENOMEM); 1123 sc->an_rdata.an_tx_fids[i] = id; 1124 sc->an_rdata.an_tx_ring[i] = 0; 1125 } 1126 1127 sc->an_rdata.an_tx_prod = 0; 1128 sc->an_rdata.an_tx_cons = 0; 1129 1130 return(0); 1131 } 1132 1133 void 1134 an_init(sc) 1135 struct an_softc *sc; 1136 { 1137 struct ifnet *ifp = &sc->arpcom.ac_if; 1138 struct an_ltv_ssidlist ssid; 1139 struct an_ltv_aplist aplist; 1140 struct an_ltv_genconfig genconf; 1141 int s; 1142 1143 if (sc->an_gone) 1144 return; 1145 1146 s = splimp(); 1147 1148 if (ifp->if_flags & IFF_RUNNING) 1149 an_stop(sc); 1150 1151 sc->an_associated = 0; 1152 1153 /* Allocate the TX buffers */ 1154 if (an_init_tx_ring(sc)) { 1155 printf("%s: tx buffer allocation failed\n", 1156 sc->sc_dev.dv_xname); 1157 splx(s); 1158 return; 1159 } 1160 1161 /* Set our MAC address. */ 1162 bcopy((char *)&sc->arpcom.ac_enaddr, 1163 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN); 1164 1165 if (ifp->if_flags & IFF_BROADCAST) 1166 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1167 else 1168 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1169 1170 if (ifp->if_flags & IFF_MULTICAST) 1171 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1172 1173 /* Initialize promisc mode. */ 1174 if (ifp->if_flags & IFF_PROMISC) 1175 sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS; 1176 1177 sc->an_rxmode = sc->an_config.an_rxmode; 1178 1179 /* Set the ssid list */ 1180 ssid = sc->an_ssidlist; 1181 ssid.an_type = AN_RID_SSIDLIST; 1182 ssid.an_len = sizeof(struct an_ltv_ssidlist); 1183 if (an_write_record(sc, (struct an_ltv_gen *)&ssid)) { 1184 printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname); 1185 splx(s); 1186 return; 1187 } 1188 1189 /* Set the AP list */ 1190 aplist = sc->an_aplist; 1191 aplist.an_type = AN_RID_APLIST; 1192 aplist.an_len = sizeof(struct an_ltv_aplist); 1193 if (an_write_record(sc, (struct an_ltv_gen *)&aplist)) { 1194 printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname); 1195 splx(s); 1196 return; 1197 } 1198 1199 /* Set the configuration in the NIC */ 1200 genconf = sc->an_config; 1201 genconf.an_len = sizeof(struct an_ltv_genconfig); 1202 genconf.an_type = AN_RID_GENCONFIG; 1203 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 1204 printf("%s: failed to set configuration\n", 1205 sc->sc_dev.dv_xname); 1206 splx(s); 1207 return; 1208 } 1209 1210 /* Enable the MAC */ 1211 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1212 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname); 1213 splx(s); 1214 return; 1215 } 1216 1217 /* enable interrupts */ 1218 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1219 1220 splx(s); 1221 1222 ifp->if_flags |= IFF_RUNNING; 1223 ifp->if_flags &= ~IFF_OACTIVE; 1224 1225 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz); 1226 } 1227 1228 void 1229 an_start(ifp) 1230 struct ifnet *ifp; 1231 { 1232 struct an_softc *sc; 1233 struct mbuf *m0 = NULL; 1234 struct an_txframe_802_3 tx_frame_802_3; 1235 struct ether_header *eh; 1236 u_int16_t len; 1237 int id; 1238 int idx; 1239 unsigned char txcontrol; 1240 1241 sc = ifp->if_softc; 1242 1243 if (sc->an_gone) 1244 return; 1245 1246 if (ifp->if_flags & IFF_OACTIVE) 1247 return; 1248 1249 if (!sc->an_associated) 1250 return; 1251 1252 idx = sc->an_rdata.an_tx_prod; 1253 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3)); 1254 1255 while(sc->an_rdata.an_tx_ring[idx] == 0) { 1256 IF_DEQUEUE(&ifp->if_snd, m0); 1257 if (m0 == NULL) 1258 break; 1259 1260 id = sc->an_rdata.an_tx_fids[idx]; 1261 eh = mtod(m0, struct ether_header *); 1262 1263 bcopy((char *)&eh->ether_dhost, 1264 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN); 1265 bcopy((char *)&eh->ether_shost, 1266 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); 1267 1268 len = m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ 1269 tx_frame_802_3.an_tx_802_3_payload_len = htole16(len); 1270 1271 m_copydata(m0, sizeof(struct ether_header) - 2, len, 1272 (caddr_t)&sc->an_txbuf); 1273 1274 txcontrol=AN_TXCTL_8023; 1275 /* write the txcontrol only */ 1276 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol, 1277 sizeof(txcontrol)); 1278 1279 /* 802_3 header */ 1280 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3, 1281 sizeof(struct an_txframe_802_3)); 1282 1283 /* in mbuf header type is just before payload */ 1284 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, len); 1285 1286 /* 1287 * If there's a BPF listner, bounce a copy of 1288 * this frame to him. 1289 */ 1290 #if NBPFILTER > 0 1291 if (ifp->if_bpf) 1292 BPF_MTAP(ifp, m0); 1293 #endif 1294 1295 m_freem(m0); 1296 m0 = NULL; 1297 1298 sc->an_rdata.an_tx_ring[idx] = id; 1299 if (an_cmd(sc, AN_CMD_TX, id)) 1300 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1301 1302 AN_INC(idx, AN_TX_RING_CNT); 1303 } 1304 1305 if (m0 != NULL) 1306 ifp->if_flags |= IFF_OACTIVE; 1307 1308 sc->an_rdata.an_tx_prod = idx; 1309 1310 /* 1311 * Set a timeout in case the chip goes out to lunch. 1312 */ 1313 ifp->if_timer = 5; 1314 } 1315 1316 void 1317 an_stop(sc) 1318 struct an_softc *sc; 1319 { 1320 struct ifnet *ifp; 1321 int i; 1322 1323 if (sc->an_gone) 1324 return; 1325 1326 ifp = &sc->arpcom.ac_if; 1327 1328 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 1329 CSR_WRITE_2(sc, AN_INT_EN, 0); 1330 an_cmd(sc, AN_CMD_DISABLE, 0); 1331 1332 for (i = 0; i < AN_TX_RING_CNT; i++) 1333 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 1334 1335 UNTIMEOUT(an_stats_update, sc, sc->an_stat_ch); 1336 1337 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1338 } 1339 1340 void 1341 an_watchdog(ifp) 1342 struct ifnet *ifp; 1343 { 1344 struct an_softc *sc; 1345 1346 sc = ifp->if_softc; 1347 1348 if (sc->an_gone) 1349 return; 1350 1351 printf("%s: device timeout\n", sc->sc_dev.dv_xname); 1352 1353 an_reset(sc); 1354 an_init(sc); 1355 1356 ifp->if_oerrors++; 1357 } 1358 1359 void 1360 an_shutdown(self) 1361 void *self; 1362 { 1363 an_stop(self); 1364 } 1365 1366 #ifdef ANCACHE 1367 /* Aironet signal strength cache code. 1368 * store signal/noise/quality on per MAC src basis in 1369 * a small fixed cache. The cache wraps if > MAX slots 1370 * used. The cache may be zeroed out to start over. 1371 * Two simple filters exist to reduce computation: 1372 * 1. ip only (literally 0x800) which may be used 1373 * to ignore some packets. It defaults to ip only. 1374 * it could be used to focus on broadcast, non-IP 802.11 beacons. 1375 * 2. multicast/broadcast only. This may be used to 1376 * ignore unicast packets and only cache signal strength 1377 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 1378 * beacons and not unicast traffic. 1379 * 1380 * The cache stores (MAC src(index), IP src (major clue), signal, 1381 * quality, noise) 1382 * 1383 * No apologies for storing IP src here. It's easy and saves much 1384 * trouble elsewhere. The cache is assumed to be INET dependent, 1385 * although it need not be. 1386 * 1387 * Note: the Aironet only has a single byte of signal strength value 1388 * in the rx frame header, and it's not scaled to anything sensible. 1389 * This is kind of lame, but it's all we've got. 1390 */ 1391 1392 #ifdef documentation 1393 1394 int an_sigitems; /* number of cached entries */ 1395 struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 1396 int an_nextitem; /* index/# of entries */ 1397 1398 1399 #endif 1400 1401 /* control variables for cache filtering. Basic idea is 1402 * to reduce cost (e.g., to only Mobile-IP agent beacons 1403 * which are broadcast or multicast). Still you might 1404 * want to measure signal strength anth unicast ping packets 1405 * on a pt. to pt. ant. setup. 1406 */ 1407 /* set true if you want to limit cache items to broadcast/mcast 1408 * only packets (not unicast). Useful for mobile-ip beacons which 1409 * are broadcast/multicast at network layer. Default is all packets 1410 * so ping/unicast anll work say anth pt. to pt. antennae setup. 1411 */ 1412 #if 0 1413 static int an_cache_mcastonly = 0; 1414 SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 1415 &an_cache_mcastonly, 0, ""); 1416 1417 /* set true if you want to limit cache items to IP packets only 1418 */ 1419 static int an_cache_iponly = 1; 1420 SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 1421 &an_cache_iponly, 0, ""); 1422 #endif 1423 1424 /* 1425 * an_cache_store, per rx packet store signal 1426 * strength in MAC (src) indexed cache. 1427 */ 1428 void 1429 an_cache_store (sc, eh, m, rx_quality) 1430 struct an_softc *sc; 1431 struct ether_header *eh; 1432 struct mbuf *m; 1433 unsigned short rx_quality; 1434 { 1435 struct ip *ip = 0; 1436 int i; 1437 static int cache_slot = 0; /* use this cache entry */ 1438 static int wrapindex = 0; /* next "free" cache entry */ 1439 int saanp=0; 1440 1441 /* filters: 1442 * 1. ip only 1443 * 2. configurable filter to throw out unicast packets, 1444 * keep multicast only. 1445 */ 1446 1447 if ((ntohs(eh->ether_type) == 0x800)) 1448 saanp = 1; 1449 1450 /* filter for ip packets only 1451 */ 1452 if (sc->an_cache_iponly && !saanp) 1453 return; 1454 1455 /* filter for broadcast/multicast only */ 1456 if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) 1457 return; 1458 1459 #ifdef SIGDEBUG 1460 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 1461 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 1462 #endif 1463 1464 /* find the ip header. we want to store the ip_src address */ 1465 if (saanp) 1466 ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header)); 1467 1468 /* do a linear search for a matching MAC address 1469 * in the cache table 1470 * . MAC address is 6 bytes, 1471 * . var w_nextitem holds total number of entries already cached 1472 */ 1473 for(i = 0; i < sc->an_nextitem; i++) 1474 if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6)) 1475 /* Match!, 1476 * so we already have this entry, update the data 1477 */ 1478 break; 1479 1480 /* did we find a matching mac address? 1481 * if yes, then overwrite a previously existing cache entry 1482 */ 1483 if (i < sc->an_nextitem ) 1484 cache_slot = i; 1485 1486 /* else, have a new address entry,so 1487 * add this new entry, 1488 * if table full, then we need to replace LRU entry 1489 */ 1490 else { 1491 1492 /* check for space in cache table 1493 * note: an_nextitem also holds number of entries 1494 * added in the cache table 1495 */ 1496 if ( sc->an_nextitem < MAXANCACHE ) { 1497 cache_slot = sc->an_nextitem; 1498 sc->an_nextitem++; 1499 sc->an_sigitems = sc->an_nextitem; 1500 } 1501 /* no space found, so simply wrap anth wrap index 1502 * and "zap" the next entry 1503 */ 1504 else { 1505 if (wrapindex == MAXANCACHE) 1506 wrapindex = 0; 1507 cache_slot = wrapindex++; 1508 } 1509 } 1510 1511 /* invariant: cache_slot now points at some slot 1512 * in cache. 1513 */ 1514 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 1515 log(LOG_ERR, "an_cache_store, bad index: %d of " 1516 "[0..%d], gross cache error\n", 1517 cache_slot, MAXANCACHE); 1518 return; 1519 } 1520 1521 /* store items in cache 1522 * .ip source address 1523 * .mac src 1524 * .signal, etc. 1525 */ 1526 if (saanp) 1527 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 1528 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); 1529 1530 sc->an_sigcache[cache_slot].signal = rx_quality; 1531 } 1532 #endif 1533 1534 int 1535 an_media_change(ifp) 1536 struct ifnet *ifp; 1537 { 1538 struct an_softc *sc = ifp->if_softc; 1539 int otype = sc->an_config.an_opmode; 1540 int orate = sc->an_tx_rate; 1541 1542 if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) 1543 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; 1544 else 1545 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 1546 1547 switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) { 1548 case IFM_IEEE80211_DS1: 1549 sc->an_tx_rate = AN_RATE_1MBPS; 1550 break; 1551 case IFM_IEEE80211_DS2: 1552 sc->an_tx_rate = AN_RATE_2MBPS; 1553 break; 1554 case IFM_IEEE80211_DS5: 1555 sc->an_tx_rate = AN_RATE_5_5MBPS; 1556 break; 1557 case IFM_IEEE80211_DS11: 1558 sc->an_tx_rate = AN_RATE_11MBPS; 1559 break; 1560 case IFM_AUTO: 1561 sc->an_tx_rate = 0; 1562 break; 1563 } 1564 1565 if (otype != sc->an_config.an_opmode || 1566 orate != sc->an_tx_rate) 1567 an_init(sc); 1568 1569 return(0); 1570 } 1571 1572 void 1573 an_media_status(ifp, imr) 1574 struct ifnet *ifp; 1575 struct ifmediareq *imr; 1576 { 1577 struct an_ltv_status status; 1578 struct an_softc *sc = ifp->if_softc; 1579 1580 status.an_len = sizeof(status); 1581 status.an_type = AN_RID_STATUS; 1582 if (an_read_record(sc, (struct an_ltv_gen *)&status)) { 1583 /* If the status read fails, just lie. */ 1584 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 1585 imr->ifm_status = IFM_AVALID|IFM_ACTIVE; 1586 } 1587 1588 if (sc->an_tx_rate == 0) { 1589 imr->ifm_active = IFM_IEEE80211|IFM_AUTO; 1590 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 1591 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1592 switch (status.an_current_tx_rate) { 1593 case AN_RATE_1MBPS: 1594 imr->ifm_active |= IFM_IEEE80211_DS1; 1595 break; 1596 case AN_RATE_2MBPS: 1597 imr->ifm_active |= IFM_IEEE80211_DS2; 1598 break; 1599 case AN_RATE_5_5MBPS: 1600 imr->ifm_active |= IFM_IEEE80211_DS5; 1601 break; 1602 case AN_RATE_11MBPS: 1603 imr->ifm_active |= IFM_IEEE80211_DS11; 1604 break; 1605 } 1606 } else { 1607 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 1608 } 1609 1610 imr->ifm_status = IFM_AVALID; 1611 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 1612 imr->ifm_status |= IFM_ACTIVE; 1613 else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 1614 imr->ifm_status |= IFM_ACTIVE; 1615 } 1616