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