1 /* $OpenBSD: an.c,v 1.27 2003/06/25 22:28:14 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 128 #include <dev/ic/anvar.h> 129 #include <dev/ic/anreg.h> 130 131 #define TIMEOUT(handle,func,sc,time) timeout_add(&(handle), (time)) 132 #define UNTIMEOUT(func,sc,handle) timeout_del(&(handle)) 133 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf)) 134 #define BPFATTACH(if_bpf,if,dlt,sz) 135 136 struct cfdriver an_cd = { 137 NULL, "an", DV_IFNET 138 }; 139 140 void an_reset(struct an_softc *); 141 int an_ioctl(struct ifnet *, u_long, caddr_t); 142 int an_init_tx_ring(struct an_softc *); 143 void an_start(struct ifnet *); 144 void an_watchdog(struct ifnet *); 145 void an_rxeof(struct an_softc *); 146 void an_txeof(struct an_softc *, int); 147 148 void an_promisc(struct an_softc *, int); 149 int an_cmd(struct an_softc *, int, int); 150 int an_read_record(struct an_softc *, struct an_ltv_gen *); 151 int an_write_record(struct an_softc *, struct an_ltv_gen *); 152 int an_read_data(struct an_softc *, int, 153 int, caddr_t, int); 154 int an_write_data(struct an_softc *, int, 155 int, caddr_t, int); 156 int an_seek(struct an_softc *, int, int, int); 157 int an_alloc_nicmem(struct an_softc *, int, int *); 158 void an_stats_update(void *); 159 void an_setdef(struct an_softc *, struct an_req *); 160 #ifdef ANCACHE 161 void an_cache_store(struct an_softc *, struct ether_header *, 162 struct mbuf *, unsigned short); 163 #endif 164 int an_media_change(struct ifnet *); 165 void an_media_status(struct ifnet *, struct ifmediareq *); 166 167 static __inline void 168 an_swap16(u_int16_t *p, int cnt) 169 { 170 for (; cnt--; p++) 171 *p = swap16(*p); 172 } 173 174 int 175 an_attach(sc) 176 struct an_softc *sc; 177 { 178 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 179 180 sc->an_gone = 0; 181 sc->an_associated = 0; 182 183 /* disable interrupts */ 184 CSR_WRITE_2(sc, AN_INT_EN, 0); 185 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xffff); 186 187 /* Reset the NIC. */ 188 an_reset(sc); 189 190 /* Load factory config */ 191 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 192 printf("%s: failed to load config data\n", ifp->if_xname); 193 return(EIO); 194 } 195 196 /* Read the current configuration */ 197 sc->an_config.an_type = AN_RID_GENCONFIG; 198 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 199 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 200 printf("%s: read record failed\n", ifp->if_xname); 201 return(EIO); 202 } 203 204 /* Read the card capabilities */ 205 sc->an_caps.an_type = AN_RID_CAPABILITIES; 206 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 207 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 208 printf("%s: read record failed\n", ifp->if_xname); 209 return(EIO); 210 } 211 212 /* Read ssid list */ 213 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 214 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 215 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 216 printf("%s: read record failed\n", ifp->if_xname); 217 return(EIO); 218 } 219 220 /* Read AP list */ 221 sc->an_aplist.an_type = AN_RID_APLIST; 222 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 223 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 224 printf("%s: read record failed\n", ifp->if_xname); 225 return(EIO); 226 } 227 228 bcopy((char *)&sc->an_caps.an_oemaddr, 229 (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 230 231 printf(": address %6s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); 232 233 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 234 ifp->if_softc = sc; 235 ifp->if_mtu = ETHERMTU; 236 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 237 ifp->if_ioctl = an_ioctl; 238 ifp->if_start = an_start; 239 ifp->if_watchdog = an_watchdog; 240 ifp->if_baudrate = 10000000; 241 IFQ_SET_READY(&ifp->if_snd); 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->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->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->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->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->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 (!IFQ_IS_EMPTY(&ifp->if_snd)) 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 case AN_RID_ACTUALCFG: 660 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 661 an_swap16(<v->an_val[63], 8); /* an_nodename */ 662 break; 663 case AN_RID_SSIDLIST: 664 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 665 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 666 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 667 break; 668 case AN_RID_APLIST: 669 an_swap16(ltv->an_val, 12); 670 break; 671 case AN_RID_DRVNAME: 672 an_swap16(ltv->an_val, 8); 673 break; 674 case AN_RID_CAPABILITIES: 675 an_swap16(ltv->an_val, 2); /* an_oui */ 676 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 677 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 678 break; 679 case AN_RID_STATUS: 680 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 681 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 682 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 683 break; 684 case AN_RID_WEP_VOLATILE: 685 case AN_RID_WEP_PERMANENT: 686 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 687 an_swap16(<v->an_val[5], 6); 688 break; 689 case AN_RID_32BITS_CUM: 690 for (i = 0x60; i--; ) { 691 u_int16_t t = ltv->an_val[i * 2] ^ ltv->an_val[i * 2 + 1]; 692 ltv->an_val[i * 2] ^= t; 693 ltv->an_val[i * 2 + 1] ^= t; 694 } 695 break; 696 } 697 #endif 698 return(0); 699 } 700 701 /* 702 * Same as read, except we inject data instead of reading it. 703 */ 704 int 705 an_write_record(sc, ltv) 706 struct an_softc *sc; 707 struct an_ltv_gen *ltv; 708 { 709 u_int16_t *ptr; 710 int i; 711 712 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 713 return(EIO); 714 715 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 716 return(EIO); 717 718 #if BYTE_ORDER == BIG_ENDIAN 719 switch (ltv->an_type) { 720 case AN_RID_GENCONFIG: 721 case AN_RID_ACTUALCFG: 722 an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ 723 an_swap16(<v->an_val[63], 8); /* an_nodename */ 724 break; 725 case AN_RID_SSIDLIST: 726 an_swap16(<v->an_val[1], 16); /* an_ssid1 */ 727 an_swap16(<v->an_val[18], 16); /* an_ssid2 */ 728 an_swap16(<v->an_val[35], 16); /* an_ssid3 */ 729 break; 730 case AN_RID_APLIST: 731 an_swap16(ltv->an_val, 12); 732 break; 733 case AN_RID_DRVNAME: 734 an_swap16(ltv->an_val, 8); 735 break; 736 case AN_RID_CAPABILITIES: 737 an_swap16(ltv->an_val, 2); /* an_oui */ 738 an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ 739 an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ 740 break; 741 case AN_RID_STATUS: 742 an_swap16(<v->an_val[0], 3); /* an_macaddr */ 743 an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ 744 an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ 745 break; 746 case AN_RID_WEP_VOLATILE: 747 case AN_RID_WEP_PERMANENT: 748 an_swap16(<v->an_val[1], 3); /* an_mac_addr */ 749 an_swap16(<v->an_val[5], 6); 750 break; 751 } 752 #endif 753 754 CSR_WRITE_2(sc, AN_DATA1, ltv->an_len); 755 756 ptr = ltv->an_val; 757 for (i = 0; i < (ltv->an_len - 1) >> 1; i++) 758 CSR_WRITE_2(sc, AN_DATA1, ptr[i]); 759 760 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 761 return(EIO); 762 763 return(0); 764 } 765 766 int 767 an_seek(sc, id, off, chan) 768 struct an_softc *sc; 769 int id, off, chan; 770 { 771 int i; 772 int selreg, offreg; 773 774 switch (chan) { 775 case AN_BAP0: 776 selreg = AN_SEL0; 777 offreg = AN_OFF0; 778 break; 779 case AN_BAP1: 780 selreg = AN_SEL1; 781 offreg = AN_OFF1; 782 break; 783 default: 784 printf("%s: invalid data path: %x\n", 785 sc->sc_dev.dv_xname, chan); 786 return (EIO); 787 } 788 789 CSR_WRITE_2(sc, selreg, id); 790 CSR_WRITE_2(sc, offreg, off); 791 792 for (i = AN_TIMEOUT; i--; DELAY(10)) { 793 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 794 break; 795 } 796 797 if (i <= 0) 798 return(ETIMEDOUT); 799 800 return (0); 801 } 802 803 int 804 an_read_data(sc, id, off, buf, len) 805 struct an_softc *sc; 806 int id, off; 807 caddr_t buf; 808 int len; 809 { 810 if (off != -1 && an_seek(sc, id, off, AN_BAP1)) 811 return(EIO); 812 813 bus_space_read_raw_multi_2(sc->an_btag, sc->an_bhandle, 814 AN_DATA1, buf, len & ~1); 815 if (len & 1) 816 ((u_int8_t *)buf)[len - 1] = CSR_READ_1(sc, AN_DATA1); 817 818 return (0); 819 } 820 821 int 822 an_write_data(sc, id, off, buf, len) 823 struct an_softc *sc; 824 int id, off; 825 caddr_t buf; 826 int len; 827 { 828 if (off != -1 && an_seek(sc, id, off, AN_BAP0)) 829 return(EIO); 830 831 bus_space_write_raw_multi_2(sc->an_btag, sc->an_bhandle, 832 AN_DATA0, buf, len & ~1); 833 if (len & 1) 834 CSR_WRITE_1(sc, AN_DATA0, ((u_int8_t *)buf)[len - 1]); 835 836 return (0); 837 } 838 839 /* 840 * Allocate a region of memory inside the NIC and zero 841 * it out. 842 */ 843 int 844 an_alloc_nicmem(sc, len, id) 845 struct an_softc *sc; 846 int len; 847 int *id; 848 { 849 int i; 850 851 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 852 printf("%s: failed to allocate %d bytes on NIC\n", 853 sc->sc_dev.dv_xname, len); 854 return(ENOMEM); 855 } 856 857 for (i = AN_TIMEOUT; i--; DELAY(10)) { 858 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 859 break; 860 } 861 862 if (i <= 0) 863 return(ETIMEDOUT); 864 865 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 866 *id = CSR_READ_2(sc, AN_ALLOC_FID); 867 868 if (an_seek(sc, *id, 0, AN_BAP0)) 869 return(EIO); 870 871 bus_space_set_multi_2(sc->an_btag, sc->an_bhandle, 872 AN_DATA0, 0, len / 2); 873 CSR_WRITE_1(sc, AN_DATA0, 0); 874 875 return(0); 876 } 877 878 void 879 an_setdef(sc, areq) 880 struct an_softc *sc; 881 struct an_req *areq; 882 { 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 889 ifp = &sc->sc_arpcom.ac_if; 890 891 switch (areq->an_type) { 892 case AN_RID_GENCONFIG: 893 cfg = (struct an_ltv_genconfig *)areq; 894 bcopy((char *)&cfg->an_macaddr, 895 (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 896 bcopy((char *)&cfg->an_macaddr, LLADDR(ifp->if_sadl), 897 ETHER_ADDR_LEN); 898 899 bcopy((char *)cfg, (char *)&sc->an_config, 900 sizeof(struct an_ltv_genconfig)); 901 break; 902 case AN_RID_SSIDLIST: 903 ssid = (struct an_ltv_ssidlist *)areq; 904 bcopy((char *)ssid, (char *)&sc->an_ssidlist, 905 sizeof(struct an_ltv_ssidlist)); 906 break; 907 case AN_RID_APLIST: 908 ap = (struct an_ltv_aplist *)areq; 909 bcopy((char *)ap, (char *)&sc->an_aplist, 910 sizeof(struct an_ltv_aplist)); 911 break; 912 case AN_RID_TX_SPEED: 913 sp = (struct an_ltv_gen *)areq; 914 sc->an_tx_rate = sp->an_val[0]; 915 break; 916 case AN_RID_WEP_VOLATILE: 917 /* Disable the MAC */ 918 an_cmd(sc, AN_CMD_DISABLE, 0); 919 920 /* Just write the key, we dont' want to save it */ 921 an_write_record(sc, (struct an_ltv_gen *)areq); 922 923 /* Turn the MAC back on */ 924 an_cmd(sc, AN_CMD_ENABLE, 0); 925 926 break; 927 case AN_RID_WEP_PERMANENT: 928 /* Disable the MAC */ 929 an_cmd(sc, AN_CMD_DISABLE, 0); 930 931 /* Just write the key, the card will save it in this mode */ 932 an_write_record(sc, (struct an_ltv_gen *)areq); 933 934 /* Turn the MAC back on */ 935 an_cmd(sc, AN_CMD_ENABLE, 0); 936 937 break; 938 default: 939 printf("%s: unknown RID: %x\n", 940 sc->sc_dev.dv_xname, areq->an_type); 941 return; 942 } 943 944 /* Reinitialize the card. */ 945 if (ifp->if_flags & IFF_UP) 946 an_init(sc); 947 } 948 949 /* 950 * We can't change the NIC configuration while the MAC is enabled, 951 * so in order to turn on RX monitor mode, we have to turn the MAC 952 * off first. 953 */ 954 void 955 an_promisc(sc, promisc) 956 struct an_softc *sc; 957 int promisc; 958 { 959 struct an_ltv_genconfig genconf; 960 961 /* Disable the MAC. */ 962 an_cmd(sc, AN_CMD_DISABLE, 0); 963 964 /* Set RX mode. */ 965 if (promisc && 966 !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) ) { 967 sc->an_rxmode = sc->an_config.an_rxmode; 968 sc->an_config.an_rxmode |= 969 AN_RXMODE_LAN_MONITOR_CURBSS; 970 } else { 971 sc->an_config.an_rxmode = sc->an_rxmode; 972 } 973 974 /* Transfer the configuration to the NIC */ 975 genconf = sc->an_config; 976 genconf.an_len = sizeof(struct an_ltv_genconfig); 977 genconf.an_type = AN_RID_GENCONFIG; 978 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 979 printf("%s: failed to set configuration\n", 980 sc->sc_dev.dv_xname); 981 return; 982 } 983 /* Turn the MAC back on. */ 984 an_cmd(sc, AN_CMD_ENABLE, 0); 985 } 986 987 int 988 an_ioctl(ifp, command, data) 989 struct ifnet *ifp; 990 u_long command; 991 caddr_t data; 992 { 993 int s, error = 0; 994 struct an_softc *sc; 995 struct an_req areq; 996 struct ifreq *ifr; 997 struct proc *p = curproc; 998 struct ifaddr *ifa = (struct ifaddr *)data; 999 1000 s = splimp(); 1001 1002 sc = ifp->if_softc; 1003 ifr = (struct ifreq *)data; 1004 1005 if (sc->an_gone) { 1006 splx(s); 1007 return(ENODEV); 1008 } 1009 1010 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) { 1011 splx(s); 1012 return error; 1013 } 1014 1015 switch(command) { 1016 case SIOCSIFADDR: 1017 ifp->if_flags |= IFF_UP; 1018 switch (ifa->ifa_addr->sa_family) { 1019 #ifdef INET 1020 case AF_INET: 1021 an_init(sc); 1022 arp_ifinit(&sc->sc_arpcom, ifa); 1023 break; 1024 #endif 1025 default: 1026 an_init(sc); 1027 break; 1028 } 1029 break; 1030 case SIOCSIFFLAGS: 1031 if (ifp->if_flags & IFF_UP) { 1032 if (ifp->if_flags & IFF_RUNNING && 1033 ifp->if_flags & IFF_PROMISC && 1034 !(sc->an_if_flags & IFF_PROMISC)) { 1035 an_promisc(sc, 1); 1036 } else if (ifp->if_flags & IFF_RUNNING && 1037 !(ifp->if_flags & IFF_PROMISC) && 1038 sc->an_if_flags & IFF_PROMISC) { 1039 an_promisc(sc, 0); 1040 an_reset(sc); 1041 } 1042 an_init(sc); 1043 } else { 1044 if (ifp->if_flags & IFF_RUNNING) 1045 an_stop(sc); 1046 } 1047 sc->an_if_flags = ifp->if_flags; 1048 error = 0; 1049 break; 1050 case SIOCSIFMEDIA: 1051 case SIOCGIFMEDIA: 1052 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command); 1053 break; 1054 case SIOCADDMULTI: 1055 case SIOCDELMULTI: 1056 /* The Aironet has no multicast filter. */ 1057 error = 0; 1058 break; 1059 case SIOCGAIRONET: 1060 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1061 if (error) 1062 break; 1063 #ifdef ANCACHE 1064 if (areq.an_type == AN_RID_ZERO_CACHE) { 1065 error = suser(p->p_ucred, &p->p_acflag); 1066 if (error) 1067 break; 1068 sc->an_sigitems = sc->an_nextitem = 0; 1069 break; 1070 } else if (areq.an_type == AN_RID_READ_CACHE) { 1071 char *pt = (char *)&areq.an_val; 1072 bcopy((char *)&sc->an_sigitems, (char *)pt, 1073 sizeof(int)); 1074 pt += sizeof(int); 1075 areq.an_len = sizeof(int) / 2; 1076 bcopy((char *)&sc->an_sigcache, (char *)pt, 1077 sizeof(struct an_sigcache) * sc->an_sigitems); 1078 areq.an_len += ((sizeof(struct an_sigcache) * 1079 sc->an_sigitems) / 2) + 1; 1080 } else 1081 #endif 1082 if (an_read_record(sc, (struct an_ltv_gen *)&areq)) { 1083 error = EINVAL; 1084 break; 1085 } 1086 error = copyout(&areq, ifr->ifr_data, sizeof(areq)); 1087 break; 1088 case SIOCSAIRONET: 1089 error = suser(p->p_ucred, &p->p_acflag); 1090 if (error) 1091 break; 1092 error = copyin(ifr->ifr_data, &areq, sizeof(areq)); 1093 if (error) 1094 break; 1095 an_setdef(sc, &areq); 1096 break; 1097 default: 1098 error = EINVAL; 1099 break; 1100 } 1101 1102 splx(s); 1103 1104 return(error); 1105 } 1106 1107 int 1108 an_init_tx_ring(sc) 1109 struct an_softc *sc; 1110 { 1111 int i; 1112 int id; 1113 1114 if (sc->an_gone) 1115 return (0); 1116 1117 for (i = 0; i < AN_TX_RING_CNT; i++) { 1118 if (an_alloc_nicmem(sc, 1518 + 0x44, &id)) 1119 return(ENOMEM); 1120 sc->an_rdata.an_tx_fids[i] = id; 1121 sc->an_rdata.an_tx_ring[i] = 0; 1122 } 1123 1124 sc->an_rdata.an_tx_prod = 0; 1125 sc->an_rdata.an_tx_cons = 0; 1126 1127 return(0); 1128 } 1129 1130 void 1131 an_init(sc) 1132 struct an_softc *sc; 1133 { 1134 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 1135 struct an_ltv_ssidlist ssid; 1136 struct an_ltv_aplist aplist; 1137 struct an_ltv_genconfig genconf; 1138 int s; 1139 1140 if (sc->an_gone) 1141 return; 1142 1143 s = splimp(); 1144 1145 if (ifp->if_flags & IFF_RUNNING) 1146 an_stop(sc); 1147 1148 sc->an_associated = 0; 1149 1150 /* Allocate the TX buffers */ 1151 if (an_init_tx_ring(sc)) { 1152 printf("%s: tx buffer allocation failed\n", 1153 sc->sc_dev.dv_xname); 1154 splx(s); 1155 return; 1156 } 1157 1158 /* Set our MAC address. */ 1159 bcopy((char *)&sc->sc_arpcom.ac_enaddr, 1160 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN); 1161 1162 if (ifp->if_flags & IFF_BROADCAST) 1163 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1164 else 1165 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1166 1167 if (ifp->if_flags & IFF_MULTICAST) 1168 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1169 1170 /* Initialize promisc mode. */ 1171 if (ifp->if_flags & IFF_PROMISC) 1172 sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS; 1173 1174 sc->an_rxmode = sc->an_config.an_rxmode; 1175 1176 /* Set the ssid list */ 1177 ssid = sc->an_ssidlist; 1178 ssid.an_type = AN_RID_SSIDLIST; 1179 ssid.an_len = sizeof(struct an_ltv_ssidlist); 1180 if (an_write_record(sc, (struct an_ltv_gen *)&ssid)) { 1181 printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname); 1182 splx(s); 1183 return; 1184 } 1185 1186 /* Set the AP list */ 1187 aplist = sc->an_aplist; 1188 aplist.an_type = AN_RID_APLIST; 1189 aplist.an_len = sizeof(struct an_ltv_aplist); 1190 if (an_write_record(sc, (struct an_ltv_gen *)&aplist)) { 1191 printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname); 1192 splx(s); 1193 return; 1194 } 1195 1196 /* Set the configuration in the NIC */ 1197 genconf = sc->an_config; 1198 genconf.an_len = sizeof(struct an_ltv_genconfig); 1199 genconf.an_type = AN_RID_GENCONFIG; 1200 if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { 1201 printf("%s: failed to set configuration\n", 1202 sc->sc_dev.dv_xname); 1203 splx(s); 1204 return; 1205 } 1206 1207 /* Enable the MAC */ 1208 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1209 printf("%s: failed to enable MAC\n", sc->sc_dev.dv_xname); 1210 splx(s); 1211 return; 1212 } 1213 1214 /* enable interrupts */ 1215 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1216 1217 splx(s); 1218 1219 ifp->if_flags |= IFF_RUNNING; 1220 ifp->if_flags &= ~IFF_OACTIVE; 1221 1222 TIMEOUT(sc->an_stat_ch, an_stats_update, sc, hz); 1223 } 1224 1225 void 1226 an_start(ifp) 1227 struct ifnet *ifp; 1228 { 1229 struct an_softc *sc; 1230 struct mbuf *m0 = NULL; 1231 struct an_txframe_802_3 tx_frame_802_3; 1232 struct ether_header *eh; 1233 u_int16_t len; 1234 int id; 1235 int idx; 1236 unsigned char txcontrol; 1237 int pkts = 0; 1238 1239 sc = ifp->if_softc; 1240 1241 if (sc->an_gone) 1242 return; 1243 1244 if (ifp->if_flags & IFF_OACTIVE) 1245 return; 1246 1247 if (!sc->an_associated) 1248 return; 1249 1250 idx = sc->an_rdata.an_tx_prod; 1251 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3)); 1252 1253 while(sc->an_rdata.an_tx_ring[idx] == 0) { 1254 IFQ_DEQUEUE(&ifp->if_snd, m0); 1255 if (m0 == NULL) 1256 break; 1257 1258 pkts++; 1259 id = sc->an_rdata.an_tx_fids[idx]; 1260 eh = mtod(m0, struct ether_header *); 1261 1262 bcopy((char *)&eh->ether_dhost, 1263 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN); 1264 bcopy((char *)&eh->ether_shost, 1265 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); 1266 1267 len = m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ 1268 tx_frame_802_3.an_tx_802_3_payload_len = htole16(len); 1269 1270 m_copydata(m0, sizeof(struct ether_header) - 2, len, 1271 (caddr_t)&sc->an_txbuf); 1272 1273 txcontrol=AN_TXCTL_8023; 1274 /* write the txcontrol only */ 1275 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol, 1276 sizeof(txcontrol)); 1277 1278 /* 802_3 header */ 1279 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3, 1280 sizeof(struct an_txframe_802_3)); 1281 1282 /* in mbuf header type is just before payload */ 1283 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, len); 1284 1285 /* 1286 * If there's a BPF listner, bounce a copy of 1287 * this frame to him. 1288 */ 1289 #if NBPFILTER > 0 1290 if (ifp->if_bpf) 1291 BPF_MTAP(ifp, m0); 1292 #endif 1293 1294 m_freem(m0); 1295 m0 = NULL; 1296 1297 sc->an_rdata.an_tx_ring[idx] = id; 1298 if (an_cmd(sc, AN_CMD_TX, id)) 1299 printf("%s: xmit failed\n", sc->sc_dev.dv_xname); 1300 1301 AN_INC(idx, AN_TX_RING_CNT); 1302 } 1303 if (pkts == 0) 1304 return; 1305 1306 if (m0 != NULL) 1307 ifp->if_flags |= IFF_OACTIVE; 1308 1309 sc->an_rdata.an_tx_prod = idx; 1310 1311 /* 1312 * Set a timeout in case the chip goes out to lunch. 1313 */ 1314 ifp->if_timer = 5; 1315 } 1316 1317 void 1318 an_stop(sc) 1319 struct an_softc *sc; 1320 { 1321 struct ifnet *ifp; 1322 int i; 1323 1324 if (sc->an_gone) 1325 return; 1326 1327 ifp = &sc->sc_arpcom.ac_if; 1328 1329 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 1330 CSR_WRITE_2(sc, AN_INT_EN, 0); 1331 an_cmd(sc, AN_CMD_DISABLE, 0); 1332 1333 for (i = 0; i < AN_TX_RING_CNT; i++) 1334 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 1335 1336 UNTIMEOUT(an_stats_update, sc, sc->an_stat_ch); 1337 1338 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1339 } 1340 1341 void 1342 an_watchdog(ifp) 1343 struct ifnet *ifp; 1344 { 1345 struct an_softc *sc; 1346 1347 sc = ifp->if_softc; 1348 1349 if (sc->an_gone) 1350 return; 1351 1352 printf("%s: device timeout\n", sc->sc_dev.dv_xname); 1353 1354 an_reset(sc); 1355 an_init(sc); 1356 1357 ifp->if_oerrors++; 1358 } 1359 1360 void 1361 an_shutdown(self) 1362 void *self; 1363 { 1364 an_stop(self); 1365 } 1366 1367 #ifdef ANCACHE 1368 /* Aironet signal strength cache code. 1369 * store signal/noise/quality on per MAC src basis in 1370 * a small fixed cache. The cache wraps if > MAX slots 1371 * used. The cache may be zeroed out to start over. 1372 * Two simple filters exist to reduce computation: 1373 * 1. ip only (literally 0x800) which may be used 1374 * to ignore some packets. It defaults to ip only. 1375 * it could be used to focus on broadcast, non-IP 802.11 beacons. 1376 * 2. multicast/broadcast only. This may be used to 1377 * ignore unicast packets and only cache signal strength 1378 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 1379 * beacons and not unicast traffic. 1380 * 1381 * The cache stores (MAC src(index), IP src (major clue), signal, 1382 * quality, noise) 1383 * 1384 * No apologies for storing IP src here. It's easy and saves much 1385 * trouble elsewhere. The cache is assumed to be INET dependent, 1386 * although it need not be. 1387 * 1388 * Note: the Aironet only has a single byte of signal strength value 1389 * in the rx frame header, and it's not scaled to anything sensible. 1390 * This is kind of lame, but it's all we've got. 1391 */ 1392 1393 #ifdef documentation 1394 1395 int an_sigitems; /* number of cached entries */ 1396 struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 1397 int an_nextitem; /* index/# of entries */ 1398 1399 1400 #endif 1401 1402 /* control variables for cache filtering. Basic idea is 1403 * to reduce cost (e.g., to only Mobile-IP agent beacons 1404 * which are broadcast or multicast). Still you might 1405 * want to measure signal strength anth unicast ping packets 1406 * on a pt. to pt. ant. setup. 1407 */ 1408 /* set true if you want to limit cache items to broadcast/mcast 1409 * only packets (not unicast). Useful for mobile-ip beacons which 1410 * are broadcast/multicast at network layer. Default is all packets 1411 * so ping/unicast anll work say anth pt. to pt. antennae setup. 1412 */ 1413 #if 0 1414 static int an_cache_mcastonly = 0; 1415 SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 1416 &an_cache_mcastonly, 0, ""); 1417 1418 /* set true if you want to limit cache items to IP packets only 1419 */ 1420 static int an_cache_iponly = 1; 1421 SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 1422 &an_cache_iponly, 0, ""); 1423 #endif 1424 1425 /* 1426 * an_cache_store, per rx packet store signal 1427 * strength in MAC (src) indexed cache. 1428 */ 1429 void 1430 an_cache_store (sc, eh, m, rx_quality) 1431 struct an_softc *sc; 1432 struct ether_header *eh; 1433 struct mbuf *m; 1434 unsigned short rx_quality; 1435 { 1436 struct ip *ip = 0; 1437 int i; 1438 static int cache_slot = 0; /* use this cache entry */ 1439 static int wrapindex = 0; /* next "free" cache entry */ 1440 int saanp=0; 1441 1442 /* filters: 1443 * 1. ip only 1444 * 2. configurable filter to throw out unicast packets, 1445 * keep multicast only. 1446 */ 1447 1448 if ((ntohs(eh->ether_type) == 0x800)) 1449 saanp = 1; 1450 1451 /* filter for ip packets only 1452 */ 1453 if (sc->an_cache_iponly && !saanp) 1454 return; 1455 1456 /* filter for broadcast/multicast only */ 1457 if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) 1458 return; 1459 1460 #ifdef SIGDEBUG 1461 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 1462 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 1463 #endif 1464 1465 /* find the ip header. we want to store the ip_src address */ 1466 if (saanp) 1467 ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header)); 1468 1469 /* do a linear search for a matching MAC address 1470 * in the cache table 1471 * . MAC address is 6 bytes, 1472 * . var w_nextitem holds total number of entries already cached 1473 */ 1474 for(i = 0; i < sc->an_nextitem; i++) 1475 if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6)) 1476 /* Match!, 1477 * so we already have this entry, update the data 1478 */ 1479 break; 1480 1481 /* did we find a matching mac address? 1482 * if yes, then overwrite a previously existing cache entry 1483 */ 1484 if (i < sc->an_nextitem ) 1485 cache_slot = i; 1486 1487 /* else, have a new address entry,so 1488 * add this new entry, 1489 * if table full, then we need to replace LRU entry 1490 */ 1491 else { 1492 1493 /* check for space in cache table 1494 * note: an_nextitem also holds number of entries 1495 * added in the cache table 1496 */ 1497 if ( sc->an_nextitem < MAXANCACHE ) { 1498 cache_slot = sc->an_nextitem; 1499 sc->an_nextitem++; 1500 sc->an_sigitems = sc->an_nextitem; 1501 } 1502 /* no space found, so simply wrap anth wrap index 1503 * and "zap" the next entry 1504 */ 1505 else { 1506 if (wrapindex == MAXANCACHE) 1507 wrapindex = 0; 1508 cache_slot = wrapindex++; 1509 } 1510 } 1511 1512 /* invariant: cache_slot now points at some slot 1513 * in cache. 1514 */ 1515 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 1516 log(LOG_ERR, "an_cache_store, bad index: %d of " 1517 "[0..%d], gross cache error\n", 1518 cache_slot, MAXANCACHE); 1519 return; 1520 } 1521 1522 /* store items in cache 1523 * .ip source address 1524 * .mac src 1525 * .signal, etc. 1526 */ 1527 if (saanp) 1528 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 1529 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); 1530 1531 sc->an_sigcache[cache_slot].signal = rx_quality; 1532 } 1533 #endif 1534 1535 int 1536 an_media_change(ifp) 1537 struct ifnet *ifp; 1538 { 1539 struct an_softc *sc = ifp->if_softc; 1540 int otype = sc->an_config.an_opmode; 1541 int orate = sc->an_tx_rate; 1542 1543 if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) 1544 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; 1545 else 1546 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 1547 1548 switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) { 1549 case IFM_IEEE80211_DS1: 1550 sc->an_tx_rate = AN_RATE_1MBPS; 1551 break; 1552 case IFM_IEEE80211_DS2: 1553 sc->an_tx_rate = AN_RATE_2MBPS; 1554 break; 1555 case IFM_IEEE80211_DS5: 1556 sc->an_tx_rate = AN_RATE_5_5MBPS; 1557 break; 1558 case IFM_IEEE80211_DS11: 1559 sc->an_tx_rate = AN_RATE_11MBPS; 1560 break; 1561 case IFM_AUTO: 1562 sc->an_tx_rate = 0; 1563 break; 1564 } 1565 1566 if (otype != sc->an_config.an_opmode || 1567 orate != sc->an_tx_rate) 1568 an_init(sc); 1569 1570 return(0); 1571 } 1572 1573 void 1574 an_media_status(ifp, imr) 1575 struct ifnet *ifp; 1576 struct ifmediareq *imr; 1577 { 1578 struct an_ltv_status status; 1579 struct an_softc *sc = ifp->if_softc; 1580 1581 status.an_len = sizeof(status); 1582 status.an_type = AN_RID_STATUS; 1583 if (an_read_record(sc, (struct an_ltv_gen *)&status)) { 1584 /* If the status read fails, just lie. */ 1585 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 1586 imr->ifm_status = IFM_AVALID|IFM_ACTIVE; 1587 } 1588 1589 if (sc->an_tx_rate == 0) { 1590 imr->ifm_active = IFM_IEEE80211|IFM_AUTO; 1591 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 1592 imr->ifm_active |= IFM_IEEE80211_ADHOC; 1593 switch (status.an_current_tx_rate) { 1594 case AN_RATE_1MBPS: 1595 imr->ifm_active |= IFM_IEEE80211_DS1; 1596 break; 1597 case AN_RATE_2MBPS: 1598 imr->ifm_active |= IFM_IEEE80211_DS2; 1599 break; 1600 case AN_RATE_5_5MBPS: 1601 imr->ifm_active |= IFM_IEEE80211_DS5; 1602 break; 1603 case AN_RATE_11MBPS: 1604 imr->ifm_active |= IFM_IEEE80211_DS11; 1605 break; 1606 } 1607 } else { 1608 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 1609 } 1610 1611 imr->ifm_status = IFM_AVALID; 1612 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 1613 imr->ifm_status |= IFM_ACTIVE; 1614 else if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 1615 imr->ifm_status |= IFM_ACTIVE; 1616 } 1617