if_an.c revision 108259
1/* 2 * Copyright (c) 1997, 1998, 1999 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/dev/an/if_an.c 108259 2002-12-24 14:46:01Z rwatson $ 33 */ 34 35/* 36 * Aironet 4500/4800 802.11 PCMCIA/ISA/PCI driver for FreeBSD. 37 * 38 * Written by Bill Paul <wpaul@ctr.columbia.edu> 39 * Electrical Engineering Department 40 * Columbia University, New York City 41 */ 42 43/* 44 * The Aironet 4500/4800 series cards come in PCMCIA, ISA and PCI form. 45 * This driver supports all three device types (PCI devices are supported 46 * through an extra PCI shim: /sys/dev/an/if_an_pci.c). ISA devices can be 47 * supported either using hard-coded IO port/IRQ settings or via Plug 48 * and Play. The 4500 series devices support 1Mbps and 2Mbps data rates. 49 * The 4800 devices support 1, 2, 5.5 and 11Mbps rates. 50 * 51 * Like the WaveLAN/IEEE cards, the Aironet NICs are all essentially 52 * PCMCIA devices. The ISA and PCI cards are a combination of a PCMCIA 53 * device and a PCMCIA to ISA or PCMCIA to PCI adapter card. There are 54 * a couple of important differences though: 55 * 56 * - Lucent ISA card looks to the host like a PCMCIA controller with 57 * a PCMCIA WaveLAN card inserted. This means that even desktop 58 * machines need to be configured with PCMCIA support in order to 59 * use WaveLAN/IEEE ISA cards. The Aironet cards on the other hand 60 * actually look like normal ISA and PCI devices to the host, so 61 * no PCMCIA controller support is needed 62 * 63 * The latter point results in a small gotcha. The Aironet PCMCIA 64 * cards can be configured for one of two operating modes depending 65 * on how the Vpp1 and Vpp2 programming voltages are set when the 66 * card is activated. In order to put the card in proper PCMCIA 67 * operation (where the CIS table is visible and the interface is 68 * programmed for PCMCIA operation), both Vpp1 and Vpp2 have to be 69 * set to 5 volts. FreeBSD by default doesn't set the Vpp voltages, 70 * which leaves the card in ISA/PCI mode, which prevents it from 71 * being activated as an PCMCIA device. 72 * 73 * Note that some PCMCIA controller software packages for Windows NT 74 * fail to set the voltages as well. 75 * 76 * The Aironet devices can operate in both station mode and access point 77 * mode. Typically, when programmed for station mode, the card can be set 78 * to automatically perform encapsulation/decapsulation of Ethernet II 79 * and 802.3 frames within 802.11 frames so that the host doesn't have 80 * to do it itself. This driver doesn't program the card that way: the 81 * driver handles all of the encapsulation/decapsulation itself. 82 */ 83 84#include "opt_inet.h" 85 86#ifdef INET 87#define ANCACHE /* enable signal strength cache */ 88#endif 89 90#include <sys/param.h> 91#include <sys/systm.h> 92#include <sys/sockio.h> 93#include <sys/mbuf.h> 94#include <sys/proc.h> 95#include <sys/kernel.h> 96#include <sys/socket.h> 97#ifdef ANCACHE 98#include <sys/syslog.h> 99#include <sys/sysctl.h> 100#endif 101 102#include <sys/module.h> 103#include <sys/sysctl.h> 104#include <sys/bus.h> 105#include <machine/bus.h> 106#include <sys/rman.h> 107#include <sys/lock.h> 108#include <sys/mutex.h> 109#include <machine/resource.h> 110 111#include <net/if.h> 112#include <net/if_arp.h> 113#include <net/ethernet.h> 114#include <net/if_dl.h> 115#include <net/if_types.h> 116#include <net/if_ieee80211.h> 117#include <net/if_media.h> 118 119#ifdef INET 120#include <netinet/in.h> 121#include <netinet/in_systm.h> 122#include <netinet/in_var.h> 123#include <netinet/ip.h> 124#endif 125 126#include <net/bpf.h> 127 128#include <machine/md_var.h> 129 130#include <dev/an/if_aironet_ieee.h> 131#include <dev/an/if_anreg.h> 132 133#if !defined(lint) 134static const char rcsid[] = 135 "$FreeBSD: head/sys/dev/an/if_an.c 108259 2002-12-24 14:46:01Z rwatson $"; 136#endif 137 138/* These are global because we need them in sys/pci/if_an_p.c. */ 139static void an_reset (struct an_softc *); 140static int an_ioctl (struct ifnet *, u_long, caddr_t); 141static void an_init (void *); 142static int an_init_tx_ring (struct an_softc *); 143static void an_start (struct ifnet *); 144static void an_watchdog (struct ifnet *); 145static void an_rxeof (struct an_softc *); 146static void an_txeof (struct an_softc *, int); 147 148static void an_promisc (struct an_softc *, int); 149static int an_cmd (struct an_softc *, int, int); 150static int an_read_record (struct an_softc *, struct an_ltv_gen *); 151static int an_write_record (struct an_softc *, struct an_ltv_gen *); 152static int an_read_data (struct an_softc *, int, int, caddr_t, int); 153static int an_write_data (struct an_softc *, int, int, caddr_t, int); 154static int an_seek (struct an_softc *, int, int, int); 155static int an_alloc_nicmem (struct an_softc *, int, int *); 156static void an_stats_update (void *); 157static void an_setdef (struct an_softc *, struct an_req *); 158#ifdef ANCACHE 159static void an_cache_store (struct an_softc *, struct ether_header *, 160 struct mbuf *, unsigned short); 161#endif 162 163/* function definitions for use with the Cisco's Linux configuration 164 utilities 165*/ 166 167static int readrids(struct ifnet*, struct aironet_ioctl*); 168static int writerids(struct ifnet*, struct aironet_ioctl*); 169static int flashcard(struct ifnet*, struct aironet_ioctl*); 170 171static int cmdreset(struct ifnet *); 172static int setflashmode(struct ifnet *); 173static int flashgchar(struct ifnet *,int,int); 174static int flashpchar(struct ifnet *,int,int); 175static int flashputbuf(struct ifnet *); 176static int flashrestart(struct ifnet *); 177static int WaitBusy(struct ifnet *, int); 178static int unstickbusy(struct ifnet *); 179 180static void an_dump_record (struct an_softc *,struct an_ltv_gen *, 181 char *); 182 183static int an_media_change (struct ifnet *); 184static void an_media_status (struct ifnet *, struct ifmediareq *); 185 186static int an_dump = 0; 187 188static char an_conf[256]; 189 190/* sysctl vars */ 191SYSCTL_NODE(_machdep, OID_AUTO, an, CTLFLAG_RD, 0, "dump RID"); 192 193/* XXX violate ethernet/netgraph callback hooks */ 194extern void (*ng_ether_attach_p)(struct ifnet *ifp); 195extern void (*ng_ether_detach_p)(struct ifnet *ifp); 196 197static int 198sysctl_an_dump(SYSCTL_HANDLER_ARGS) 199{ 200 int error, r, last; 201 char *s = an_conf; 202 203 last = an_dump; 204 bzero(an_conf, sizeof(an_conf)); 205 206 switch (an_dump) { 207 case 0: 208 strcat(an_conf, "off"); 209 break; 210 case 1: 211 strcat(an_conf, "type"); 212 break; 213 case 2: 214 strcat(an_conf, "dump"); 215 break; 216 default: 217 snprintf(an_conf, 5, "%x", an_dump); 218 break; 219 } 220 221 error = sysctl_handle_string(oidp, an_conf, sizeof(an_conf), req); 222 223 if (strncmp(an_conf,"off", 4) == 0) { 224 an_dump = 0; 225 } 226 if (strncmp(an_conf,"dump", 4) == 0) { 227 an_dump = 1; 228 } 229 if (strncmp(an_conf,"type", 4) == 0) { 230 an_dump = 2; 231 } 232 if (*s == 'f') { 233 r = 0; 234 for (;;s++) { 235 if ((*s >= '0') && (*s <= '9')) { 236 r = r * 16 + (*s - '0'); 237 } else if ((*s >= 'a') && (*s <= 'f')) { 238 r = r * 16 + (*s - 'a' + 10); 239 } else { 240 break; 241 } 242 } 243 an_dump = r; 244 } 245 if (an_dump != last) 246 printf("Sysctl changed for Aironet driver\n"); 247 248 return error; 249} 250 251SYSCTL_PROC(_machdep, OID_AUTO, an_dump, CTLTYPE_STRING | CTLFLAG_RW, 252 0, sizeof(an_conf), sysctl_an_dump, "A", ""); 253 254/* 255 * We probe for an Aironet 4500/4800 card by attempting to 256 * read the default SSID list. On reset, the first entry in 257 * the SSID list will contain the name "tsunami." If we don't 258 * find this, then there's no card present. 259 */ 260int 261an_probe(dev) 262 device_t dev; 263{ 264 struct an_softc *sc = device_get_softc(dev); 265 struct an_ltv_ssidlist ssid; 266 int error; 267 268 bzero((char *)&ssid, sizeof(ssid)); 269 270 error = an_alloc_port(dev, 0, AN_IOSIZ); 271 if (error != 0) 272 return (0); 273 274 /* can't do autoprobing */ 275 if (rman_get_start(sc->port_res) == -1) 276 return(0); 277 278 /* 279 * We need to fake up a softc structure long enough 280 * to be able to issue commands and call some of the 281 * other routines. 282 */ 283 sc->an_bhandle = rman_get_bushandle(sc->port_res); 284 sc->an_btag = rman_get_bustag(sc->port_res); 285 sc->an_unit = device_get_unit(dev); 286 287 ssid.an_len = sizeof(ssid); 288 ssid.an_type = AN_RID_SSIDLIST; 289 290 /* Make sure interrupts are disabled. */ 291 CSR_WRITE_2(sc, AN_INT_EN, 0); 292 CSR_WRITE_2(sc, AN_EVENT_ACK, 0xFFFF); 293 294 an_reset(sc); 295 296 if (an_cmd(sc, AN_CMD_READCFG, 0)) 297 return(0); 298 299 if (an_read_record(sc, (struct an_ltv_gen *)&ssid)) 300 return(0); 301 302 /* See if the ssid matches what we expect ... but doesn't have to */ 303 if (strcmp(ssid.an_ssid1, AN_DEF_SSID)) 304 return(0); 305 306 return(AN_IOSIZ); 307} 308 309/* 310 * Allocate a port resource with the given resource id. 311 */ 312int 313an_alloc_port(dev, rid, size) 314 device_t dev; 315 int rid; 316 int size; 317{ 318 struct an_softc *sc = device_get_softc(dev); 319 struct resource *res; 320 321 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 322 0ul, ~0ul, size, RF_ACTIVE); 323 if (res) { 324 sc->port_rid = rid; 325 sc->port_res = res; 326 return (0); 327 } else { 328 return (ENOENT); 329 } 330} 331 332/* 333 * Allocate an irq resource with the given resource id. 334 */ 335int 336an_alloc_irq(dev, rid, flags) 337 device_t dev; 338 int rid; 339 int flags; 340{ 341 struct an_softc *sc = device_get_softc(dev); 342 struct resource *res; 343 344 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 345 0ul, ~0ul, 1, (RF_ACTIVE | flags)); 346 if (res) { 347 sc->irq_rid = rid; 348 sc->irq_res = res; 349 return (0); 350 } else { 351 return (ENOENT); 352 } 353} 354 355/* 356 * Release all resources 357 */ 358void 359an_release_resources(dev) 360 device_t dev; 361{ 362 struct an_softc *sc = device_get_softc(dev); 363 364 if (sc->port_res) { 365 bus_release_resource(dev, SYS_RES_IOPORT, 366 sc->port_rid, sc->port_res); 367 sc->port_res = 0; 368 } 369 if (sc->irq_res) { 370 bus_release_resource(dev, SYS_RES_IRQ, 371 sc->irq_rid, sc->irq_res); 372 sc->irq_res = 0; 373 } 374} 375 376int 377an_attach(sc, unit, flags) 378 struct an_softc *sc; 379 int unit; 380 int flags; 381{ 382 struct ifnet *ifp = &sc->arpcom.ac_if; 383 384 mtx_init(&sc->an_mtx, device_get_nameunit(sc->an_dev), MTX_NETWORK_LOCK, 385 MTX_DEF | MTX_RECURSE); 386 AN_LOCK(sc); 387 388 sc->an_gone = 0; 389 sc->an_associated = 0; 390 sc->an_monitor = 0; 391 sc->an_was_monitor = 0; 392 393 /* Reset the NIC. */ 394 an_reset(sc); 395 396 /* Load factory config */ 397 if (an_cmd(sc, AN_CMD_READCFG, 0)) { 398 printf("an%d: failed to load config data\n", sc->an_unit); 399 AN_UNLOCK(sc); 400 mtx_destroy(&sc->an_mtx); 401 return(EIO); 402 } 403 404 /* Read the current configuration */ 405 sc->an_config.an_type = AN_RID_GENCONFIG; 406 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 407 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 408 printf("an%d: read record failed\n", sc->an_unit); 409 AN_UNLOCK(sc); 410 mtx_destroy(&sc->an_mtx); 411 return(EIO); 412 } 413 414 /* Read the card capabilities */ 415 sc->an_caps.an_type = AN_RID_CAPABILITIES; 416 sc->an_caps.an_len = sizeof(struct an_ltv_caps); 417 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_caps)) { 418 printf("an%d: read record failed\n", sc->an_unit); 419 AN_UNLOCK(sc); 420 mtx_destroy(&sc->an_mtx); 421 return(EIO); 422 } 423 424 /* Read ssid list */ 425 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 426 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 427 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 428 printf("an%d: read record failed\n", sc->an_unit); 429 AN_UNLOCK(sc); 430 mtx_destroy(&sc->an_mtx); 431 return(EIO); 432 } 433 434 /* Read AP list */ 435 sc->an_aplist.an_type = AN_RID_APLIST; 436 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 437 if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 438 printf("an%d: read record failed\n", sc->an_unit); 439 AN_UNLOCK(sc); 440 mtx_destroy(&sc->an_mtx); 441 return(EIO); 442 } 443 444 bcopy((char *)&sc->an_caps.an_oemaddr, 445 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 446 447 printf("an%d: Ethernet address: %6D\n", sc->an_unit, 448 sc->arpcom.ac_enaddr, ":"); 449 450 ifp->if_softc = sc; 451 ifp->if_unit = sc->an_unit = unit; 452 ifp->if_name = "an"; 453 ifp->if_mtu = ETHERMTU; 454 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 455 ifp->if_ioctl = an_ioctl; 456 ifp->if_output = ether_output; 457 ifp->if_start = an_start; 458 ifp->if_watchdog = an_watchdog; 459 ifp->if_init = an_init; 460 ifp->if_baudrate = 10000000; 461 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 462 463 bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); 464 bcopy(AN_DEFAULT_NODENAME, sc->an_config.an_nodename, 465 sizeof(AN_DEFAULT_NODENAME) - 1); 466 467 bzero(sc->an_ssidlist.an_ssid1, sizeof(sc->an_ssidlist.an_ssid1)); 468 bcopy(AN_DEFAULT_NETNAME, sc->an_ssidlist.an_ssid1, 469 sizeof(AN_DEFAULT_NETNAME) - 1); 470 sc->an_ssidlist.an_ssid1_len = strlen(AN_DEFAULT_NETNAME); 471 472 sc->an_config.an_opmode = 473 AN_OPMODE_INFRASTRUCTURE_STATION; 474 475 sc->an_tx_rate = 0; 476 bzero((char *)&sc->an_stats, sizeof(sc->an_stats)); 477 478 ifmedia_init(&sc->an_ifmedia, 0, an_media_change, an_media_status); 479#define ADD(m, c) ifmedia_add(&sc->an_ifmedia, (m), (c), NULL) 480 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 481 IFM_IEEE80211_ADHOC, 0), 0); 482 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0); 483 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 484 IFM_IEEE80211_ADHOC, 0), 0); 485 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0); 486 if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) { 487 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 488 IFM_IEEE80211_ADHOC, 0), 0); 489 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0); 490 } 491 if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) { 492 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 493 IFM_IEEE80211_ADHOC, 0), 0); 494 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0); 495 } 496 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 497 IFM_IEEE80211_ADHOC, 0), 0); 498 ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0); 499#undef ADD 500 ifmedia_set(&sc->an_ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 501 0, 0)); 502 503 /* 504 * Call MI attach routine. 505 */ 506 ether_ifattach(ifp, sc->arpcom.ac_enaddr); 507 callout_handle_init(&sc->an_stat_ch); 508 AN_UNLOCK(sc); 509 510 return(0); 511} 512 513static void 514an_rxeof(sc) 515 struct an_softc *sc; 516{ 517 struct ifnet *ifp; 518 struct ether_header *eh; 519 struct ieee80211_frame *ih; 520 struct an_rxframe rx_frame; 521 struct an_rxframe_802_3 rx_frame_802_3; 522 struct mbuf *m; 523 int len, id, error = 0; 524 int ieee80211_header_len; 525 u_char *bpf_buf; 526 u_short fc1; 527 528 ifp = &sc->arpcom.ac_if; 529 530 id = CSR_READ_2(sc, AN_RX_FID); 531 532 if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) { 533 /* read raw 802.11 packet */ 534 bpf_buf = sc->buf_802_11; 535 536 /* read header */ 537 if (an_read_data(sc, id, 0x0, (caddr_t)&rx_frame, 538 sizeof(rx_frame))) { 539 ifp->if_ierrors++; 540 return; 541 } 542 543 /* 544 * skip beacon by default since this increases the 545 * system load a lot 546 */ 547 548 if (!(sc->an_monitor & AN_MONITOR_INCLUDE_BEACON) && 549 (rx_frame.an_frame_ctl & IEEE80211_FC0_SUBTYPE_BEACON)) { 550 return; 551 } 552 553 if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) { 554 len = rx_frame.an_rx_payload_len 555 + sizeof(rx_frame); 556 /* Check for insane frame length */ 557 if (len > sizeof(sc->buf_802_11)) { 558 printf("an%d: oversized packet received (%d, %d)\n", 559 sc->an_unit, len, MCLBYTES); 560 ifp->if_ierrors++; 561 return; 562 } 563 564 bcopy((char *)&rx_frame, 565 bpf_buf, sizeof(rx_frame)); 566 567 error = an_read_data(sc, id, sizeof(rx_frame), 568 (caddr_t)bpf_buf+sizeof(rx_frame), 569 rx_frame.an_rx_payload_len); 570 } else { 571 fc1=rx_frame.an_frame_ctl >> 8; 572 ieee80211_header_len = sizeof(struct ieee80211_frame); 573 if ((fc1 & IEEE80211_FC1_DIR_TODS) && 574 (fc1 & IEEE80211_FC1_DIR_FROMDS)) { 575 ieee80211_header_len += ETHER_ADDR_LEN; 576 } 577 578 len = rx_frame.an_rx_payload_len 579 + ieee80211_header_len; 580 /* Check for insane frame length */ 581 if (len > sizeof(sc->buf_802_11)) { 582 printf("an%d: oversized packet received (%d, %d)\n", 583 sc->an_unit, len, MCLBYTES); 584 ifp->if_ierrors++; 585 return; 586 } 587 588 ih = (struct ieee80211_frame *)bpf_buf; 589 590 bcopy((char *)&rx_frame.an_frame_ctl, 591 (char *)ih, ieee80211_header_len); 592 593 error = an_read_data(sc, id, sizeof(rx_frame) + 594 rx_frame.an_gaplen, 595 (caddr_t)ih +ieee80211_header_len, 596 rx_frame.an_rx_payload_len); 597 } 598 /* dump raw 802.11 packet to bpf and skip ip stack */ 599 BPF_TAP(ifp, bpf_buf, len); 600 } else { 601 MGETHDR(m, M_DONTWAIT, MT_DATA); 602 if (m == NULL) { 603 ifp->if_ierrors++; 604 return; 605 } 606 MCLGET(m, M_DONTWAIT); 607 if (!(m->m_flags & M_EXT)) { 608 m_freem(m); 609 ifp->if_ierrors++; 610 return; 611 } 612 m->m_pkthdr.rcvif = ifp; 613 /* Read Ethernet encapsulated packet */ 614 615#ifdef ANCACHE 616 /* Read NIC frame header */ 617 if (an_read_data(sc, id, 0, (caddr_t) & rx_frame, sizeof(rx_frame))) { 618 ifp->if_ierrors++; 619 return; 620 } 621#endif 622 /* Read in the 802_3 frame header */ 623 if (an_read_data(sc, id, 0x34, (caddr_t) & rx_frame_802_3, 624 sizeof(rx_frame_802_3))) { 625 ifp->if_ierrors++; 626 return; 627 } 628 if (rx_frame_802_3.an_rx_802_3_status != 0) { 629 ifp->if_ierrors++; 630 return; 631 } 632 /* Check for insane frame length */ 633 if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) { 634 ifp->if_ierrors++; 635 return; 636 } 637 m->m_pkthdr.len = m->m_len = 638 rx_frame_802_3.an_rx_802_3_payload_len + 12; 639 640 eh = mtod(m, struct ether_header *); 641 642 bcopy((char *)&rx_frame_802_3.an_rx_dst_addr, 643 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 644 bcopy((char *)&rx_frame_802_3.an_rx_src_addr, 645 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 646 647 /* in mbuf header type is just before payload */ 648 error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type), 649 rx_frame_802_3.an_rx_802_3_payload_len); 650 651 if (error) { 652 m_freem(m); 653 ifp->if_ierrors++; 654 return; 655 } 656 ifp->if_ipackets++; 657 658 /* Receive packet. */ 659#ifdef ANCACHE 660 an_cache_store(sc, eh, m, rx_frame.an_rx_signal_strength); 661#endif 662 (*ifp->if_input)(ifp, m); 663 } 664} 665 666static void 667an_txeof(sc, status) 668 struct an_softc *sc; 669 int status; 670{ 671 struct ifnet *ifp; 672 int id, i; 673 674 ifp = &sc->arpcom.ac_if; 675 676 ifp->if_timer = 0; 677 ifp->if_flags &= ~IFF_OACTIVE; 678 679 id = CSR_READ_2(sc, AN_TX_CMP_FID); 680 681 if (status & AN_EV_TX_EXC) { 682 ifp->if_oerrors++; 683 } else 684 ifp->if_opackets++; 685 686 for (i = 0; i < AN_TX_RING_CNT; i++) { 687 if (id == sc->an_rdata.an_tx_ring[i]) { 688 sc->an_rdata.an_tx_ring[i] = 0; 689 break; 690 } 691 } 692 693 AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT); 694 695 return; 696} 697 698/* 699 * We abuse the stats updater to check the current NIC status. This 700 * is important because we don't want to allow transmissions until 701 * the NIC has synchronized to the current cell (either as the master 702 * in an ad-hoc group, or as a station connected to an access point). 703 */ 704static void 705an_stats_update(xsc) 706 void *xsc; 707{ 708 struct an_softc *sc; 709 struct ifnet *ifp; 710 711 sc = xsc; 712 AN_LOCK(sc); 713 ifp = &sc->arpcom.ac_if; 714 715 sc->an_status.an_type = AN_RID_STATUS; 716 sc->an_status.an_len = sizeof(struct an_ltv_status); 717 an_read_record(sc, (struct an_ltv_gen *)&sc->an_status); 718 719 if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC) 720 sc->an_associated = 1; 721 else 722 sc->an_associated = 0; 723 724 /* Don't do this while we're transmitting */ 725 if (ifp->if_flags & IFF_OACTIVE) { 726 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 727 AN_UNLOCK(sc); 728 return; 729 } 730 731 sc->an_stats.an_len = sizeof(struct an_ltv_stats); 732 sc->an_stats.an_type = AN_RID_32BITS_CUM; 733 an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len); 734 735 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 736 AN_UNLOCK(sc); 737 738 return; 739} 740 741void 742an_intr(xsc) 743 void *xsc; 744{ 745 struct an_softc *sc; 746 struct ifnet *ifp; 747 u_int16_t status; 748 749 sc = (struct an_softc*)xsc; 750 751 AN_LOCK(sc); 752 753 if (sc->an_gone) { 754 AN_UNLOCK(sc); 755 return; 756 } 757 758 ifp = &sc->arpcom.ac_if; 759 760 /* Disable interrupts. */ 761 CSR_WRITE_2(sc, AN_INT_EN, 0); 762 763 status = CSR_READ_2(sc, AN_EVENT_STAT); 764 CSR_WRITE_2(sc, AN_EVENT_ACK, ~AN_INTRS); 765 766 if (status & AN_EV_AWAKE) { 767 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_AWAKE); 768 } 769 770 if (status & AN_EV_LINKSTAT) { 771 if (CSR_READ_2(sc, AN_LINKSTAT) == AN_LINKSTAT_ASSOCIATED) 772 sc->an_associated = 1; 773 else 774 sc->an_associated = 0; 775 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_LINKSTAT); 776 } 777 778 if (status & AN_EV_RX) { 779 an_rxeof(sc); 780 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_RX); 781 } 782 783 if (status & AN_EV_TX) { 784 an_txeof(sc, status); 785 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX); 786 } 787 788 if (status & AN_EV_TX_EXC) { 789 an_txeof(sc, status); 790 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_TX_EXC); 791 } 792 793 if (status & AN_EV_ALLOC) 794 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 795 796 /* Re-enable interrupts. */ 797 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 798 799 if ((ifp->if_flags & IFF_UP) && (ifp->if_snd.ifq_head != NULL)) 800 an_start(ifp); 801 802 AN_UNLOCK(sc); 803 804 return; 805} 806 807static int 808an_cmd(sc, cmd, val) 809 struct an_softc *sc; 810 int cmd; 811 int val; 812{ 813 int i, s = 0; 814 815 CSR_WRITE_2(sc, AN_PARAM0, val); 816 CSR_WRITE_2(sc, AN_PARAM1, 0); 817 CSR_WRITE_2(sc, AN_PARAM2, 0); 818 CSR_WRITE_2(sc, AN_COMMAND, cmd); 819 820 for (i = 0; i < AN_TIMEOUT; i++) { 821 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_CMD) 822 break; 823 else { 824 if (CSR_READ_2(sc, AN_COMMAND) == cmd) 825 CSR_WRITE_2(sc, AN_COMMAND, cmd); 826 } 827 } 828 829 for (i = 0; i < AN_TIMEOUT; i++) { 830 CSR_READ_2(sc, AN_RESP0); 831 CSR_READ_2(sc, AN_RESP1); 832 CSR_READ_2(sc, AN_RESP2); 833 s = CSR_READ_2(sc, AN_STATUS); 834 if ((s & AN_STAT_CMD_CODE) == (cmd & AN_STAT_CMD_CODE)) 835 break; 836 } 837 838 /* Ack the command */ 839 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CMD); 840 841 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) 842 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 843 844 if (i == AN_TIMEOUT) 845 return(ETIMEDOUT); 846 847 return(0); 848} 849 850/* 851 * This reset sequence may look a little strange, but this is the 852 * most reliable method I've found to really kick the NIC in the 853 * head and force it to reboot correctly. 854 */ 855static void 856an_reset(sc) 857 struct an_softc *sc; 858{ 859 if (sc->an_gone) 860 return; 861 862 an_cmd(sc, AN_CMD_ENABLE, 0); 863 an_cmd(sc, AN_CMD_FW_RESTART, 0); 864 an_cmd(sc, AN_CMD_NOOP2, 0); 865 866 if (an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0) == ETIMEDOUT) 867 printf("an%d: reset failed\n", sc->an_unit); 868 869 an_cmd(sc, AN_CMD_DISABLE, 0); 870 871 return; 872} 873 874/* 875 * Read an LTV record from the NIC. 876 */ 877static int 878an_read_record(sc, ltv) 879 struct an_softc *sc; 880 struct an_ltv_gen *ltv; 881{ 882 u_int16_t *ptr; 883 u_int8_t *ptr2; 884 int i, len; 885 886 if (ltv->an_len < 4 || ltv->an_type == 0) 887 return(EINVAL); 888 889 /* Tell the NIC to enter record read mode. */ 890 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) { 891 printf("an%d: RID access failed\n", sc->an_unit); 892 return(EIO); 893 } 894 895 /* Seek to the record. */ 896 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) { 897 printf("an%d: seek to record failed\n", sc->an_unit); 898 return(EIO); 899 } 900 901 /* 902 * Read the length and record type and make sure they 903 * match what we expect (this verifies that we have enough 904 * room to hold all of the returned data). 905 * Length includes type but not length. 906 */ 907 len = CSR_READ_2(sc, AN_DATA1); 908 if (len > (ltv->an_len - 2)) { 909 printf("an%d: record length mismatch -- expected %d, " 910 "got %d for Rid %x\n", sc->an_unit, 911 ltv->an_len - 2, len, ltv->an_type); 912 len = ltv->an_len - 2; 913 } else { 914 ltv->an_len = len + 2; 915 } 916 917 /* Now read the data. */ 918 len -= 2; /* skip the type */ 919 ptr = <v->an_val; 920 for (i = len; i > 1; i -= 2) 921 *ptr++ = CSR_READ_2(sc, AN_DATA1); 922 if (i) { 923 ptr2 = (u_int8_t *)ptr; 924 *ptr2 = CSR_READ_1(sc, AN_DATA1); 925 } 926 if (an_dump) 927 an_dump_record(sc, ltv, "Read"); 928 929 return(0); 930} 931 932/* 933 * Same as read, except we inject data instead of reading it. 934 */ 935static int 936an_write_record(sc, ltv) 937 struct an_softc *sc; 938 struct an_ltv_gen *ltv; 939{ 940 u_int16_t *ptr; 941 u_int8_t *ptr2; 942 int i, len; 943 944 if (an_dump) 945 an_dump_record(sc, ltv, "Write"); 946 947 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) 948 return(EIO); 949 950 if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) 951 return(EIO); 952 953 /* 954 * Length includes type but not length. 955 */ 956 len = ltv->an_len - 2; 957 CSR_WRITE_2(sc, AN_DATA1, len); 958 959 len -= 2; /* skip the type */ 960 ptr = <v->an_val; 961 for (i = len; i > 1; i -= 2) 962 CSR_WRITE_2(sc, AN_DATA1, *ptr++); 963 if (i) { 964 ptr2 = (u_int8_t *)ptr; 965 CSR_WRITE_1(sc, AN_DATA0, *ptr2); 966 } 967 968 if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type)) 969 return(EIO); 970 971 return(0); 972} 973 974static void 975an_dump_record(sc, ltv, string) 976 struct an_softc *sc; 977 struct an_ltv_gen *ltv; 978 char *string; 979{ 980 u_int8_t *ptr2; 981 int len; 982 int i; 983 int count = 0; 984 char buf[17], temp; 985 986 len = ltv->an_len - 4; 987 printf("an%d: RID %4x, Length %4d, Mode %s\n", 988 sc->an_unit, ltv->an_type, ltv->an_len - 4, string); 989 990 if (an_dump == 1 || (an_dump == ltv->an_type)) { 991 printf("an%d:\t", sc->an_unit); 992 bzero(buf,sizeof(buf)); 993 994 ptr2 = (u_int8_t *)<v->an_val; 995 for (i = len; i > 0; i--) { 996 printf("%02x ", *ptr2); 997 998 temp = *ptr2++; 999 if (temp >= ' ' && temp <= '~') 1000 buf[count] = temp; 1001 else if (temp >= 'A' && temp <= 'Z') 1002 buf[count] = temp; 1003 else 1004 buf[count] = '.'; 1005 if (++count == 16) { 1006 count = 0; 1007 printf("%s\n",buf); 1008 printf("an%d:\t", sc->an_unit); 1009 bzero(buf,sizeof(buf)); 1010 } 1011 } 1012 for (; count != 16; count++) { 1013 printf(" "); 1014 } 1015 printf(" %s\n",buf); 1016 } 1017} 1018 1019static int 1020an_seek(sc, id, off, chan) 1021 struct an_softc *sc; 1022 int id, off, chan; 1023{ 1024 int i; 1025 int selreg, offreg; 1026 1027 switch (chan) { 1028 case AN_BAP0: 1029 selreg = AN_SEL0; 1030 offreg = AN_OFF0; 1031 break; 1032 case AN_BAP1: 1033 selreg = AN_SEL1; 1034 offreg = AN_OFF1; 1035 break; 1036 default: 1037 printf("an%d: invalid data path: %x\n", sc->an_unit, chan); 1038 return(EIO); 1039 } 1040 1041 CSR_WRITE_2(sc, selreg, id); 1042 CSR_WRITE_2(sc, offreg, off); 1043 1044 for (i = 0; i < AN_TIMEOUT; i++) { 1045 if (!(CSR_READ_2(sc, offreg) & (AN_OFF_BUSY|AN_OFF_ERR))) 1046 break; 1047 } 1048 1049 if (i == AN_TIMEOUT) 1050 return(ETIMEDOUT); 1051 1052 return(0); 1053} 1054 1055static int 1056an_read_data(sc, id, off, buf, len) 1057 struct an_softc *sc; 1058 int id, off; 1059 caddr_t buf; 1060 int len; 1061{ 1062 int i; 1063 u_int16_t *ptr; 1064 u_int8_t *ptr2; 1065 1066 if (off != -1) { 1067 if (an_seek(sc, id, off, AN_BAP1)) 1068 return(EIO); 1069 } 1070 1071 ptr = (u_int16_t *)buf; 1072 for (i = len; i > 1; i -= 2) 1073 *ptr++ = CSR_READ_2(sc, AN_DATA1); 1074 if (i) { 1075 ptr2 = (u_int8_t *)ptr; 1076 *ptr2 = CSR_READ_1(sc, AN_DATA1); 1077 } 1078 1079 return(0); 1080} 1081 1082static int 1083an_write_data(sc, id, off, buf, len) 1084 struct an_softc *sc; 1085 int id, off; 1086 caddr_t buf; 1087 int len; 1088{ 1089 int i; 1090 u_int16_t *ptr; 1091 u_int8_t *ptr2; 1092 1093 if (off != -1) { 1094 if (an_seek(sc, id, off, AN_BAP0)) 1095 return(EIO); 1096 } 1097 1098 ptr = (u_int16_t *)buf; 1099 for (i = len; i > 1; i -= 2) 1100 CSR_WRITE_2(sc, AN_DATA0, *ptr++); 1101 if (i) { 1102 ptr2 = (u_int8_t *)ptr; 1103 CSR_WRITE_1(sc, AN_DATA0, *ptr2); 1104 } 1105 1106 return(0); 1107} 1108 1109/* 1110 * Allocate a region of memory inside the NIC and zero 1111 * it out. 1112 */ 1113static int 1114an_alloc_nicmem(sc, len, id) 1115 struct an_softc *sc; 1116 int len; 1117 int *id; 1118{ 1119 int i; 1120 1121 if (an_cmd(sc, AN_CMD_ALLOC_MEM, len)) { 1122 printf("an%d: failed to allocate %d bytes on NIC\n", 1123 sc->an_unit, len); 1124 return(ENOMEM); 1125 } 1126 1127 for (i = 0; i < AN_TIMEOUT; i++) { 1128 if (CSR_READ_2(sc, AN_EVENT_STAT) & AN_EV_ALLOC) 1129 break; 1130 } 1131 1132 if (i == AN_TIMEOUT) 1133 return(ETIMEDOUT); 1134 1135 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_ALLOC); 1136 *id = CSR_READ_2(sc, AN_ALLOC_FID); 1137 1138 if (an_seek(sc, *id, 0, AN_BAP0)) 1139 return(EIO); 1140 1141 for (i = 0; i < len / 2; i++) 1142 CSR_WRITE_2(sc, AN_DATA0, 0); 1143 1144 return(0); 1145} 1146 1147static void 1148an_setdef(sc, areq) 1149 struct an_softc *sc; 1150 struct an_req *areq; 1151{ 1152 struct sockaddr_dl *sdl; 1153 struct ifaddr *ifa; 1154 struct ifnet *ifp; 1155 struct an_ltv_genconfig *cfg; 1156 struct an_ltv_ssidlist *ssid; 1157 struct an_ltv_aplist *ap; 1158 struct an_ltv_gen *sp; 1159 1160 ifp = &sc->arpcom.ac_if; 1161 1162 switch (areq->an_type) { 1163 case AN_RID_GENCONFIG: 1164 cfg = (struct an_ltv_genconfig *)areq; 1165 1166 ifa = ifaddr_byindex(ifp->if_index); 1167 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1168 bcopy((char *)&cfg->an_macaddr, (char *)&sc->arpcom.ac_enaddr, 1169 ETHER_ADDR_LEN); 1170 bcopy((char *)&cfg->an_macaddr, LLADDR(sdl), ETHER_ADDR_LEN); 1171 1172 bcopy((char *)cfg, (char *)&sc->an_config, 1173 sizeof(struct an_ltv_genconfig)); 1174 break; 1175 case AN_RID_SSIDLIST: 1176 ssid = (struct an_ltv_ssidlist *)areq; 1177 bcopy((char *)ssid, (char *)&sc->an_ssidlist, 1178 sizeof(struct an_ltv_ssidlist)); 1179 break; 1180 case AN_RID_APLIST: 1181 ap = (struct an_ltv_aplist *)areq; 1182 bcopy((char *)ap, (char *)&sc->an_aplist, 1183 sizeof(struct an_ltv_aplist)); 1184 break; 1185 case AN_RID_TX_SPEED: 1186 sp = (struct an_ltv_gen *)areq; 1187 sc->an_tx_rate = sp->an_val; 1188 break; 1189 case AN_RID_WEP_TEMP: 1190 case AN_RID_WEP_PERM: 1191 case AN_RID_LEAPUSERNAME: 1192 case AN_RID_LEAPPASSWORD: 1193 /* Disable the MAC. */ 1194 an_cmd(sc, AN_CMD_DISABLE, 0); 1195 1196 /* Write the key */ 1197 an_write_record(sc, (struct an_ltv_gen *)areq); 1198 1199 /* Turn the MAC back on. */ 1200 an_cmd(sc, AN_CMD_ENABLE, 0); 1201 1202 break; 1203 case AN_RID_MONITOR_MODE: 1204 cfg = (struct an_ltv_genconfig *)areq; 1205 bpfdetach(ifp); 1206 if (ng_ether_detach_p != NULL) 1207 (*ng_ether_detach_p) (ifp); 1208 sc->an_monitor = cfg->an_len; 1209 1210 if (sc->an_monitor & AN_MONITOR) { 1211 if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) { 1212 bpfattach(ifp, DLT_AIRONET_HEADER, 1213 sizeof(struct ether_header)); 1214 } else { 1215 bpfattach(ifp, DLT_IEEE802_11, 1216 sizeof(struct ether_header)); 1217 } 1218 } else { 1219 bpfattach(ifp, DLT_EN10MB, 1220 sizeof(struct ether_header)); 1221 if (ng_ether_attach_p != NULL) 1222 (*ng_ether_attach_p) (ifp); 1223 } 1224 break; 1225 default: 1226 printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type); 1227 return; 1228 break; 1229 } 1230 1231 1232 /* Reinitialize the card. */ 1233 if (ifp->if_flags) 1234 an_init(sc); 1235 1236 return; 1237} 1238 1239/* 1240 * Derived from Linux driver to enable promiscious mode. 1241 */ 1242 1243static void 1244an_promisc(sc, promisc) 1245 struct an_softc *sc; 1246 int promisc; 1247{ 1248 if (sc->an_was_monitor) 1249 an_reset(sc); 1250 if (sc->an_monitor || sc->an_was_monitor) 1251 an_init(sc); 1252 1253 sc->an_was_monitor = sc->an_monitor; 1254 an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0); 1255 1256 return; 1257} 1258 1259static int 1260an_ioctl(ifp, command, data) 1261 struct ifnet *ifp; 1262 u_long command; 1263 caddr_t data; 1264{ 1265 int error = 0; 1266 int len; 1267 int i; 1268 struct an_softc *sc; 1269 struct ifreq *ifr; 1270 struct thread *td = curthread; 1271 struct ieee80211req *ireq; 1272 u_int8_t tmpstr[IEEE80211_NWID_LEN*2]; 1273 u_int8_t *tmpptr; 1274 struct an_ltv_genconfig *config; 1275 struct an_ltv_key *key; 1276 struct an_ltv_status *status; 1277 struct an_ltv_ssidlist *ssids; 1278 int mode; 1279 struct aironet_ioctl l_ioctl; 1280 1281 sc = ifp->if_softc; 1282 AN_LOCK(sc); 1283 ifr = (struct ifreq *)data; 1284 ireq = (struct ieee80211req *)data; 1285 1286 config = (struct an_ltv_genconfig *)&sc->areq; 1287 key = (struct an_ltv_key *)&sc->areq; 1288 status = (struct an_ltv_status *)&sc->areq; 1289 ssids = (struct an_ltv_ssidlist *)&sc->areq; 1290 1291 if (sc->an_gone) { 1292 error = ENODEV; 1293 goto out; 1294 } 1295 1296 switch (command) { 1297 case SIOCSIFFLAGS: 1298 if (ifp->if_flags & IFF_UP) { 1299 if (ifp->if_flags & IFF_RUNNING && 1300 ifp->if_flags & IFF_PROMISC && 1301 !(sc->an_if_flags & IFF_PROMISC)) { 1302 an_promisc(sc, 1); 1303 } else if (ifp->if_flags & IFF_RUNNING && 1304 !(ifp->if_flags & IFF_PROMISC) && 1305 sc->an_if_flags & IFF_PROMISC) { 1306 an_promisc(sc, 0); 1307 } else 1308 an_init(sc); 1309 } else { 1310 if (ifp->if_flags & IFF_RUNNING) 1311 an_stop(sc); 1312 } 1313 sc->an_if_flags = ifp->if_flags; 1314 error = 0; 1315 break; 1316 case SIOCSIFMEDIA: 1317 case SIOCGIFMEDIA: 1318 error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command); 1319 break; 1320 case SIOCADDMULTI: 1321 case SIOCDELMULTI: 1322 /* The Aironet has no multicast filter. */ 1323 error = 0; 1324 break; 1325 case SIOCGAIRONET: 1326 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq)); 1327 if (error != 0) 1328 break; 1329#ifdef ANCACHE 1330 if (sc->areq.an_type == AN_RID_ZERO_CACHE) { 1331 error = suser(td); 1332 if (error) 1333 break; 1334 sc->an_sigitems = sc->an_nextitem = 0; 1335 break; 1336 } else if (sc->areq.an_type == AN_RID_READ_CACHE) { 1337 char *pt = (char *)&sc->areq.an_val; 1338 bcopy((char *)&sc->an_sigitems, (char *)pt, 1339 sizeof(int)); 1340 pt += sizeof(int); 1341 sc->areq.an_len = sizeof(int) / 2; 1342 bcopy((char *)&sc->an_sigcache, (char *)pt, 1343 sizeof(struct an_sigcache) * sc->an_sigitems); 1344 sc->areq.an_len += ((sizeof(struct an_sigcache) * 1345 sc->an_sigitems) / 2) + 1; 1346 } else 1347#endif 1348 if (an_read_record(sc, (struct an_ltv_gen *)&sc->areq)) { 1349 error = EINVAL; 1350 break; 1351 } 1352 error = copyout(&sc->areq, ifr->ifr_data, sizeof(sc->areq)); 1353 break; 1354 case SIOCSAIRONET: 1355 if ((error = suser(td))) 1356 goto out; 1357 error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq)); 1358 if (error != 0) 1359 break; 1360 an_setdef(sc, &sc->areq); 1361 break; 1362 case SIOCGPRIVATE_0: /* used by Cisco client utility */ 1363 if ((error = suser(td))) 1364 goto out; 1365 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl)); 1366 mode = l_ioctl.command; 1367 1368 if (mode >= AIROGCAP && mode <= AIROGSTATSD32) { 1369 error = readrids(ifp, &l_ioctl); 1370 }else if (mode >= AIROPCAP && mode <= AIROPLEAPUSR) { 1371 error = writerids(ifp, &l_ioctl); 1372 }else if (mode >= AIROFLSHRST && mode <= AIRORESTART) { 1373 error = flashcard(ifp, &l_ioctl); 1374 }else{ 1375 error =-1; 1376 } 1377 1378 /* copy out the updated command info */ 1379 copyout(&l_ioctl, ifr->ifr_data, sizeof(l_ioctl)); 1380 1381 break; 1382 case SIOCGPRIVATE_1: /* used by Cisco client utility */ 1383 if ((error = suser(td))) 1384 goto out; 1385 copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl)); 1386 l_ioctl.command = 0; 1387 error = AIROMAGIC; 1388 copyout(&error, l_ioctl.data, sizeof(error)); 1389 error = 0; 1390 break; 1391 case SIOCG80211: 1392 sc->areq.an_len = sizeof(sc->areq); 1393 /* was that a good idea DJA we are doing a short-cut */ 1394 switch (ireq->i_type) { 1395 case IEEE80211_IOC_SSID: 1396 if (ireq->i_val == -1) { 1397 sc->areq.an_type = AN_RID_STATUS; 1398 if (an_read_record(sc, 1399 (struct an_ltv_gen *)&sc->areq)) { 1400 error = EINVAL; 1401 break; 1402 } 1403 len = status->an_ssidlen; 1404 tmpptr = status->an_ssid; 1405 } else if (ireq->i_val >= 0) { 1406 sc->areq.an_type = AN_RID_SSIDLIST; 1407 if (an_read_record(sc, 1408 (struct an_ltv_gen *)&sc->areq)) { 1409 error = EINVAL; 1410 break; 1411 } 1412 if (ireq->i_val == 0) { 1413 len = ssids->an_ssid1_len; 1414 tmpptr = ssids->an_ssid1; 1415 } else if (ireq->i_val == 1) { 1416 len = ssids->an_ssid2_len; 1417 tmpptr = ssids->an_ssid2; 1418 } else if (ireq->i_val == 2) { 1419 len = ssids->an_ssid3_len; 1420 tmpptr = ssids->an_ssid3; 1421 } else { 1422 error = EINVAL; 1423 break; 1424 } 1425 } else { 1426 error = EINVAL; 1427 break; 1428 } 1429 if (len > IEEE80211_NWID_LEN) { 1430 error = EINVAL; 1431 break; 1432 } 1433 ireq->i_len = len; 1434 bzero(tmpstr, IEEE80211_NWID_LEN); 1435 bcopy(tmpptr, tmpstr, len); 1436 error = copyout(tmpstr, ireq->i_data, 1437 IEEE80211_NWID_LEN); 1438 break; 1439 case IEEE80211_IOC_NUMSSIDS: 1440 ireq->i_val = 3; 1441 break; 1442 case IEEE80211_IOC_WEP: 1443 sc->areq.an_type = AN_RID_ACTUALCFG; 1444 if (an_read_record(sc, 1445 (struct an_ltv_gen *)&sc->areq)) { 1446 error = EINVAL; 1447 break; 1448 } 1449 if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) { 1450 if (config->an_authtype & 1451 AN_AUTHTYPE_ALLOW_UNENCRYPTED) 1452 ireq->i_val = IEEE80211_WEP_MIXED; 1453 else 1454 ireq->i_val = IEEE80211_WEP_ON; 1455 } else { 1456 ireq->i_val = IEEE80211_WEP_OFF; 1457 } 1458 break; 1459 case IEEE80211_IOC_WEPKEY: 1460 /* 1461 * XXX: I'm not entierly convinced this is 1462 * correct, but it's what is implemented in 1463 * ancontrol so it will have to do until we get 1464 * access to actual Cisco code. 1465 */ 1466 if (ireq->i_val < 0 || ireq->i_val > 8) { 1467 error = EINVAL; 1468 break; 1469 } 1470 len = 0; 1471 if (ireq->i_val < 5) { 1472 sc->areq.an_type = AN_RID_WEP_TEMP; 1473 for (i = 0; i < 5; i++) { 1474 if (an_read_record(sc, 1475 (struct an_ltv_gen *)&sc->areq)) { 1476 error = EINVAL; 1477 break; 1478 } 1479 if (key->kindex == 0xffff) 1480 break; 1481 if (key->kindex == ireq->i_val) 1482 len = key->klen; 1483 /* Required to get next entry */ 1484 sc->areq.an_type = AN_RID_WEP_PERM; 1485 } 1486 if (error != 0) 1487 break; 1488 } 1489 /* We aren't allowed to read the value of the 1490 * key from the card so we just output zeros 1491 * like we would if we could read the card, but 1492 * denied the user access. 1493 */ 1494 bzero(tmpstr, len); 1495 ireq->i_len = len; 1496 error = copyout(tmpstr, ireq->i_data, len); 1497 break; 1498 case IEEE80211_IOC_NUMWEPKEYS: 1499 ireq->i_val = 9; /* include home key */ 1500 break; 1501 case IEEE80211_IOC_WEPTXKEY: 1502 /* 1503 * For some strange reason, you have to read all 1504 * keys before you can read the txkey. 1505 */ 1506 sc->areq.an_type = AN_RID_WEP_TEMP; 1507 for (i = 0; i < 5; i++) { 1508 if (an_read_record(sc, 1509 (struct an_ltv_gen *) &sc->areq)) { 1510 error = EINVAL; 1511 break; 1512 } 1513 if (key->kindex == 0xffff) 1514 break; 1515 /* Required to get next entry */ 1516 sc->areq.an_type = AN_RID_WEP_PERM; 1517 } 1518 if (error != 0) 1519 break; 1520 1521 sc->areq.an_type = AN_RID_WEP_PERM; 1522 key->kindex = 0xffff; 1523 if (an_read_record(sc, 1524 (struct an_ltv_gen *)&sc->areq)) { 1525 error = EINVAL; 1526 break; 1527 } 1528 ireq->i_val = key->mac[0]; 1529 /* 1530 * Check for home mode. Map home mode into 1531 * 5th key since that is how it is stored on 1532 * the card 1533 */ 1534 sc->areq.an_len = sizeof(struct an_ltv_genconfig); 1535 sc->areq.an_type = AN_RID_GENCONFIG; 1536 if (an_read_record(sc, 1537 (struct an_ltv_gen *)&sc->areq)) { 1538 error = EINVAL; 1539 break; 1540 } 1541 if (config->an_home_product & AN_HOME_NETWORK) 1542 ireq->i_val = 4; 1543 break; 1544 case IEEE80211_IOC_AUTHMODE: 1545 sc->areq.an_type = AN_RID_ACTUALCFG; 1546 if (an_read_record(sc, 1547 (struct an_ltv_gen *)&sc->areq)) { 1548 error = EINVAL; 1549 break; 1550 } 1551 if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1552 AN_AUTHTYPE_NONE) { 1553 ireq->i_val = IEEE80211_AUTH_NONE; 1554 } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1555 AN_AUTHTYPE_OPEN) { 1556 ireq->i_val = IEEE80211_AUTH_OPEN; 1557 } else if ((config->an_authtype & AN_AUTHTYPE_MASK) == 1558 AN_AUTHTYPE_SHAREDKEY) { 1559 ireq->i_val = IEEE80211_AUTH_SHARED; 1560 } else 1561 error = EINVAL; 1562 break; 1563 case IEEE80211_IOC_STATIONNAME: 1564 sc->areq.an_type = AN_RID_ACTUALCFG; 1565 if (an_read_record(sc, 1566 (struct an_ltv_gen *)&sc->areq)) { 1567 error = EINVAL; 1568 break; 1569 } 1570 ireq->i_len = sizeof(config->an_nodename); 1571 tmpptr = config->an_nodename; 1572 bzero(tmpstr, IEEE80211_NWID_LEN); 1573 bcopy(tmpptr, tmpstr, ireq->i_len); 1574 error = copyout(tmpstr, ireq->i_data, 1575 IEEE80211_NWID_LEN); 1576 break; 1577 case IEEE80211_IOC_CHANNEL: 1578 sc->areq.an_type = AN_RID_STATUS; 1579 if (an_read_record(sc, 1580 (struct an_ltv_gen *)&sc->areq)) { 1581 error = EINVAL; 1582 break; 1583 } 1584 ireq->i_val = status->an_cur_channel; 1585 break; 1586 case IEEE80211_IOC_POWERSAVE: 1587 sc->areq.an_type = AN_RID_ACTUALCFG; 1588 if (an_read_record(sc, 1589 (struct an_ltv_gen *)&sc->areq)) { 1590 error = EINVAL; 1591 break; 1592 } 1593 if (config->an_psave_mode == AN_PSAVE_NONE) { 1594 ireq->i_val = IEEE80211_POWERSAVE_OFF; 1595 } else if (config->an_psave_mode == AN_PSAVE_CAM) { 1596 ireq->i_val = IEEE80211_POWERSAVE_CAM; 1597 } else if (config->an_psave_mode == AN_PSAVE_PSP) { 1598 ireq->i_val = IEEE80211_POWERSAVE_PSP; 1599 } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) { 1600 ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM; 1601 } else 1602 error = EINVAL; 1603 break; 1604 case IEEE80211_IOC_POWERSAVESLEEP: 1605 sc->areq.an_type = AN_RID_ACTUALCFG; 1606 if (an_read_record(sc, 1607 (struct an_ltv_gen *)&sc->areq)) { 1608 error = EINVAL; 1609 break; 1610 } 1611 ireq->i_val = config->an_listen_interval; 1612 break; 1613 } 1614 break; 1615 case SIOCS80211: 1616 if ((error = suser(td))) 1617 goto out; 1618 sc->areq.an_len = sizeof(sc->areq); 1619 /* 1620 * We need a config structure for everything but the WEP 1621 * key management and SSIDs so we get it now so avoid 1622 * duplicating this code every time. 1623 */ 1624 if (ireq->i_type != IEEE80211_IOC_SSID && 1625 ireq->i_type != IEEE80211_IOC_WEPKEY && 1626 ireq->i_type != IEEE80211_IOC_WEPTXKEY) { 1627 sc->areq.an_type = AN_RID_GENCONFIG; 1628 if (an_read_record(sc, 1629 (struct an_ltv_gen *)&sc->areq)) { 1630 error = EINVAL; 1631 break; 1632 } 1633 } 1634 switch (ireq->i_type) { 1635 case IEEE80211_IOC_SSID: 1636 sc->areq.an_type = AN_RID_SSIDLIST; 1637 if (an_read_record(sc, 1638 (struct an_ltv_gen *)&sc->areq)) { 1639 error = EINVAL; 1640 break; 1641 } 1642 if (ireq->i_len > IEEE80211_NWID_LEN) { 1643 error = EINVAL; 1644 break; 1645 } 1646 switch (ireq->i_val) { 1647 case 0: 1648 error = copyin(ireq->i_data, 1649 ssids->an_ssid1, ireq->i_len); 1650 ssids->an_ssid1_len = ireq->i_len; 1651 break; 1652 case 1: 1653 error = copyin(ireq->i_data, 1654 ssids->an_ssid2, ireq->i_len); 1655 ssids->an_ssid2_len = ireq->i_len; 1656 break; 1657 case 2: 1658 error = copyin(ireq->i_data, 1659 ssids->an_ssid3, ireq->i_len); 1660 ssids->an_ssid3_len = ireq->i_len; 1661 break; 1662 default: 1663 error = EINVAL; 1664 break; 1665 } 1666 break; 1667 case IEEE80211_IOC_WEP: 1668 switch (ireq->i_val) { 1669 case IEEE80211_WEP_OFF: 1670 config->an_authtype &= 1671 ~(AN_AUTHTYPE_PRIVACY_IN_USE | 1672 AN_AUTHTYPE_ALLOW_UNENCRYPTED); 1673 break; 1674 case IEEE80211_WEP_ON: 1675 config->an_authtype |= 1676 AN_AUTHTYPE_PRIVACY_IN_USE; 1677 config->an_authtype &= 1678 ~AN_AUTHTYPE_ALLOW_UNENCRYPTED; 1679 break; 1680 case IEEE80211_WEP_MIXED: 1681 config->an_authtype |= 1682 AN_AUTHTYPE_PRIVACY_IN_USE | 1683 AN_AUTHTYPE_ALLOW_UNENCRYPTED; 1684 break; 1685 default: 1686 error = EINVAL; 1687 break; 1688 } 1689 break; 1690 case IEEE80211_IOC_WEPKEY: 1691 if (ireq->i_val < 0 || ireq->i_val > 7 || 1692 ireq->i_len > 13) { 1693 error = EINVAL; 1694 break; 1695 } 1696 error = copyin(ireq->i_data, tmpstr, 13); 1697 if (error != 0) 1698 break; 1699 bzero(&sc->areq, sizeof(struct an_ltv_key)); 1700 sc->areq.an_len = sizeof(struct an_ltv_key); 1701 key->mac[0] = 1; /* The others are 0. */ 1702 key->kindex = ireq->i_val % 4; 1703 if (ireq->i_val < 4) 1704 sc->areq.an_type = AN_RID_WEP_TEMP; 1705 else 1706 sc->areq.an_type = AN_RID_WEP_PERM; 1707 key->klen = ireq->i_len; 1708 bcopy(tmpstr, key->key, key->klen); 1709 break; 1710 case IEEE80211_IOC_WEPTXKEY: 1711 /* 1712 * Map the 5th key into the home mode 1713 * since that is how it is stored on 1714 * the card 1715 */ 1716 if (ireq->i_val < 0 || ireq->i_val > 4) { 1717 error = EINVAL; 1718 break; 1719 } 1720 sc->areq.an_len = sizeof(struct an_ltv_genconfig); 1721 sc->areq.an_type = AN_RID_ACTUALCFG; 1722 if (an_read_record(sc, 1723 (struct an_ltv_gen *)&sc->areq)) { 1724 error = EINVAL; 1725 break; 1726 } 1727 if (ireq->i_val == 4) { 1728 config->an_home_product |= AN_HOME_NETWORK; 1729 ireq->i_val = 0; 1730 } else { 1731 config->an_home_product &= ~AN_HOME_NETWORK; 1732 } 1733 1734 sc->an_config.an_home_product 1735 = config->an_home_product; 1736 an_write_record(sc, (struct an_ltv_gen *)&sc->areq); 1737 1738 bzero(&sc->areq, sizeof(struct an_ltv_key)); 1739 sc->areq.an_len = sizeof(struct an_ltv_key); 1740 sc->areq.an_type = AN_RID_WEP_PERM; 1741 key->kindex = 0xffff; 1742 key->mac[0] = ireq->i_val; 1743 break; 1744 case IEEE80211_IOC_AUTHMODE: 1745 switch (ireq->i_val) { 1746 case IEEE80211_AUTH_NONE: 1747 config->an_authtype = AN_AUTHTYPE_NONE | 1748 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1749 break; 1750 case IEEE80211_AUTH_OPEN: 1751 config->an_authtype = AN_AUTHTYPE_OPEN | 1752 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1753 break; 1754 case IEEE80211_AUTH_SHARED: 1755 config->an_authtype = AN_AUTHTYPE_SHAREDKEY | 1756 (config->an_authtype & ~AN_AUTHTYPE_MASK); 1757 break; 1758 default: 1759 error = EINVAL; 1760 } 1761 break; 1762 case IEEE80211_IOC_STATIONNAME: 1763 if (ireq->i_len > 16) { 1764 error = EINVAL; 1765 break; 1766 } 1767 bzero(config->an_nodename, 16); 1768 error = copyin(ireq->i_data, 1769 config->an_nodename, ireq->i_len); 1770 break; 1771 case IEEE80211_IOC_CHANNEL: 1772 /* 1773 * The actual range is 1-14, but if you set it 1774 * to 0 you get the default so we let that work 1775 * too. 1776 */ 1777 if (ireq->i_val < 0 || ireq->i_val >14) { 1778 error = EINVAL; 1779 break; 1780 } 1781 config->an_ds_channel = ireq->i_val; 1782 break; 1783 case IEEE80211_IOC_POWERSAVE: 1784 switch (ireq->i_val) { 1785 case IEEE80211_POWERSAVE_OFF: 1786 config->an_psave_mode = AN_PSAVE_NONE; 1787 break; 1788 case IEEE80211_POWERSAVE_CAM: 1789 config->an_psave_mode = AN_PSAVE_CAM; 1790 break; 1791 case IEEE80211_POWERSAVE_PSP: 1792 config->an_psave_mode = AN_PSAVE_PSP; 1793 break; 1794 case IEEE80211_POWERSAVE_PSP_CAM: 1795 config->an_psave_mode = AN_PSAVE_PSP_CAM; 1796 break; 1797 default: 1798 error = EINVAL; 1799 break; 1800 } 1801 break; 1802 case IEEE80211_IOC_POWERSAVESLEEP: 1803 config->an_listen_interval = ireq->i_val; 1804 break; 1805 } 1806 1807 if (!error) 1808 an_setdef(sc, &sc->areq); 1809 break; 1810 default: 1811 error = ether_ioctl(ifp, command, data); 1812 break; 1813 } 1814out: 1815 AN_UNLOCK(sc); 1816 1817 return(error != 0); 1818} 1819 1820static int 1821an_init_tx_ring(sc) 1822 struct an_softc *sc; 1823{ 1824 int i; 1825 int id; 1826 1827 if (sc->an_gone) 1828 return (0); 1829 1830 for (i = 0; i < AN_TX_RING_CNT; i++) { 1831 if (an_alloc_nicmem(sc, 1518 + 1832 0x44, &id)) 1833 return(ENOMEM); 1834 sc->an_rdata.an_tx_fids[i] = id; 1835 sc->an_rdata.an_tx_ring[i] = 0; 1836 } 1837 1838 sc->an_rdata.an_tx_prod = 0; 1839 sc->an_rdata.an_tx_cons = 0; 1840 1841 return(0); 1842} 1843 1844static void 1845an_init(xsc) 1846 void *xsc; 1847{ 1848 struct an_softc *sc = xsc; 1849 struct ifnet *ifp = &sc->arpcom.ac_if; 1850 1851 AN_LOCK(sc); 1852 1853 if (sc->an_gone) { 1854 AN_UNLOCK(sc); 1855 return; 1856 } 1857 1858 if (ifp->if_flags & IFF_RUNNING) 1859 an_stop(sc); 1860 1861 sc->an_associated = 0; 1862 1863 /* Allocate the TX buffers */ 1864 if (an_init_tx_ring(sc)) { 1865 an_reset(sc); 1866 if (an_init_tx_ring(sc)) { 1867 printf("an%d: tx buffer allocation " 1868 "failed\n", sc->an_unit); 1869 AN_UNLOCK(sc); 1870 return; 1871 } 1872 } 1873 1874 /* Set our MAC address. */ 1875 bcopy((char *)&sc->arpcom.ac_enaddr, 1876 (char *)&sc->an_config.an_macaddr, ETHER_ADDR_LEN); 1877 1878 if (ifp->if_flags & IFF_BROADCAST) 1879 sc->an_config.an_rxmode = AN_RXMODE_BC_ADDR; 1880 else 1881 sc->an_config.an_rxmode = AN_RXMODE_ADDR; 1882 1883 if (ifp->if_flags & IFF_MULTICAST) 1884 sc->an_config.an_rxmode = AN_RXMODE_BC_MC_ADDR; 1885 1886 if (ifp->if_flags & IFF_PROMISC) { 1887 if (sc->an_monitor & AN_MONITOR) { 1888 if (sc->an_monitor & AN_MONITOR_ANY_BSS) { 1889 sc->an_config.an_rxmode |= 1890 AN_RXMODE_80211_MONITOR_ANYBSS | 1891 AN_RXMODE_NO_8023_HEADER; 1892 } else { 1893 sc->an_config.an_rxmode |= 1894 AN_RXMODE_80211_MONITOR_CURBSS | 1895 AN_RXMODE_NO_8023_HEADER; 1896 } 1897 } 1898 } 1899 1900 /* Set the ssid list */ 1901 sc->an_ssidlist.an_type = AN_RID_SSIDLIST; 1902 sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); 1903 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { 1904 printf("an%d: failed to set ssid list\n", sc->an_unit); 1905 AN_UNLOCK(sc); 1906 return; 1907 } 1908 1909 /* Set the AP list */ 1910 sc->an_aplist.an_type = AN_RID_APLIST; 1911 sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); 1912 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { 1913 printf("an%d: failed to set AP list\n", sc->an_unit); 1914 AN_UNLOCK(sc); 1915 return; 1916 } 1917 1918 /* Set the configuration in the NIC */ 1919 sc->an_config.an_len = sizeof(struct an_ltv_genconfig); 1920 sc->an_config.an_type = AN_RID_GENCONFIG; 1921 if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) { 1922 printf("an%d: failed to set configuration\n", sc->an_unit); 1923 AN_UNLOCK(sc); 1924 return; 1925 } 1926 1927 /* Enable the MAC */ 1928 if (an_cmd(sc, AN_CMD_ENABLE, 0)) { 1929 printf("an%d: failed to enable MAC\n", sc->an_unit); 1930 AN_UNLOCK(sc); 1931 return; 1932 } 1933 1934 if (ifp->if_flags & IFF_PROMISC) 1935 an_cmd(sc, AN_CMD_SET_MODE, 0xffff); 1936 1937 /* enable interrupts */ 1938 CSR_WRITE_2(sc, AN_INT_EN, AN_INTRS); 1939 1940 ifp->if_flags |= IFF_RUNNING; 1941 ifp->if_flags &= ~IFF_OACTIVE; 1942 1943 sc->an_stat_ch = timeout(an_stats_update, sc, hz); 1944 AN_UNLOCK(sc); 1945 1946 return; 1947} 1948 1949static void 1950an_start(ifp) 1951 struct ifnet *ifp; 1952{ 1953 struct an_softc *sc; 1954 struct mbuf *m0 = NULL; 1955 struct an_txframe_802_3 tx_frame_802_3; 1956 struct ether_header *eh; 1957 int id; 1958 int idx; 1959 unsigned char txcontrol; 1960 1961 sc = ifp->if_softc; 1962 1963 if (sc->an_gone) 1964 return; 1965 1966 if (ifp->if_flags & IFF_OACTIVE) 1967 return; 1968 1969 if (!sc->an_associated) 1970 return; 1971 1972 /* We can't send in monitor mode so toss any attempts. */ 1973 if (sc->an_monitor && (ifp->if_flags & IFF_PROMISC)) { 1974 for (;;) { 1975 IF_DEQUEUE(&ifp->if_snd, m0); 1976 if (m0 == NULL) 1977 break; 1978 m_freem(m0); 1979 } 1980 return; 1981 } 1982 1983 idx = sc->an_rdata.an_tx_prod; 1984 bzero((char *)&tx_frame_802_3, sizeof(tx_frame_802_3)); 1985 1986 while (sc->an_rdata.an_tx_ring[idx] == 0) { 1987 IF_DEQUEUE(&ifp->if_snd, m0); 1988 if (m0 == NULL) 1989 break; 1990 1991 id = sc->an_rdata.an_tx_fids[idx]; 1992 eh = mtod(m0, struct ether_header *); 1993 1994 bcopy((char *)&eh->ether_dhost, 1995 (char *)&tx_frame_802_3.an_tx_dst_addr, ETHER_ADDR_LEN); 1996 bcopy((char *)&eh->ether_shost, 1997 (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); 1998 1999 tx_frame_802_3.an_tx_802_3_payload_len = 2000 m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ 2001 2002 m_copydata(m0, sizeof(struct ether_header) - 2 , 2003 tx_frame_802_3.an_tx_802_3_payload_len, 2004 (caddr_t)&sc->an_txbuf); 2005 2006 txcontrol = AN_TXCTL_8023; 2007 /* write the txcontrol only */ 2008 an_write_data(sc, id, 0x08, (caddr_t)&txcontrol, 2009 sizeof(txcontrol)); 2010 2011 /* 802_3 header */ 2012 an_write_data(sc, id, 0x34, (caddr_t)&tx_frame_802_3, 2013 sizeof(struct an_txframe_802_3)); 2014 2015 /* in mbuf header type is just before payload */ 2016 an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, 2017 tx_frame_802_3.an_tx_802_3_payload_len); 2018 2019 /* 2020 * If there's a BPF listner, bounce a copy of 2021 * this frame to him. 2022 */ 2023 BPF_MTAP(ifp, m0); 2024 2025 m_freem(m0); 2026 m0 = NULL; 2027 2028 sc->an_rdata.an_tx_ring[idx] = id; 2029 if (an_cmd(sc, AN_CMD_TX, id)) 2030 printf("an%d: xmit failed\n", sc->an_unit); 2031 2032 AN_INC(idx, AN_TX_RING_CNT); 2033 } 2034 2035 if (m0 != NULL) 2036 ifp->if_flags |= IFF_OACTIVE; 2037 2038 sc->an_rdata.an_tx_prod = idx; 2039 2040 /* 2041 * Set a timeout in case the chip goes out to lunch. 2042 */ 2043 ifp->if_timer = 5; 2044 2045 return; 2046} 2047 2048void 2049an_stop(sc) 2050 struct an_softc *sc; 2051{ 2052 struct ifnet *ifp; 2053 int i; 2054 2055 AN_LOCK(sc); 2056 2057 if (sc->an_gone) { 2058 AN_UNLOCK(sc); 2059 return; 2060 } 2061 2062 ifp = &sc->arpcom.ac_if; 2063 2064 an_cmd(sc, AN_CMD_FORCE_SYNCLOSS, 0); 2065 CSR_WRITE_2(sc, AN_INT_EN, 0); 2066 an_cmd(sc, AN_CMD_DISABLE, 0); 2067 2068 for (i = 0; i < AN_TX_RING_CNT; i++) 2069 an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]); 2070 2071 untimeout(an_stats_update, sc, sc->an_stat_ch); 2072 2073 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 2074 2075 AN_UNLOCK(sc); 2076 2077 return; 2078} 2079 2080static void 2081an_watchdog(ifp) 2082 struct ifnet *ifp; 2083{ 2084 struct an_softc *sc; 2085 2086 sc = ifp->if_softc; 2087 AN_LOCK(sc); 2088 2089 if (sc->an_gone) { 2090 AN_UNLOCK(sc); 2091 return; 2092 } 2093 2094 printf("an%d: device timeout\n", sc->an_unit); 2095 2096 an_reset(sc); 2097 an_init(sc); 2098 2099 ifp->if_oerrors++; 2100 AN_UNLOCK(sc); 2101 2102 return; 2103} 2104 2105void 2106an_shutdown(dev) 2107 device_t dev; 2108{ 2109 struct an_softc *sc; 2110 2111 sc = device_get_softc(dev); 2112 an_stop(sc); 2113 2114 return; 2115} 2116 2117#ifdef ANCACHE 2118/* Aironet signal strength cache code. 2119 * store signal/noise/quality on per MAC src basis in 2120 * a small fixed cache. The cache wraps if > MAX slots 2121 * used. The cache may be zeroed out to start over. 2122 * Two simple filters exist to reduce computation: 2123 * 1. ip only (literally 0x800, ETHERTYPE_IP) which may be used 2124 * to ignore some packets. It defaults to ip only. 2125 * it could be used to focus on broadcast, non-IP 802.11 beacons. 2126 * 2. multicast/broadcast only. This may be used to 2127 * ignore unicast packets and only cache signal strength 2128 * for multicast/broadcast packets (beacons); e.g., Mobile-IP 2129 * beacons and not unicast traffic. 2130 * 2131 * The cache stores (MAC src(index), IP src (major clue), signal, 2132 * quality, noise) 2133 * 2134 * No apologies for storing IP src here. It's easy and saves much 2135 * trouble elsewhere. The cache is assumed to be INET dependent, 2136 * although it need not be. 2137 * 2138 * Note: the Aironet only has a single byte of signal strength value 2139 * in the rx frame header, and it's not scaled to anything sensible. 2140 * This is kind of lame, but it's all we've got. 2141 */ 2142 2143#ifdef documentation 2144 2145int an_sigitems; /* number of cached entries */ 2146struct an_sigcache an_sigcache[MAXANCACHE]; /* array of cache entries */ 2147int an_nextitem; /* index/# of entries */ 2148 2149 2150#endif 2151 2152/* control variables for cache filtering. Basic idea is 2153 * to reduce cost (e.g., to only Mobile-IP agent beacons 2154 * which are broadcast or multicast). Still you might 2155 * want to measure signal strength anth unicast ping packets 2156 * on a pt. to pt. ant. setup. 2157 */ 2158/* set true if you want to limit cache items to broadcast/mcast 2159 * only packets (not unicast). Useful for mobile-ip beacons which 2160 * are broadcast/multicast at network layer. Default is all packets 2161 * so ping/unicast anll work say anth pt. to pt. antennae setup. 2162 */ 2163static int an_cache_mcastonly = 0; 2164SYSCTL_INT(_machdep, OID_AUTO, an_cache_mcastonly, CTLFLAG_RW, 2165 &an_cache_mcastonly, 0, ""); 2166 2167/* set true if you want to limit cache items to IP packets only 2168*/ 2169static int an_cache_iponly = 1; 2170SYSCTL_INT(_machdep, OID_AUTO, an_cache_iponly, CTLFLAG_RW, 2171 &an_cache_iponly, 0, ""); 2172 2173/* 2174 * an_cache_store, per rx packet store signal 2175 * strength in MAC (src) indexed cache. 2176 */ 2177static void 2178an_cache_store (sc, eh, m, rx_quality) 2179 struct an_softc *sc; 2180 struct ether_header *eh; 2181 struct mbuf *m; 2182 unsigned short rx_quality; 2183{ 2184 struct ip *ip = 0; 2185 int i; 2186 static int cache_slot = 0; /* use this cache entry */ 2187 static int wrapindex = 0; /* next "free" cache entry */ 2188 int type_ipv4 = 0; 2189 2190 /* filters: 2191 * 1. ip only 2192 * 2. configurable filter to throw out unicast packets, 2193 * keep multicast only. 2194 */ 2195 2196 if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) { 2197 type_ipv4 = 1; 2198 } 2199 2200 /* filter for ip packets only 2201 */ 2202 if ( an_cache_iponly && !type_ipv4) { 2203 return; 2204 } 2205 2206 /* filter for broadcast/multicast only 2207 */ 2208 if (an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { 2209 return; 2210 } 2211 2212#ifdef SIGDEBUG 2213 printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", 2214 rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); 2215#endif 2216 2217 /* find the ip header. we want to store the ip_src 2218 * address. 2219 */ 2220 if (type_ipv4) { 2221 ip = mtod(m, struct ip *); 2222 } 2223 2224 /* do a linear search for a matching MAC address 2225 * in the cache table 2226 * . MAC address is 6 bytes, 2227 * . var w_nextitem holds total number of entries already cached 2228 */ 2229 for (i = 0; i < sc->an_nextitem; i++) { 2230 if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6 )) { 2231 /* Match!, 2232 * so we already have this entry, 2233 * update the data 2234 */ 2235 break; 2236 } 2237 } 2238 2239 /* did we find a matching mac address? 2240 * if yes, then overwrite a previously existing cache entry 2241 */ 2242 if (i < sc->an_nextitem ) { 2243 cache_slot = i; 2244 } 2245 /* else, have a new address entry,so 2246 * add this new entry, 2247 * if table full, then we need to replace LRU entry 2248 */ 2249 else { 2250 2251 /* check for space in cache table 2252 * note: an_nextitem also holds number of entries 2253 * added in the cache table 2254 */ 2255 if ( sc->an_nextitem < MAXANCACHE ) { 2256 cache_slot = sc->an_nextitem; 2257 sc->an_nextitem++; 2258 sc->an_sigitems = sc->an_nextitem; 2259 } 2260 /* no space found, so simply wrap anth wrap index 2261 * and "zap" the next entry 2262 */ 2263 else { 2264 if (wrapindex == MAXANCACHE) { 2265 wrapindex = 0; 2266 } 2267 cache_slot = wrapindex++; 2268 } 2269 } 2270 2271 /* invariant: cache_slot now points at some slot 2272 * in cache. 2273 */ 2274 if (cache_slot < 0 || cache_slot >= MAXANCACHE) { 2275 log(LOG_ERR, "an_cache_store, bad index: %d of " 2276 "[0..%d], gross cache error\n", 2277 cache_slot, MAXANCACHE); 2278 return; 2279 } 2280 2281 /* store items in cache 2282 * .ip source address 2283 * .mac src 2284 * .signal, etc. 2285 */ 2286 if (type_ipv4) { 2287 sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; 2288 } 2289 bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); 2290 2291 sc->an_sigcache[cache_slot].signal = rx_quality; 2292 2293 return; 2294} 2295#endif 2296 2297static int 2298an_media_change(ifp) 2299 struct ifnet *ifp; 2300{ 2301 struct an_softc *sc = ifp->if_softc; 2302 int otype = sc->an_config.an_opmode; 2303 int orate = sc->an_tx_rate; 2304 2305 if ((sc->an_ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0) 2306 sc->an_config.an_opmode = AN_OPMODE_IBSS_ADHOC; 2307 else 2308 sc->an_config.an_opmode = AN_OPMODE_INFRASTRUCTURE_STATION; 2309 2310 switch (IFM_SUBTYPE(sc->an_ifmedia.ifm_cur->ifm_media)) { 2311 case IFM_IEEE80211_DS1: 2312 sc->an_tx_rate = AN_RATE_1MBPS; 2313 break; 2314 case IFM_IEEE80211_DS2: 2315 sc->an_tx_rate = AN_RATE_2MBPS; 2316 break; 2317 case IFM_IEEE80211_DS5: 2318 sc->an_tx_rate = AN_RATE_5_5MBPS; 2319 break; 2320 case IFM_IEEE80211_DS11: 2321 sc->an_tx_rate = AN_RATE_11MBPS; 2322 break; 2323 case IFM_AUTO: 2324 sc->an_tx_rate = 0; 2325 break; 2326 } 2327 2328 if (otype != sc->an_config.an_opmode || 2329 orate != sc->an_tx_rate) 2330 an_init(sc); 2331 2332 return(0); 2333} 2334 2335static void 2336an_media_status(ifp, imr) 2337 struct ifnet *ifp; 2338 struct ifmediareq *imr; 2339{ 2340 struct an_ltv_status status; 2341 struct an_softc *sc = ifp->if_softc; 2342 2343 status.an_len = sizeof(status); 2344 status.an_type = AN_RID_STATUS; 2345 if (an_read_record(sc, (struct an_ltv_gen *)&status)) { 2346 /* If the status read fails, just lie. */ 2347 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 2348 imr->ifm_status = IFM_AVALID|IFM_ACTIVE; 2349 } 2350 2351 if (sc->an_tx_rate == 0) { 2352 imr->ifm_active = IFM_IEEE80211|IFM_AUTO; 2353 if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC) 2354 imr->ifm_active |= IFM_IEEE80211_ADHOC; 2355 switch (status.an_current_tx_rate) { 2356 case AN_RATE_1MBPS: 2357 imr->ifm_active |= IFM_IEEE80211_DS1; 2358 break; 2359 case AN_RATE_2MBPS: 2360 imr->ifm_active |= IFM_IEEE80211_DS2; 2361 break; 2362 case AN_RATE_5_5MBPS: 2363 imr->ifm_active |= IFM_IEEE80211_DS5; 2364 break; 2365 case AN_RATE_11MBPS: 2366 imr->ifm_active |= IFM_IEEE80211_DS11; 2367 break; 2368 } 2369 } else { 2370 imr->ifm_active = sc->an_ifmedia.ifm_cur->ifm_media; 2371 } 2372 2373 imr->ifm_status = IFM_AVALID; 2374 if (status.an_opmode & AN_STATUS_OPMODE_ASSOCIATED) 2375 imr->ifm_status |= IFM_ACTIVE; 2376} 2377 2378/********************** Cisco utility support routines *************/ 2379 2380/* 2381 * ReadRids & WriteRids derived from Cisco driver additions to Ben Reed's 2382 * Linux driver 2383 */ 2384 2385static int 2386readrids(ifp, l_ioctl) 2387 struct ifnet *ifp; 2388 struct aironet_ioctl *l_ioctl; 2389{ 2390 unsigned short rid; 2391 struct an_softc *sc; 2392 2393 switch (l_ioctl->command) { 2394 case AIROGCAP: 2395 rid = AN_RID_CAPABILITIES; 2396 break; 2397 case AIROGCFG: 2398 rid = AN_RID_GENCONFIG; 2399 break; 2400 case AIROGSLIST: 2401 rid = AN_RID_SSIDLIST; 2402 break; 2403 case AIROGVLIST: 2404 rid = AN_RID_APLIST; 2405 break; 2406 case AIROGDRVNAM: 2407 rid = AN_RID_DRVNAME; 2408 break; 2409 case AIROGEHTENC: 2410 rid = AN_RID_ENCAPPROTO; 2411 break; 2412 case AIROGWEPKTMP: 2413 rid = AN_RID_WEP_TEMP; 2414 break; 2415 case AIROGWEPKNV: 2416 rid = AN_RID_WEP_PERM; 2417 break; 2418 case AIROGSTAT: 2419 rid = AN_RID_STATUS; 2420 break; 2421 case AIROGSTATSD32: 2422 rid = AN_RID_32BITS_DELTA; 2423 break; 2424 case AIROGSTATSC32: 2425 rid = AN_RID_32BITS_CUM; 2426 break; 2427 default: 2428 rid = 999; 2429 break; 2430 } 2431 2432 if (rid == 999) /* Is bad command */ 2433 return -EINVAL; 2434 2435 sc = ifp->if_softc; 2436 sc->areq.an_len = AN_MAX_DATALEN; 2437 sc->areq.an_type = rid; 2438 2439 an_read_record(sc, (struct an_ltv_gen *)&sc->areq); 2440 2441 l_ioctl->len = sc->areq.an_len - 4; /* just data */ 2442 2443 /* the data contains the length at first */ 2444 if (copyout(&(sc->areq.an_len), l_ioctl->data, 2445 sizeof(sc->areq.an_len))) { 2446 return -EFAULT; 2447 } 2448 /* Just copy the data back */ 2449 if (copyout(&(sc->areq.an_val), l_ioctl->data + 2, 2450 l_ioctl->len)) { 2451 return -EFAULT; 2452 } 2453 return 0; 2454} 2455 2456static int 2457writerids(ifp, l_ioctl) 2458 struct ifnet *ifp; 2459 struct aironet_ioctl *l_ioctl; 2460{ 2461 struct an_softc *sc; 2462 int rid, command; 2463 2464 sc = ifp->if_softc; 2465 rid = 0; 2466 command = l_ioctl->command; 2467 2468 switch (command) { 2469 case AIROPSIDS: 2470 rid = AN_RID_SSIDLIST; 2471 break; 2472 case AIROPCAP: 2473 rid = AN_RID_CAPABILITIES; 2474 break; 2475 case AIROPAPLIST: 2476 rid = AN_RID_APLIST; 2477 break; 2478 case AIROPCFG: 2479 rid = AN_RID_GENCONFIG; 2480 break; 2481 case AIROPMACON: 2482 an_cmd(sc, AN_CMD_ENABLE, 0); 2483 return 0; 2484 break; 2485 case AIROPMACOFF: 2486 an_cmd(sc, AN_CMD_DISABLE, 0); 2487 return 0; 2488 break; 2489 case AIROPSTCLR: 2490 /* 2491 * This command merely clears the counts does not actually 2492 * store any data only reads rid. But as it changes the cards 2493 * state, I put it in the writerid routines. 2494 */ 2495 2496 rid = AN_RID_32BITS_DELTACLR; 2497 sc = ifp->if_softc; 2498 sc->areq.an_len = AN_MAX_DATALEN; 2499 sc->areq.an_type = rid; 2500 2501 an_read_record(sc, (struct an_ltv_gen *)&sc->areq); 2502 l_ioctl->len = sc->areq.an_len - 4; /* just data */ 2503 2504 /* the data contains the length at first */ 2505 if (copyout(&(sc->areq.an_len), l_ioctl->data, 2506 sizeof(sc->areq.an_len))) { 2507 return -EFAULT; 2508 } 2509 /* Just copy the data */ 2510 if (copyout(&(sc->areq.an_val), l_ioctl->data + 2, 2511 l_ioctl->len)) { 2512 return -EFAULT; 2513 } 2514 return 0; 2515 break; 2516 case AIROPWEPKEY: 2517 rid = AN_RID_WEP_TEMP; 2518 break; 2519 case AIROPWEPKEYNV: 2520 rid = AN_RID_WEP_PERM; 2521 break; 2522 case AIROPLEAPUSR: 2523 rid = AN_RID_LEAPUSERNAME; 2524 break; 2525 case AIROPLEAPPWD: 2526 rid = AN_RID_LEAPPASSWORD; 2527 break; 2528 default: 2529 return -EOPNOTSUPP; 2530 } 2531 2532 if (rid) { 2533 if (l_ioctl->len > sizeof(sc->areq.an_val) + 4) 2534 return -EINVAL; 2535 sc->areq.an_len = l_ioctl->len + 4; /* add type & length */ 2536 sc->areq.an_type = rid; 2537 2538 /* Just copy the data back */ 2539 copyin((l_ioctl->data) + 2, &sc->areq.an_val, 2540 l_ioctl->len); 2541 2542 an_cmd(sc, AN_CMD_DISABLE, 0); 2543 an_write_record(sc, (struct an_ltv_gen *)&sc->areq); 2544 an_cmd(sc, AN_CMD_ENABLE, 0); 2545 return 0; 2546 } 2547 return -EOPNOTSUPP; 2548} 2549 2550/* 2551 * General Flash utilities derived from Cisco driver additions to Ben Reed's 2552 * Linux driver 2553 */ 2554 2555#define FLASH_DELAY(x) tsleep(ifp, PZERO, "flash", ((x) / hz) + 1); 2556 2557static int 2558unstickbusy(ifp) 2559 struct ifnet *ifp; 2560{ 2561 struct an_softc *sc = ifp->if_softc; 2562 2563 if (CSR_READ_2(sc, AN_COMMAND) & AN_CMD_BUSY) { 2564 CSR_WRITE_2(sc, AN_EVENT_ACK, AN_EV_CLR_STUCK_BUSY); 2565 return 1; 2566 } 2567 return 0; 2568} 2569 2570/* 2571 * Wait for busy completion from card wait for delay uSec's Return true for 2572 * success meaning command reg is clear 2573 */ 2574 2575static int 2576WaitBusy(ifp, uSec) 2577 struct ifnet *ifp; 2578 int uSec; 2579{ 2580 int statword = 0xffff; 2581 int delay = 0; 2582 struct an_softc *sc = ifp->if_softc; 2583 2584 while ((statword & AN_CMD_BUSY) && delay <= (1000 * 100)) { 2585 FLASH_DELAY(10); 2586 delay += 10; 2587 statword = CSR_READ_2(sc, AN_COMMAND); 2588 2589 if ((AN_CMD_BUSY & statword) && (delay % 200)) { 2590 unstickbusy(ifp); 2591 } 2592 } 2593 2594 return 0 == (AN_CMD_BUSY & statword); 2595} 2596 2597/* 2598 * STEP 1) Disable MAC and do soft reset on card. 2599 */ 2600 2601static int 2602cmdreset(ifp) 2603 struct ifnet *ifp; 2604{ 2605 int status; 2606 struct an_softc *sc = ifp->if_softc; 2607 2608 an_stop(sc); 2609 2610 an_cmd(sc, AN_CMD_DISABLE, 0); 2611 2612 if (!(status = WaitBusy(ifp, 600))) { 2613 printf("an%d: Waitbusy hang b4 RESET =%d\n", 2614 sc->an_unit, status); 2615 return -EBUSY; 2616 } 2617 CSR_WRITE_2(sc, AN_COMMAND, AN_CMD_FW_RESTART); 2618 2619 FLASH_DELAY(1000); /* WAS 600 12/7/00 */ 2620 2621 2622 if (!(status = WaitBusy(ifp, 100))) { 2623 printf("an%d: Waitbusy hang AFTER RESET =%d\n", 2624 sc->an_unit, status); 2625 return -EBUSY; 2626 } 2627 return 0; 2628} 2629 2630/* 2631 * STEP 2) Put the card in legendary flash mode 2632 */ 2633#define FLASH_COMMAND 0x7e7e 2634 2635static int 2636setflashmode(ifp) 2637 struct ifnet *ifp; 2638{ 2639 int status; 2640 struct an_softc *sc = ifp->if_softc; 2641 2642 CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND); 2643 CSR_WRITE_2(sc, AN_SW1, FLASH_COMMAND); 2644 CSR_WRITE_2(sc, AN_SW0, FLASH_COMMAND); 2645 CSR_WRITE_2(sc, AN_COMMAND, FLASH_COMMAND); 2646 2647 /* 2648 * mdelay(500); // 500ms delay 2649 */ 2650 2651 FLASH_DELAY(500); 2652 2653 if (!(status = WaitBusy(ifp, 600))) { 2654 printf("Waitbusy hang after setflash mode\n"); 2655 return -EIO; 2656 } 2657 return 0; 2658} 2659 2660/* 2661 * Get a character from the card matching matchbyte Step 3) 2662 */ 2663 2664static int 2665flashgchar(ifp, matchbyte, dwelltime) 2666 struct ifnet *ifp; 2667 int matchbyte; 2668 int dwelltime; 2669{ 2670 int rchar; 2671 unsigned char rbyte = 0; 2672 int success = -1; 2673 struct an_softc *sc = ifp->if_softc; 2674 2675 2676 do { 2677 rchar = CSR_READ_2(sc, AN_SW1); 2678 2679 if (dwelltime && !(0x8000 & rchar)) { 2680 dwelltime -= 10; 2681 FLASH_DELAY(10); 2682 continue; 2683 } 2684 rbyte = 0xff & rchar; 2685 2686 if ((rbyte == matchbyte) && (0x8000 & rchar)) { 2687 CSR_WRITE_2(sc, AN_SW1, 0); 2688 success = 1; 2689 break; 2690 } 2691 if (rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar) 2692 break; 2693 CSR_WRITE_2(sc, AN_SW1, 0); 2694 2695 } while (dwelltime > 0); 2696 return success; 2697} 2698 2699/* 2700 * Put character to SWS0 wait for dwelltime x 50us for echo . 2701 */ 2702 2703static int 2704flashpchar(ifp, byte, dwelltime) 2705 struct ifnet *ifp; 2706 int byte; 2707 int dwelltime; 2708{ 2709 int echo; 2710 int pollbusy, waittime; 2711 struct an_softc *sc = ifp->if_softc; 2712 2713 byte |= 0x8000; 2714 2715 if (dwelltime == 0) 2716 dwelltime = 200; 2717 2718 waittime = dwelltime; 2719 2720 /* 2721 * Wait for busy bit d15 to go false indicating buffer empty 2722 */ 2723 do { 2724 pollbusy = CSR_READ_2(sc, AN_SW0); 2725 2726 if (pollbusy & 0x8000) { 2727 FLASH_DELAY(50); 2728 waittime -= 50; 2729 continue; 2730 } else 2731 break; 2732 } 2733 while (waittime >= 0); 2734 2735 /* timeout for busy clear wait */ 2736 2737 if (waittime <= 0) { 2738 printf("an%d: flash putchar busywait timeout! \n", 2739 sc->an_unit); 2740 return -1; 2741 } 2742 /* 2743 * Port is clear now write byte and wait for it to echo back 2744 */ 2745 do { 2746 CSR_WRITE_2(sc, AN_SW0, byte); 2747 FLASH_DELAY(50); 2748 dwelltime -= 50; 2749 echo = CSR_READ_2(sc, AN_SW1); 2750 } while (dwelltime >= 0 && echo != byte); 2751 2752 2753 CSR_WRITE_2(sc, AN_SW1, 0); 2754 2755 return echo == byte; 2756} 2757 2758/* 2759 * Transfer 32k of firmware data from user buffer to our buffer and send to 2760 * the card 2761 */ 2762 2763static char flashbuffer[1024 * 38]; /* RAW Buffer for flash will be 2764 * dynamic next */ 2765 2766static int 2767flashputbuf(ifp) 2768 struct ifnet *ifp; 2769{ 2770 unsigned short *bufp; 2771 int nwords; 2772 struct an_softc *sc = ifp->if_softc; 2773 2774 /* Write stuff */ 2775 2776 bufp = (unsigned short *)flashbuffer; 2777 2778 CSR_WRITE_2(sc, AN_AUX_PAGE, 0x100); 2779 CSR_WRITE_2(sc, AN_AUX_OFFSET, 0); 2780 2781 for (nwords = 0; nwords != 16384; nwords++) { 2782 CSR_WRITE_2(sc, AN_AUX_DATA, bufp[nwords] & 0xffff); 2783 } 2784 2785 CSR_WRITE_2(sc, AN_SW0, 0x8000); 2786 2787 return 0; 2788} 2789 2790/* 2791 * After flashing restart the card. 2792 */ 2793 2794static int 2795flashrestart(ifp) 2796 struct ifnet *ifp; 2797{ 2798 int status = 0; 2799 struct an_softc *sc = ifp->if_softc; 2800 2801 FLASH_DELAY(1024); /* Added 12/7/00 */ 2802 2803 an_init(sc); 2804 2805 FLASH_DELAY(1024); /* Added 12/7/00 */ 2806 return status; 2807} 2808 2809/* 2810 * Entry point for flash ioclt. 2811 */ 2812 2813static int 2814flashcard(ifp, l_ioctl) 2815 struct ifnet *ifp; 2816 struct aironet_ioctl *l_ioctl; 2817{ 2818 int z = 0, status; 2819 struct an_softc *sc; 2820 2821 sc = ifp->if_softc; 2822 status = l_ioctl->command; 2823 2824 switch (l_ioctl->command) { 2825 case AIROFLSHRST: 2826 return cmdreset(ifp); 2827 break; 2828 case AIROFLSHSTFL: 2829 return setflashmode(ifp); 2830 break; 2831 case AIROFLSHGCHR: /* Get char from aux */ 2832 copyin(l_ioctl->data, &sc->areq, l_ioctl->len); 2833 z = *(int *)&sc->areq; 2834 if ((status = flashgchar(ifp, z, 8000)) == 1) 2835 return 0; 2836 else 2837 return -1; 2838 break; 2839 case AIROFLSHPCHR: /* Send char to card. */ 2840 copyin(l_ioctl->data, &sc->areq, l_ioctl->len); 2841 z = *(int *)&sc->areq; 2842 if ((status = flashpchar(ifp, z, 8000)) == -1) 2843 return -EIO; 2844 else 2845 return 0; 2846 break; 2847 case AIROFLPUTBUF: /* Send 32k to card */ 2848 if (l_ioctl->len > sizeof(flashbuffer)) { 2849 printf("an%d: Buffer to big, %x %zx\n", sc->an_unit, 2850 l_ioctl->len, sizeof(flashbuffer)); 2851 return -EINVAL; 2852 } 2853 copyin(l_ioctl->data, &flashbuffer, l_ioctl->len); 2854 2855 if ((status = flashputbuf(ifp)) != 0) 2856 return -EIO; 2857 else 2858 return 0; 2859 break; 2860 case AIRORESTART: 2861 if ((status = flashrestart(ifp)) != 0) { 2862 printf("an%d: FLASHRESTART returned %d\n", 2863 sc->an_unit, status); 2864 return -EIO; 2865 } else 2866 return 0; 2867 2868 break; 2869 default: 2870 return -EINVAL; 2871 } 2872 2873 return -EINVAL; 2874} 2875 2876