if_wi.c revision 52632
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/wi/if_wi.c 52632 1999-10-29 17:28:09Z imp $ 33 */ 34 35/* 36 * Lucent WaveLAN/IEEE 802.11 PCMCIA 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 WaveLAN/IEEE adapter is the second generation of the WaveLAN 45 * from Lucent. Unlike the older cards, the new ones are programmed 46 * entirely via a firmware-driven controller called the Hermes. 47 * Unfortunately, Lucent will not release the Hermes programming manual 48 * without an NDA (if at all). What they do release is an API library 49 * called the HCF (Hardware Control Functions) which is supposed to 50 * do the device-specific operations of a device driver for you. The 51 * publically available version of the HCF library (the 'HCF Light') is 52 * a) extremely gross, b) lacks certain features, particularly support 53 * for 802.11 frames, and c) is contaminated by the GNU Public License. 54 * 55 * This driver does not use the HCF or HCF Light at all. Instead, it 56 * programs the Hermes controller directly, using information gleaned 57 * from the HCF Light code and corresponding documentation. 58 * 59 * This driver supports both the PCMCIA and ISA versions of the 60 * WaveLAN/IEEE cards. Note however that the ISA card isn't really 61 * anything of the sort: it's actually a PCMCIA bridge adapter 62 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is 63 * inserted. Consequently, you need to use the pccard support for 64 * both the ISA and PCMCIA adapters. 65 */ 66 67#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */ 68#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */ 69 70#include "card.h" 71#undef NCARD 72#define NCARD 0 73#include "wi.h" 74 75#include <sys/param.h> 76#include <sys/systm.h> 77#include <sys/eventhandler.h> 78#include <sys/sockio.h> 79#include <sys/mbuf.h> 80#include <sys/malloc.h> 81#include <sys/kernel.h> 82#include <sys/socket.h> 83 84#include <net/if.h> 85#include <net/if_arp.h> 86#include <net/ethernet.h> 87#include <net/if_dl.h> 88#include <net/if_media.h> 89#include <net/if_types.h> 90 91#ifdef INET 92#include <netinet/in.h> 93#include <netinet/in_systm.h> 94#include <netinet/in_var.h> 95#include <netinet/ip.h> 96#include <netinet/if_ether.h> 97#endif 98 99#include <net/bpf.h> 100 101#include <machine/clock.h> 102#include <machine/md_var.h> 103#include <machine/bus_pio.h> 104#include <machine/bus.h> 105 106#include <i386/isa/isa_device.h> 107#include <i386/isa/icu.h> 108#include <i386/isa/if_wireg.h> 109#include <machine/if_wavelan_ieee.h> 110 111#if NCARD > 0 112#include <sys/select.h> 113#include <pccard/cardinfo.h> 114#include <pccard/slot.h> 115#endif 116 117#if !defined(lint) 118static const char rcsid[] = 119 "$FreeBSD: head/sys/dev/wi/if_wi.c 52632 1999-10-29 17:28:09Z imp $"; 120#endif 121 122static struct wi_softc wi_softc[NWI]; 123 124#ifdef foo 125static u_int8_t wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 }; 126#endif 127 128static int wi_probe __P((struct isa_device *)); 129static int wi_attach __P((struct isa_device *)); 130#ifdef PCCARD_MODULE 131static ointhand2_t wi_intr; 132#endif 133static void wi_reset __P((struct wi_softc *)); 134static int wi_ioctl __P((struct ifnet *, u_long, caddr_t)); 135static void wi_init __P((void *)); 136static void wi_start __P((struct ifnet *)); 137static void wi_stop __P((struct wi_softc *)); 138static void wi_watchdog __P((struct ifnet *)); 139static void wi_shutdown __P((void *, int)); 140static void wi_rxeof __P((struct wi_softc *)); 141static void wi_txeof __P((struct wi_softc *, int)); 142static void wi_update_stats __P((struct wi_softc *)); 143static void wi_setmulti __P((struct wi_softc *)); 144 145static int wi_cmd __P((struct wi_softc *, int, int)); 146static int wi_read_record __P((struct wi_softc *, struct wi_ltv_gen *)); 147static int wi_write_record __P((struct wi_softc *, struct wi_ltv_gen *)); 148static int wi_read_data __P((struct wi_softc *, int, 149 int, caddr_t, int)); 150static int wi_write_data __P((struct wi_softc *, int, 151 int, caddr_t, int)); 152static int wi_seek __P((struct wi_softc *, int, int, int)); 153static int wi_alloc_nicmem __P((struct wi_softc *, int, int *)); 154static void wi_inquire __P((void *)); 155static void wi_setdef __P((struct wi_softc *, struct wi_req *)); 156static int wi_mgmt_xmit __P((struct wi_softc *, caddr_t, int)); 157 158struct isa_driver widriver = { 159 wi_probe, 160 wi_attach, 161 "wi", 162 1 163}; 164 165#if NCARD > 0 166static int wi_pccard_init __P((struct pccard_devinfo *)); 167static void wi_pccard_unload __P((struct pccard_devinfo *)); 168static int wi_pccard_intr __P((struct pccard_devinfo *)); 169 170#ifdef PCCARD_MODULE 171PCCARD_MODULE(wi, wi_pccard_init, wi_pccard_unload, 172 wi_pccard_intr, 0, net_imask); 173#else 174static struct pccard_device wi_info = { 175 "wi", 176 wi_pccard_init, 177 wi_pccard_unload, 178 wi_pccard_intr, 179 0, /* Attributes - presently unused */ 180 &net_imask /* Interrupt mask for device */ 181 /* XXX - Should this also include net_imask? */ 182}; 183 184DATA_SET(pccarddrv_set, wi_info); 185#endif 186 187/* Initialize the PCCARD. */ 188static int wi_pccard_init(sc_p) 189 struct pccard_devinfo *sc_p; 190{ 191 struct wi_softc *sc; 192 int i; 193 u_int32_t irq; 194 195 if (sc_p->isahd.id_unit >= NWI) 196 return(ENODEV); 197 198 sc = &wi_softc[sc_p->isahd.id_unit]; 199 sc->wi_gone = 0; 200 sc->wi_unit = sc_p->isahd.id_unit; 201 sc->wi_bhandle = sc_p->isahd.id_iobase; 202 sc->wi_btag = I386_BUS_SPACE_IO; 203 204 /* Make sure interrupts are disabled. */ 205 CSR_WRITE_2(sc, WI_INT_EN, 0); 206 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 207 208 /* Grr. IRQ is encoded as a bitmask. */ 209 irq = sc_p->isahd.id_irq; 210 for (i = 0; i < 32; i++) { 211 if (irq & 0x1) 212 break; 213 irq >>= 1; 214 } 215 216 /* 217 * Print a nice probe message to let the operator 218 * know something interesting is happening. 219 */ 220 printf("wi%d: <WaveLAN/IEEE 802.11> at 0x%x-0x%x irq %d on isa\n", 221 sc_p->isahd.id_unit, sc_p->isahd.id_iobase, 222 sc_p->isahd.id_iobase + WI_IOSIZ - 1, i); 223 224 if (wi_attach(&sc_p->isahd)) 225 return(ENXIO); 226 227 return(0); 228} 229 230static void wi_pccard_unload(sc_p) 231 struct pccard_devinfo *sc_p; 232{ 233 struct wi_softc *sc; 234 struct ifnet *ifp; 235 236 sc = &wi_softc[sc_p->isahd.id_unit]; 237 ifp = &sc->arpcom.ac_if; 238 239 if (sc->wi_gone) { 240 printf("wi%d: already unloaded\n", sc_p->isahd.id_unit); 241 return; 242 } 243 244 ifp->if_flags &= ~IFF_RUNNING; 245 if_down(ifp); 246 sc->wi_gone = 1; 247 printf("wi%d: unloaded\n", sc_p->isahd.id_unit); 248 249 return; 250} 251 252static int wi_pccard_intr(sc_p) 253 struct pccard_devinfo *sc_p; 254{ 255 wi_intr(sc_p->isahd.id_unit); 256 return(1); 257} 258#endif 259 260static int wi_probe(isa_dev) 261 struct isa_device *isa_dev; 262{ 263 /* 264 * The ISA WaveLAN/IEEE card is actually not an ISA card: 265 * it's a PCMCIA card plugged into a PCMCIA bridge adapter 266 * that fits into an ISA slot. Consequently, we will always 267 * be using the pccard support to probe and attach these 268 * devices, so we can never actually probe one from here. 269 */ 270 return(0); 271} 272 273static int wi_attach(isa_dev) 274 struct isa_device *isa_dev; 275{ 276 struct wi_softc *sc; 277 struct wi_ltv_macaddr mac; 278 struct wi_ltv_gen gen; 279 struct ifnet *ifp; 280 char ifname[IFNAMSIZ]; 281 282#ifdef PCCARD_MODULE 283 isa_dev->id_ointr = wi_intr; 284#endif 285 sc = &wi_softc[isa_dev->id_unit]; 286 ifp = &sc->arpcom.ac_if; 287 288 /* Reset the NIC. */ 289 wi_reset(sc); 290 291 /* Read the station address. */ 292 mac.wi_type = WI_RID_MAC_NODE; 293 mac.wi_len = 4; 294 wi_read_record(sc, (struct wi_ltv_gen *)&mac); 295 bcopy((char *)&mac.wi_mac_addr, 296 (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 297 298 printf("wi%d: Ethernet address: %6D\n", sc->wi_unit, 299 sc->arpcom.ac_enaddr, ":"); 300 301 ifp->if_softc = sc; 302 ifp->if_unit = sc->wi_unit; 303 ifp->if_name = "wi"; 304 ifp->if_mtu = ETHERMTU; 305 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 306 ifp->if_ioctl = wi_ioctl; 307 ifp->if_output = ether_output; 308 ifp->if_start = wi_start; 309 ifp->if_watchdog = wi_watchdog; 310 ifp->if_init = wi_init; 311 ifp->if_baudrate = 10000000; 312 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 313 314 bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); 315 bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name, 316 sizeof(WI_DEFAULT_NODENAME) - 1); 317 318 bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); 319 bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name, 320 sizeof(WI_DEFAULT_NETNAME) - 1); 321 322 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); 323 bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name, 324 sizeof(WI_DEFAULT_IBSS) - 1); 325 326 sc->wi_portnum = WI_DEFAULT_PORT; 327 sc->wi_ptype = WI_PORTTYPE_ADHOC; 328 sc->wi_ap_density = WI_DEFAULT_AP_DENSITY; 329 sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH; 330 sc->wi_tx_rate = WI_DEFAULT_TX_RATE; 331 sc->wi_max_data_len = WI_DEFAULT_DATALEN; 332 sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS; 333 sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED; 334 sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP; 335 336 /* 337 * Read the default channel from the NIC. This may vary 338 * depending on the country where the NIC was purchased, so 339 * we can't hard-code a default and expect it to work for 340 * everyone. 341 */ 342 gen.wi_type = WI_RID_OWN_CHNL; 343 gen.wi_len = 2; 344 wi_read_record(sc, &gen); 345 sc->wi_channel = gen.wi_val; 346 347 bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats)); 348 349 wi_init(sc); 350 wi_stop(sc); 351 352 /* 353 * If this logical interface has already been attached, 354 * don't attach it again or chaos will ensue. 355 */ 356 sprintf(ifname, "wi%d", sc->wi_unit); 357 358 if (ifunit(ifname) == NULL) { 359 callout_handle_init(&sc->wi_stat_ch); 360 /* 361 * Call MI attach routines. 362 */ 363 if_attach(ifp); 364 ether_ifattach(ifp); 365 366 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); 367 368 EVENTHANDLER_REGISTER(shutdown_post_sync, wi_shutdown, sc, 369 SHUTDOWN_PRI_DEFAULT); 370 } 371 372 return(0); 373} 374 375static void wi_rxeof(sc) 376 struct wi_softc *sc; 377{ 378 struct ifnet *ifp; 379 struct ether_header *eh; 380 struct wi_frame rx_frame; 381 struct mbuf *m; 382 int id; 383 384 ifp = &sc->arpcom.ac_if; 385 386 id = CSR_READ_2(sc, WI_RX_FID); 387 388 /* First read in the frame header */ 389 if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) { 390 ifp->if_ierrors++; 391 return; 392 } 393 394 if (rx_frame.wi_status & WI_STAT_ERRSTAT) { 395 ifp->if_ierrors++; 396 return; 397 } 398 399 MGETHDR(m, M_DONTWAIT, MT_DATA); 400 if (m == NULL) { 401 ifp->if_ierrors++; 402 return; 403 } 404 MCLGET(m, M_DONTWAIT); 405 if (!(m->m_flags & M_EXT)) { 406 m_freem(m); 407 ifp->if_ierrors++; 408 return; 409 } 410 411 eh = mtod(m, struct ether_header *); 412 m->m_pkthdr.rcvif = ifp; 413 414 if (rx_frame.wi_status == WI_STAT_1042 || 415 rx_frame.wi_status == WI_STAT_TUNNEL || 416 rx_frame.wi_status == WI_STAT_WMP_MSG) { 417 if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) { 418 printf("wi%d: oversized packet received " 419 "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit, 420 rx_frame.wi_dat_len, rx_frame.wi_status); 421 m_freem(m); 422 ifp->if_ierrors++; 423 return; 424 } 425 m->m_pkthdr.len = m->m_len = 426 rx_frame.wi_dat_len + WI_SNAPHDR_LEN; 427 428 bcopy((char *)&rx_frame.wi_addr1, 429 (char *)&eh->ether_dhost, ETHER_ADDR_LEN); 430 bcopy((char *)&rx_frame.wi_addr2, 431 (char *)&eh->ether_shost, ETHER_ADDR_LEN); 432 bcopy((char *)&rx_frame.wi_type, 433 (char *)&eh->ether_type, sizeof(u_int16_t)); 434 435 if (wi_read_data(sc, id, WI_802_11_OFFSET, 436 mtod(m, caddr_t) + sizeof(struct ether_header), 437 m->m_len + 2)) { 438 m_freem(m); 439 ifp->if_ierrors++; 440 return; 441 } 442 } else { 443 if((rx_frame.wi_dat_len + 444 sizeof(struct ether_header)) > MCLBYTES) { 445 printf("wi%d: oversized packet received " 446 "(wi_dat_len=%d, wi_status=0x%x)\n", sc->wi_unit, 447 rx_frame.wi_dat_len, rx_frame.wi_status); 448 m_freem(m); 449 ifp->if_ierrors++; 450 return; 451 } 452 m->m_pkthdr.len = m->m_len = 453 rx_frame.wi_dat_len + sizeof(struct ether_header); 454 455 if (wi_read_data(sc, id, WI_802_3_OFFSET, 456 mtod(m, caddr_t), m->m_len + 2)) { 457 m_freem(m); 458 ifp->if_ierrors++; 459 return; 460 } 461 } 462 463 ifp->if_ipackets++; 464 465 /* Handle BPF listeners. */ 466 if (ifp->if_bpf) { 467 bpf_mtap(ifp, m); 468 if (ifp->if_flags & IFF_PROMISC && 469 (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, 470 ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) { 471 m_freem(m); 472 return; 473 } 474 } 475 476 /* Receive packet. */ 477 m_adj(m, sizeof(struct ether_header)); 478 ether_input(ifp, eh, m); 479 480 return; 481} 482 483static void wi_txeof(sc, status) 484 struct wi_softc *sc; 485 int status; 486{ 487 struct ifnet *ifp; 488 489 ifp = &sc->arpcom.ac_if; 490 491 ifp->if_timer = 0; 492 ifp->if_flags &= ~IFF_OACTIVE; 493 494 if (status & WI_EV_TX_EXC) 495 ifp->if_oerrors++; 496 else 497 ifp->if_opackets++; 498 499 return; 500} 501 502void wi_inquire(xsc) 503 void *xsc; 504{ 505 struct wi_softc *sc; 506 struct ifnet *ifp; 507 508 sc = xsc; 509 ifp = &sc->arpcom.ac_if; 510 511 sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60); 512 513 /* Don't do this while we're transmitting */ 514 if (ifp->if_flags & IFF_OACTIVE) 515 return; 516 517 wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS); 518 519 return; 520} 521 522void wi_update_stats(sc) 523 struct wi_softc *sc; 524{ 525 struct wi_ltv_gen gen; 526 u_int16_t id; 527 struct ifnet *ifp; 528 u_int32_t *ptr; 529 int i; 530 u_int16_t t; 531 532 ifp = &sc->arpcom.ac_if; 533 534 id = CSR_READ_2(sc, WI_INFO_FID); 535 536 wi_read_data(sc, id, 0, (char *)&gen, 4); 537 538 if (gen.wi_type != WI_INFO_COUNTERS || 539 gen.wi_len > (sizeof(sc->wi_stats) / 4) + 1) 540 return; 541 542 ptr = (u_int32_t *)&sc->wi_stats; 543 544 for (i = 0; i < gen.wi_len - 1; i++) { 545 t = CSR_READ_2(sc, WI_DATA1); 546#ifdef WI_HERMES_STATS_WAR 547 if (t > 0xF000) 548 t = ~t & 0xFFFF; 549#endif 550 ptr[i] += t; 551 } 552 553 ifp->if_collisions = sc->wi_stats.wi_tx_single_retries + 554 sc->wi_stats.wi_tx_multi_retries + 555 sc->wi_stats.wi_tx_retry_limit; 556 557 return; 558} 559 560void wi_intr(unit) 561 int unit; 562{ 563 struct wi_softc *sc; 564 struct ifnet *ifp; 565 u_int16_t status; 566 567 sc = &wi_softc[unit]; 568 ifp = &sc->arpcom.ac_if; 569 570 if (!(ifp->if_flags & IFF_UP)) { 571 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 572 CSR_WRITE_2(sc, WI_INT_EN, 0); 573 return; 574 } 575 576 /* Disable interrupts. */ 577 CSR_WRITE_2(sc, WI_INT_EN, 0); 578 579 status = CSR_READ_2(sc, WI_EVENT_STAT); 580 CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS); 581 582 if (status & WI_EV_RX) { 583 wi_rxeof(sc); 584 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); 585 } 586 587 if (status & WI_EV_TX) { 588 wi_txeof(sc, status); 589 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX); 590 } 591 592 if (status & WI_EV_ALLOC) { 593 int id; 594 id = CSR_READ_2(sc, WI_ALLOC_FID); 595 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 596 if (id == sc->wi_tx_data_id) 597 wi_txeof(sc, status); 598 } 599 600 if (status & WI_EV_INFO) { 601 wi_update_stats(sc); 602 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); 603 } 604 605 if (status & WI_EV_TX_EXC) { 606 wi_txeof(sc, status); 607 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC); 608 } 609 610 if (status & WI_EV_INFO_DROP) { 611 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP); 612 } 613 614 /* Re-enable interrupts. */ 615 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 616 617 if (ifp->if_snd.ifq_head != NULL) 618 wi_start(ifp); 619 620 return; 621} 622 623static int wi_cmd(sc, cmd, val) 624 struct wi_softc *sc; 625 int cmd; 626 int val; 627{ 628 int i, s = 0; 629 630 CSR_WRITE_2(sc, WI_PARAM0, val); 631 CSR_WRITE_2(sc, WI_COMMAND, cmd); 632 633 for (i = 0; i < WI_TIMEOUT; i++) { 634 /* 635 * Wait for 'command complete' bit to be 636 * set in the event status register. 637 */ 638 s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD; 639 if (s) { 640 /* Ack the event and read result code. */ 641 s = CSR_READ_2(sc, WI_STATUS); 642 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD); 643#ifdef foo 644 if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK)) 645 return(EIO); 646#endif 647 if (s & WI_STAT_CMD_RESULT) 648 return(EIO); 649 break; 650 } 651 } 652 653 if (i == WI_TIMEOUT) 654 return(ETIMEDOUT); 655 656 return(0); 657} 658 659static void wi_reset(sc) 660 struct wi_softc *sc; 661{ 662 if (wi_cmd(sc, WI_CMD_INI, 0)) 663 printf("wi%d: init failed\n", sc->wi_unit); 664 CSR_WRITE_2(sc, WI_INT_EN, 0); 665 CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); 666 667 /* Calibrate timer. */ 668 WI_SETVAL(WI_RID_TICK_TIME, 8); 669 670 return; 671} 672 673/* 674 * Read an LTV record from the NIC. 675 */ 676static int wi_read_record(sc, ltv) 677 struct wi_softc *sc; 678 struct wi_ltv_gen *ltv; 679{ 680 u_int16_t *ptr; 681 int i, len, code; 682 683 /* Tell the NIC to enter record read mode. */ 684 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type)) 685 return(EIO); 686 687 /* Seek to the record. */ 688 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 689 return(EIO); 690 691 /* 692 * Read the length and record type and make sure they 693 * match what we expect (this verifies that we have enough 694 * room to hold all of the returned data). 695 */ 696 len = CSR_READ_2(sc, WI_DATA1); 697 if (len > ltv->wi_len) 698 return(ENOSPC); 699 code = CSR_READ_2(sc, WI_DATA1); 700 if (code != ltv->wi_type) 701 return(EIO); 702 703 ltv->wi_len = len; 704 ltv->wi_type = code; 705 706 /* Now read the data. */ 707 ptr = <v->wi_val; 708 for (i = 0; i < ltv->wi_len - 1; i++) 709 ptr[i] = CSR_READ_2(sc, WI_DATA1); 710 711 return(0); 712} 713 714/* 715 * Same as read, except we inject data instead of reading it. 716 */ 717static int wi_write_record(sc, ltv) 718 struct wi_softc *sc; 719 struct wi_ltv_gen *ltv; 720{ 721 u_int16_t *ptr; 722 int i; 723 724 if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) 725 return(EIO); 726 727 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len); 728 CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type); 729 730 ptr = <v->wi_val; 731 for (i = 0; i < ltv->wi_len - 1; i++) 732 CSR_WRITE_2(sc, WI_DATA1, ptr[i]); 733 734 if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type)) 735 return(EIO); 736 737 return(0); 738} 739 740static int wi_seek(sc, id, off, chan) 741 struct wi_softc *sc; 742 int id, off, chan; 743{ 744 int i; 745 int selreg, offreg; 746 747 switch (chan) { 748 case WI_BAP0: 749 selreg = WI_SEL0; 750 offreg = WI_OFF0; 751 break; 752 case WI_BAP1: 753 selreg = WI_SEL1; 754 offreg = WI_OFF1; 755 break; 756 default: 757 printf("wi%d: invalid data path: %x\n", sc->wi_unit, chan); 758 return(EIO); 759 } 760 761 CSR_WRITE_2(sc, selreg, id); 762 CSR_WRITE_2(sc, offreg, off); 763 764 for (i = 0; i < WI_TIMEOUT; i++) { 765 if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR))) 766 break; 767 } 768 769 if (i == WI_TIMEOUT) 770 return(ETIMEDOUT); 771 772 return(0); 773} 774 775static int wi_read_data(sc, id, off, buf, len) 776 struct wi_softc *sc; 777 int id, off; 778 caddr_t buf; 779 int len; 780{ 781 int i; 782 u_int16_t *ptr; 783 784 if (wi_seek(sc, id, off, WI_BAP1)) 785 return(EIO); 786 787 ptr = (u_int16_t *)buf; 788 for (i = 0; i < len / 2; i++) 789 ptr[i] = CSR_READ_2(sc, WI_DATA1); 790 791 return(0); 792} 793 794/* 795 * According to the comments in the HCF Light code, there is a bug in 796 * the Hermes (or possibly in certain Hermes firmware revisions) where 797 * the chip's internal autoincrement counter gets thrown off during 798 * data writes: the autoincrement is missed, causing one data word to 799 * be overwritten and subsequent words to be written to the wrong memory 800 * locations. The end result is that we could end up transmitting bogus 801 * frames without realizing it. The workaround for this is to write a 802 * couple of extra guard words after the end of the transfer, then 803 * attempt to read then back. If we fail to locate the guard words where 804 * we expect them, we preform the transfer over again. 805 */ 806static int wi_write_data(sc, id, off, buf, len) 807 struct wi_softc *sc; 808 int id, off; 809 caddr_t buf; 810 int len; 811{ 812 int i; 813 u_int16_t *ptr; 814 815#ifdef WI_HERMES_AUTOINC_WAR 816again: 817#endif 818 819 if (wi_seek(sc, id, off, WI_BAP0)) 820 return(EIO); 821 822 ptr = (u_int16_t *)buf; 823 for (i = 0; i < (len / 2); i++) 824 CSR_WRITE_2(sc, WI_DATA0, ptr[i]); 825 826#ifdef WI_HERMES_AUTOINC_WAR 827 CSR_WRITE_2(sc, WI_DATA0, 0x1234); 828 CSR_WRITE_2(sc, WI_DATA0, 0x5678); 829 830 if (wi_seek(sc, id, off + len, WI_BAP0)) 831 return(EIO); 832 833 if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || 834 CSR_READ_2(sc, WI_DATA0) != 0x5678) 835 goto again; 836#endif 837 838 return(0); 839} 840 841/* 842 * Allocate a region of memory inside the NIC and zero 843 * it out. 844 */ 845static int wi_alloc_nicmem(sc, len, id) 846 struct wi_softc *sc; 847 int len; 848 int *id; 849{ 850 int i; 851 852 if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) { 853 printf("wi%d: failed to allocate %d bytes on NIC\n", 854 sc->wi_unit, len); 855 return(ENOMEM); 856 } 857 858 for (i = 0; i < WI_TIMEOUT; i++) { 859 if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) 860 break; 861 } 862 863 if (i == WI_TIMEOUT) 864 return(ETIMEDOUT); 865 866 CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC); 867 *id = CSR_READ_2(sc, WI_ALLOC_FID); 868 869 if (wi_seek(sc, *id, 0, WI_BAP0)) 870 return(EIO); 871 872 for (i = 0; i < len / 2; i++) 873 CSR_WRITE_2(sc, WI_DATA0, 0); 874 875 return(0); 876} 877 878static void wi_setmulti(sc) 879 struct wi_softc *sc; 880{ 881 struct ifnet *ifp; 882 int i = 0; 883 struct ifmultiaddr *ifma; 884 struct wi_ltv_mcast mcast; 885 886 ifp = &sc->arpcom.ac_if; 887 888 bzero((char *)&mcast, sizeof(mcast)); 889 890 mcast.wi_type = WI_RID_MCAST; 891 mcast.wi_len = (3 * 16) + 1; 892 893 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 894 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 895 return; 896 } 897 898 for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; 899 ifma = ifma->ifma_link.le_next) { 900 if (ifma->ifma_addr->sa_family != AF_LINK) 901 continue; 902 if (i < 16) { 903 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 904 (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN); 905 i++; 906 } else { 907 bzero((char *)&mcast, sizeof(mcast)); 908 break; 909 } 910 } 911 912 mcast.wi_len = (i * 3) + 1; 913 wi_write_record(sc, (struct wi_ltv_gen *)&mcast); 914 915 return; 916} 917 918static void wi_setdef(sc, wreq) 919 struct wi_softc *sc; 920 struct wi_req *wreq; 921{ 922 struct sockaddr_dl *sdl; 923 struct ifaddr *ifa; 924 struct ifnet *ifp; 925 926 ifp = &sc->arpcom.ac_if; 927 928 switch(wreq->wi_type) { 929 case WI_RID_MAC_NODE: 930 ifa = ifnet_addrs[ifp->if_index - 1]; 931 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 932 bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr, 933 ETHER_ADDR_LEN); 934 bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN); 935 break; 936 case WI_RID_PORTTYPE: 937 sc->wi_ptype = wreq->wi_val[0]; 938 break; 939 case WI_RID_TX_RATE: 940 sc->wi_tx_rate = wreq->wi_val[0]; 941 break; 942 case WI_RID_MAX_DATALEN: 943 sc->wi_max_data_len = wreq->wi_val[0]; 944 break; 945 case WI_RID_RTS_THRESH: 946 sc->wi_rts_thresh = wreq->wi_val[0]; 947 break; 948 case WI_RID_SYSTEM_SCALE: 949 sc->wi_ap_density = wreq->wi_val[0]; 950 break; 951 case WI_RID_CREATE_IBSS: 952 sc->wi_create_ibss = wreq->wi_val[0]; 953 break; 954 case WI_RID_OWN_CHNL: 955 sc->wi_channel = wreq->wi_val[0]; 956 break; 957 case WI_RID_NODENAME: 958 bzero(sc->wi_node_name, sizeof(sc->wi_node_name)); 959 bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30); 960 break; 961 case WI_RID_DESIRED_SSID: 962 bzero(sc->wi_net_name, sizeof(sc->wi_net_name)); 963 bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30); 964 break; 965 case WI_RID_OWN_SSID: 966 bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name)); 967 bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30); 968 break; 969 case WI_RID_PM_ENABLED: 970 sc->wi_pm_enabled = wreq->wi_val[0]; 971 break; 972 case WI_RID_MAX_SLEEP: 973 sc->wi_max_sleep = wreq->wi_val[0]; 974 break; 975 default: 976 break; 977 } 978 979 /* Reinitialize WaveLAN. */ 980 wi_init(sc); 981 982 return; 983} 984 985static int wi_ioctl(ifp, command, data) 986 struct ifnet *ifp; 987 u_long command; 988 caddr_t data; 989{ 990 int s, error = 0; 991 struct wi_softc *sc; 992 struct wi_req wreq; 993 struct ifreq *ifr; 994 995 s = splimp(); 996 997 sc = ifp->if_softc; 998 ifr = (struct ifreq *)data; 999 1000 if (sc->wi_gone) 1001 return(ENODEV); 1002 1003 switch(command) { 1004 case SIOCSIFADDR: 1005 case SIOCGIFADDR: 1006 case SIOCSIFMTU: 1007 error = ether_ioctl(ifp, command, data); 1008 break; 1009 case SIOCSIFFLAGS: 1010 if (ifp->if_flags & IFF_UP) { 1011 if (ifp->if_flags & IFF_RUNNING && 1012 ifp->if_flags & IFF_PROMISC && 1013 !(sc->wi_if_flags & IFF_PROMISC)) { 1014 WI_SETVAL(WI_RID_PROMISC, 1); 1015 } else if (ifp->if_flags & IFF_RUNNING && 1016 !(ifp->if_flags & IFF_PROMISC) && 1017 sc->wi_if_flags & IFF_PROMISC) { 1018 WI_SETVAL(WI_RID_PROMISC, 0); 1019 } else 1020 wi_init(sc); 1021 } else { 1022 if (ifp->if_flags & IFF_RUNNING) { 1023 wi_stop(sc); 1024 } 1025 } 1026 sc->wi_if_flags = ifp->if_flags; 1027 error = 0; 1028 break; 1029 case SIOCADDMULTI: 1030 case SIOCDELMULTI: 1031 wi_setmulti(sc); 1032 error = 0; 1033 break; 1034 case SIOCGWAVELAN: 1035 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1036 if (error) 1037 break; 1038 if (wreq.wi_type == WI_RID_IFACE_STATS) { 1039 bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val, 1040 sizeof(sc->wi_stats)); 1041 wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1; 1042 } else { 1043 if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { 1044 error = EINVAL; 1045 break; 1046 } 1047 } 1048 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 1049 break; 1050 case SIOCSWAVELAN: 1051 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 1052 if (error) 1053 break; 1054 if (wreq.wi_type == WI_RID_IFACE_STATS) { 1055 error = EINVAL; 1056 break; 1057 } else if (wreq.wi_type == WI_RID_MGMT_XMIT) { 1058 error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val, 1059 wreq.wi_len); 1060 } else { 1061 error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); 1062 if (!error) 1063 wi_setdef(sc, &wreq); 1064 } 1065 break; 1066 default: 1067 error = EINVAL; 1068 break; 1069 } 1070 1071 splx(s); 1072 1073 return(error); 1074} 1075 1076static void wi_init(xsc) 1077 void *xsc; 1078{ 1079 struct wi_softc *sc = xsc; 1080 struct ifnet *ifp = &sc->arpcom.ac_if; 1081 int s; 1082 struct wi_ltv_macaddr mac; 1083 int id = 0; 1084 1085 if (sc->wi_gone) 1086 return; 1087 1088 s = splimp(); 1089 1090 if (ifp->if_flags & IFF_RUNNING) 1091 wi_stop(sc); 1092 1093 wi_reset(sc); 1094 1095 /* Program max data length. */ 1096 WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len); 1097 1098 /* Enable/disable IBSS creation. */ 1099 WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss); 1100 1101 /* Set the port type. */ 1102 WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype); 1103 1104 /* Program the RTS/CTS threshold. */ 1105 WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh); 1106 1107 /* Program the TX rate */ 1108 WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate); 1109 1110 /* Access point density */ 1111 WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density); 1112 1113 /* Power Management Enabled */ 1114 WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled); 1115 1116 /* Power Managment Max Sleep */ 1117 WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep); 1118 1119 /* Specify the IBSS name */ 1120 WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name); 1121 1122 /* Specify the network name */ 1123 WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name); 1124 1125 /* Specify the frequency to use */ 1126 WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel); 1127 1128 /* Program the nodename. */ 1129 WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name); 1130 1131 /* Set our MAC address. */ 1132 mac.wi_len = 4; 1133 mac.wi_type = WI_RID_MAC_NODE; 1134 bcopy((char *)&sc->arpcom.ac_enaddr, 1135 (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN); 1136 wi_write_record(sc, (struct wi_ltv_gen *)&mac); 1137 1138 /* Initialize promisc mode. */ 1139 if (ifp->if_flags & IFF_PROMISC) { 1140 WI_SETVAL(WI_RID_PROMISC, 1); 1141 } else { 1142 WI_SETVAL(WI_RID_PROMISC, 0); 1143 } 1144 1145 /* Set multicast filter. */ 1146 wi_setmulti(sc); 1147 1148 /* Enable desired port */ 1149 wi_cmd(sc, WI_CMD_ENABLE|sc->wi_portnum, 0); 1150 1151 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id)) 1152 printf("wi%d: tx buffer allocation failed\n", sc->wi_unit); 1153 sc->wi_tx_data_id = id; 1154 1155 if (wi_alloc_nicmem(sc, 1518 + sizeof(struct wi_frame) + 8, &id)) 1156 printf("wi%d: mgmt. buffer allocation failed\n", sc->wi_unit); 1157 sc->wi_tx_mgmt_id = id; 1158 1159 /* enable interrupts */ 1160 CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); 1161 1162 splx(s); 1163 1164 ifp->if_flags |= IFF_RUNNING; 1165 ifp->if_flags &= ~IFF_OACTIVE; 1166 1167 sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60); 1168 1169 return; 1170} 1171 1172static void wi_start(ifp) 1173 struct ifnet *ifp; 1174{ 1175 struct wi_softc *sc; 1176 struct mbuf *m0; 1177 struct wi_frame tx_frame; 1178 struct ether_header *eh; 1179 int id; 1180 1181 sc = ifp->if_softc; 1182 1183 if (sc->wi_gone) 1184 return; 1185 1186 if (ifp->if_flags & IFF_OACTIVE) 1187 return; 1188 1189 IF_DEQUEUE(&ifp->if_snd, m0); 1190 if (m0 == NULL) 1191 return; 1192 1193 bzero((char *)&tx_frame, sizeof(tx_frame)); 1194 id = sc->wi_tx_data_id; 1195 eh = mtod(m0, struct ether_header *); 1196 1197 /* 1198 * Use RFC1042 encoding for IP and ARP datagrams, 1199 * 802.3 for anything else. 1200 */ 1201 if (ntohs(eh->ether_type) == ETHERTYPE_IP || 1202 ntohs(eh->ether_type) == ETHERTYPE_ARP || 1203 ntohs(eh->ether_type) == ETHERTYPE_REVARP) { 1204 bcopy((char *)&eh->ether_dhost, 1205 (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN); 1206 bcopy((char *)&eh->ether_shost, 1207 (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN); 1208 bcopy((char *)&eh->ether_dhost, 1209 (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN); 1210 bcopy((char *)&eh->ether_shost, 1211 (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN); 1212 1213 tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN; 1214 tx_frame.wi_frame_ctl = WI_FTYPE_DATA; 1215 tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0); 1216 tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1); 1217 tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN); 1218 tx_frame.wi_type = eh->ether_type; 1219 1220 m_copydata(m0, sizeof(struct ether_header), 1221 m0->m_pkthdr.len - sizeof(struct ether_header), 1222 (caddr_t)&sc->wi_txbuf); 1223 1224 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 1225 sizeof(struct wi_frame)); 1226 wi_write_data(sc, id, WI_802_11_OFFSET, (caddr_t)&sc->wi_txbuf, 1227 (m0->m_pkthdr.len - sizeof(struct ether_header)) + 2); 1228 } else { 1229 tx_frame.wi_dat_len = m0->m_pkthdr.len; 1230 1231 m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&sc->wi_txbuf); 1232 1233 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, 1234 sizeof(struct wi_frame)); 1235 wi_write_data(sc, id, WI_802_3_OFFSET, (caddr_t)&sc->wi_txbuf, 1236 m0->m_pkthdr.len + 2); 1237 } 1238 1239 /* 1240 * If there's a BPF listner, bounce a copy of 1241 * this frame to him. 1242 */ 1243 if (ifp->if_bpf) 1244 bpf_mtap(ifp, m0); 1245 1246 m_freem(m0); 1247 1248 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) 1249 printf("wi%d: xmit failed\n", sc->wi_unit); 1250 1251 ifp->if_flags |= IFF_OACTIVE; 1252 1253 /* 1254 * Set a timeout in case the chip goes out to lunch. 1255 */ 1256 ifp->if_timer = 5; 1257 1258 return; 1259} 1260 1261static int wi_mgmt_xmit(sc, data, len) 1262 struct wi_softc *sc; 1263 caddr_t data; 1264 int len; 1265{ 1266 struct wi_frame tx_frame; 1267 int id; 1268 struct wi_80211_hdr *hdr; 1269 caddr_t dptr; 1270 1271 if (sc->wi_gone) 1272 return(ENODEV); 1273 1274 hdr = (struct wi_80211_hdr *)data; 1275 dptr = data + sizeof(struct wi_80211_hdr); 1276 1277 bzero((char *)&tx_frame, sizeof(tx_frame)); 1278 id = sc->wi_tx_mgmt_id; 1279 1280 bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl, 1281 sizeof(struct wi_80211_hdr)); 1282 1283 tx_frame.wi_dat_len = len - WI_SNAPHDR_LEN; 1284 tx_frame.wi_len = htons(len - WI_SNAPHDR_LEN); 1285 1286 wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame)); 1287 wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr, 1288 (len - sizeof(struct wi_80211_hdr)) + 2); 1289 1290 if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) { 1291 printf("wi%d: xmit failed\n", sc->wi_unit); 1292 return(EIO); 1293 } 1294 1295 return(0); 1296} 1297 1298static void wi_stop(sc) 1299 struct wi_softc *sc; 1300{ 1301 struct ifnet *ifp; 1302 1303 if (sc->wi_gone) 1304 return; 1305 1306 ifp = &sc->arpcom.ac_if; 1307 1308 CSR_WRITE_2(sc, WI_INT_EN, 0); 1309 wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0); 1310 1311 untimeout(wi_inquire, sc, sc->wi_stat_ch); 1312 1313 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1314 1315 return; 1316} 1317 1318static void wi_watchdog(ifp) 1319 struct ifnet *ifp; 1320{ 1321 struct wi_softc *sc; 1322 1323 sc = ifp->if_softc; 1324 1325 printf("wi%d: device timeout\n", sc->wi_unit); 1326 1327 wi_init(sc); 1328 1329 ifp->if_oerrors++; 1330 1331 return; 1332} 1333 1334static void wi_shutdown(arg, howto) 1335 void *arg; 1336 int howto; 1337{ 1338 struct wi_softc *sc; 1339 1340 sc = arg; 1341 wi_stop(sc); 1342 1343 return; 1344} 1345