1 /* $NetBSD: if_el.c,v 1.65 2001/11/13 08:01:17 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted 5 * to use, copy, modify and distribute this software provided that both 6 * the copyright notice and this permission notice appear in all copies 7 * of the software, derivative works or modified versions, and any 8 * portions thereof. 9 */ 10 11 /* 12 * 3COM Etherlink 3C501 device driver 13 */ 14 15 /* 16 * Bugs/possible improvements: 17 * - Does not currently support DMA 18 * - Does not currently support multicasts 19 */ 20 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: if_el.c,v 1.65 2001/11/13 08:01:17 lukem Exp $"); 23 24 #include "opt_inet.h" 25 #include "opt_ns.h" 26 #include "bpfilter.h" 27 #include "rnd.h" 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/errno.h> 32 #include <sys/ioctl.h> 33 #include <sys/mbuf.h> 34 #include <sys/socket.h> 35 #include <sys/syslog.h> 36 #include <sys/device.h> 37 #if NRND > 0 38 #include <sys/rnd.h> 39 #endif 40 41 #include <net/if.h> 42 #include <net/if_dl.h> 43 #include <net/if_types.h> 44 45 #include <net/if_ether.h> 46 47 #ifdef INET 48 #include <netinet/in.h> 49 #include <netinet/in_systm.h> 50 #include <netinet/in_var.h> 51 #include <netinet/ip.h> 52 #include <netinet/if_inarp.h> 53 #endif 54 55 #ifdef NS 56 #include <netns/ns.h> 57 #include <netns/ns_if.h> 58 #endif 59 60 #if NBPFILTER > 0 61 #include <net/bpf.h> 62 #include <net/bpfdesc.h> 63 #endif 64 65 #include <machine/cpu.h> 66 #include <machine/intr.h> 67 #include <machine/bus.h> 68 69 #include <dev/isa/isavar.h> 70 #include <dev/isa/if_elreg.h> 71 72 /* for debugging convenience */ 73 #ifdef EL_DEBUG 74 #define DPRINTF(x) printf x 75 #else 76 #define DPRINTF(x) 77 #endif 78 79 /* 80 * per-line info and status 81 */ 82 struct el_softc { 83 struct device sc_dev; 84 void *sc_ih; 85 86 struct ethercom sc_ethercom; /* ethernet common */ 87 bus_space_tag_t sc_iot; /* bus space identifier */ 88 bus_space_handle_t sc_ioh; /* i/o handle */ 89 90 #if NRND > 0 91 rndsource_element_t rnd_source; 92 #endif 93 }; 94 95 /* 96 * prototypes 97 */ 98 int elintr __P((void *)); 99 void elinit __P((struct el_softc *)); 100 int elioctl __P((struct ifnet *, u_long, caddr_t)); 101 void elstart __P((struct ifnet *)); 102 void elwatchdog __P((struct ifnet *)); 103 void elreset __P((struct el_softc *)); 104 void elstop __P((struct el_softc *)); 105 static int el_xmit __P((struct el_softc *)); 106 void elread __P((struct el_softc *, int)); 107 struct mbuf *elget __P((struct el_softc *sc, int)); 108 static inline void el_hardreset __P((struct el_softc *)); 109 110 int elprobe __P((struct device *, struct cfdata *, void *)); 111 void elattach __P((struct device *, struct device *, void *)); 112 113 struct cfattach el_ca = { 114 sizeof(struct el_softc), elprobe, elattach 115 }; 116 117 /* 118 * Probe routine. 119 * 120 * See if the card is there and at the right place. 121 * (XXX - cgd -- needs help) 122 */ 123 int 124 elprobe(parent, match, aux) 125 struct device *parent; 126 struct cfdata *match; 127 void *aux; 128 { 129 struct isa_attach_args *ia = aux; 130 bus_space_tag_t iot = ia->ia_iot; 131 bus_space_handle_t ioh; 132 int iobase = ia->ia_iobase; 133 u_int8_t station_addr[ETHER_ADDR_LEN]; 134 u_int8_t i; 135 int rval; 136 137 rval = 0; 138 139 /* First check the base. */ 140 if (iobase < 0x200 || iobase > 0x3f0) 141 return 0; 142 143 /* Map i/o space. */ 144 if (bus_space_map(iot, iobase, 16, 0, &ioh)) 145 return 0; 146 147 /* 148 * Now attempt to grab the station address from the PROM and see if it 149 * contains the 3com vendor code. 150 */ 151 DPRINTF(("Probing 3c501 at 0x%x...\n", iobase)); 152 153 /* Reset the board. */ 154 DPRINTF(("Resetting board...\n")); 155 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 156 delay(5); 157 bus_space_write_1(iot, ioh, EL_AC, 0); 158 159 /* Now read the address. */ 160 DPRINTF(("Reading station address...\n")); 161 for (i = 0; i < ETHER_ADDR_LEN; i++) { 162 bus_space_write_1(iot, ioh, EL_GPBL, i); 163 station_addr[i] = bus_space_read_1(iot, ioh, EL_EAW); 164 } 165 DPRINTF(("Address is %s\n", ether_sprintf(station_addr))); 166 167 /* 168 * If the vendor code is ok, return a 1. We'll assume that whoever 169 * configured this system is right about the IRQ. 170 */ 171 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 || 172 station_addr[2] != 0x8c) { 173 DPRINTF(("Bad vendor code.\n")); 174 goto out; 175 } 176 DPRINTF(("Vendor code ok.\n")); 177 178 ia->ia_iosize = 16; 179 ia->ia_msize = 0; 180 rval = 1; 181 182 out: 183 bus_space_unmap(iot, ioh, 16); 184 return rval; 185 } 186 187 /* 188 * Attach the interface to the kernel data structures. By the time this is 189 * called, we know that the card exists at the given I/O address. We still 190 * assume that the IRQ given is correct. 191 */ 192 void 193 elattach(parent, self, aux) 194 struct device *parent, *self; 195 void *aux; 196 { 197 struct el_softc *sc = (void *)self; 198 struct isa_attach_args *ia = aux; 199 bus_space_tag_t iot = ia->ia_iot; 200 bus_space_handle_t ioh; 201 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 202 u_int8_t myaddr[ETHER_ADDR_LEN]; 203 u_int8_t i; 204 205 printf("\n"); 206 207 DPRINTF(("Attaching %s...\n", sc->sc_dev.dv_xname)); 208 209 /* Map i/o space. */ 210 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) { 211 printf("%s: can't map i/o space\n", self->dv_xname); 212 return; 213 } 214 215 sc->sc_iot = iot; 216 sc->sc_ioh = ioh; 217 218 /* Reset the board. */ 219 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 220 delay(5); 221 bus_space_write_1(iot, ioh, EL_AC, 0); 222 223 /* Now read the address. */ 224 for (i = 0; i < ETHER_ADDR_LEN; i++) { 225 bus_space_write_1(iot, ioh, EL_GPBL, i); 226 myaddr[i] = bus_space_read_1(iot, ioh, EL_EAW); 227 } 228 229 /* Stop the board. */ 230 elstop(sc); 231 232 /* Initialize ifnet structure. */ 233 strcpy(ifp->if_xname, sc->sc_dev.dv_xname); 234 ifp->if_softc = sc; 235 ifp->if_start = elstart; 236 ifp->if_ioctl = elioctl; 237 ifp->if_watchdog = elwatchdog; 238 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 239 IFQ_SET_READY(&ifp->if_snd); 240 241 /* Now we can attach the interface. */ 242 DPRINTF(("Attaching interface...\n")); 243 if_attach(ifp); 244 ether_ifattach(ifp, myaddr); 245 246 /* Print out some information for the user. */ 247 printf("%s: address %s\n", self->dv_xname, ether_sprintf(myaddr)); 248 249 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 250 IPL_NET, elintr, sc); 251 252 #if NRND > 0 253 DPRINTF(("Attaching to random...\n")); 254 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 255 RND_TYPE_NET, 0); 256 #endif 257 258 DPRINTF(("elattach() finished.\n")); 259 } 260 261 /* 262 * Reset interface. 263 */ 264 void 265 elreset(sc) 266 struct el_softc *sc; 267 { 268 int s; 269 270 DPRINTF(("elreset()\n")); 271 s = splnet(); 272 elstop(sc); 273 elinit(sc); 274 splx(s); 275 } 276 277 /* 278 * Stop interface. 279 */ 280 void 281 elstop(sc) 282 struct el_softc *sc; 283 { 284 285 bus_space_write_1(sc->sc_iot, sc->sc_ioh, EL_AC, 0); 286 } 287 288 /* 289 * Do a hardware reset of the board, and upload the ethernet address again in 290 * case the board forgets. 291 */ 292 static inline void 293 el_hardreset(sc) 294 struct el_softc *sc; 295 { 296 bus_space_tag_t iot = sc->sc_iot; 297 bus_space_handle_t ioh = sc->sc_ioh; 298 int i; 299 300 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 301 delay(5); 302 bus_space_write_1(iot, ioh, EL_AC, 0); 303 304 for (i = 0; i < ETHER_ADDR_LEN; i++) 305 bus_space_write_1(iot, ioh, i, 306 LLADDR(sc->sc_ethercom.ec_if.if_sadl)[i]); 307 } 308 309 /* 310 * Initialize interface. 311 */ 312 void 313 elinit(sc) 314 struct el_softc *sc; 315 { 316 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 317 bus_space_tag_t iot = sc->sc_iot; 318 bus_space_handle_t ioh = sc->sc_ioh; 319 320 /* First, reset the board. */ 321 el_hardreset(sc); 322 323 /* Configure rx. */ 324 DPRINTF(("Configuring rx...\n")); 325 if (ifp->if_flags & IFF_PROMISC) 326 bus_space_write_1(iot, ioh, EL_RXC, 327 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 328 EL_RXC_DOFLOW | EL_RXC_PROMISC); 329 else 330 bus_space_write_1(iot, ioh, EL_RXC, 331 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 332 EL_RXC_DOFLOW | EL_RXC_ABROAD); 333 bus_space_write_1(iot, ioh, EL_RBC, 0); 334 335 /* Configure TX. */ 336 DPRINTF(("Configuring tx...\n")); 337 bus_space_write_1(iot, ioh, EL_TXC, 0); 338 339 /* Start reception. */ 340 DPRINTF(("Starting reception...\n")); 341 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 342 343 /* Set flags appropriately. */ 344 ifp->if_flags |= IFF_RUNNING; 345 ifp->if_flags &= ~IFF_OACTIVE; 346 347 /* And start output. */ 348 elstart(ifp); 349 } 350 351 /* 352 * Start output on interface. Get datagrams from the queue and output them, 353 * giving the receiver a chance between datagrams. Call only from splnet or 354 * interrupt level! 355 */ 356 void 357 elstart(ifp) 358 struct ifnet *ifp; 359 { 360 struct el_softc *sc = ifp->if_softc; 361 bus_space_tag_t iot = sc->sc_iot; 362 bus_space_handle_t ioh = sc->sc_ioh; 363 struct mbuf *m, *m0; 364 int s, i, off, retries; 365 366 DPRINTF(("elstart()...\n")); 367 s = splnet(); 368 369 /* Don't do anything if output is active. */ 370 if ((ifp->if_flags & IFF_OACTIVE) != 0) { 371 splx(s); 372 return; 373 } 374 375 ifp->if_flags |= IFF_OACTIVE; 376 377 /* 378 * The main loop. They warned me against endless loops, but would I 379 * listen? NOOO.... 380 */ 381 for (;;) { 382 /* Dequeue the next datagram. */ 383 IFQ_DEQUEUE(&ifp->if_snd, m0); 384 385 /* If there's nothing to send, return. */ 386 if (m0 == 0) 387 break; 388 389 #if NBPFILTER > 0 390 /* Give the packet to the bpf, if any. */ 391 if (ifp->if_bpf) 392 bpf_mtap(ifp->if_bpf, m0); 393 #endif 394 395 /* Disable the receiver. */ 396 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); 397 bus_space_write_1(iot, ioh, EL_RBC, 0); 398 399 /* Transfer datagram to board. */ 400 DPRINTF(("el: xfr pkt length=%d...\n", m0->m_pkthdr.len)); 401 off = EL_BUFSIZ - max(m0->m_pkthdr.len, 402 ETHER_MIN_LEN - ETHER_CRC_LEN); 403 #ifdef DIAGNOSTIC 404 if ((off & 0xffff) != off) 405 printf("%s: bogus off 0x%x\n", 406 sc->sc_dev.dv_xname, off); 407 #endif 408 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff); 409 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff); 410 411 /* Copy the datagram to the buffer. */ 412 for (m = m0; m != 0; m = m->m_next) 413 bus_space_write_multi_1(iot, ioh, EL_BUF, 414 mtod(m, u_int8_t *), m->m_len); 415 416 m_freem(m0); 417 418 /* Now transmit the datagram. */ 419 retries = 0; 420 for (;;) { 421 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff); 422 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff); 423 if (el_xmit(sc)) { 424 ifp->if_oerrors++; 425 break; 426 } 427 /* Check out status. */ 428 i = bus_space_read_1(iot, ioh, EL_TXS); 429 DPRINTF(("tx status=0x%x\n", i)); 430 if ((i & EL_TXS_READY) == 0) { 431 DPRINTF(("el: err txs=%x\n", i)); 432 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) { 433 ifp->if_collisions++; 434 if ((i & EL_TXC_DCOLL16) == 0 && 435 retries < 15) { 436 retries++; 437 bus_space_write_1(iot, ioh, 438 EL_AC, EL_AC_HOST); 439 } 440 } else { 441 ifp->if_oerrors++; 442 break; 443 } 444 } else { 445 ifp->if_opackets++; 446 break; 447 } 448 } 449 450 /* 451 * Now give the card a chance to receive. 452 * Gotta love 3c501s... 453 */ 454 (void)bus_space_read_1(iot, ioh, EL_AS); 455 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 456 splx(s); 457 /* Interrupt here. */ 458 s = splnet(); 459 } 460 461 (void)bus_space_read_1(iot, ioh, EL_AS); 462 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 463 ifp->if_flags &= ~IFF_OACTIVE; 464 splx(s); 465 } 466 467 /* 468 * This function actually attempts to transmit a datagram downloaded to the 469 * board. Call at splnet or interrupt, after downloading data! Returns 0 on 470 * success, non-0 on failure. 471 */ 472 static int 473 el_xmit(sc) 474 struct el_softc *sc; 475 { 476 bus_space_tag_t iot = sc->sc_iot; 477 bus_space_handle_t ioh = sc->sc_ioh; 478 int i; 479 480 /* 481 * XXX 482 * This busy-waits for the tx completion. Can we get an interrupt 483 * instead? 484 */ 485 486 DPRINTF(("el: xmit...")); 487 bus_space_write_1(iot, ioh, EL_AC, EL_AC_TXFRX); 488 i = 20000; 489 while ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_TXBUSY) && (i > 0)) 490 i--; 491 if (i == 0) { 492 DPRINTF(("tx not ready\n")); 493 return -1; 494 } 495 DPRINTF(("%d cycles.\n", 20000 - i)); 496 return 0; 497 } 498 499 /* 500 * Controller interrupt. 501 */ 502 int 503 elintr(arg) 504 void *arg; 505 { 506 struct el_softc *sc = arg; 507 bus_space_tag_t iot = sc->sc_iot; 508 bus_space_handle_t ioh = sc->sc_ioh; 509 u_int8_t rxstat; 510 int len; 511 512 DPRINTF(("elintr: ")); 513 514 /* Check board status. */ 515 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) { 516 (void)bus_space_read_1(iot, ioh, EL_RXC); 517 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 518 return 0; 519 } 520 521 for (;;) { 522 rxstat = bus_space_read_1(iot, ioh, EL_RXS); 523 if (rxstat & EL_RXS_STALE) 524 break; 525 526 /* If there's an overflow, reinit the board. */ 527 if ((rxstat & EL_RXS_NOFLOW) == 0) { 528 DPRINTF(("overflow.\n")); 529 el_hardreset(sc); 530 /* Put board back into receive mode. */ 531 if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) 532 bus_space_write_1(iot, ioh, EL_RXC, 533 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 534 EL_RXC_DOFLOW | EL_RXC_PROMISC); 535 else 536 bus_space_write_1(iot, ioh, EL_RXC, 537 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 538 EL_RXC_DOFLOW | EL_RXC_ABROAD); 539 (void)bus_space_read_1(iot, ioh, EL_AS); 540 bus_space_write_1(iot, ioh, EL_RBC, 0); 541 break; 542 } 543 544 /* Incoming packet. */ 545 len = bus_space_read_1(iot, ioh, EL_RBL); 546 len |= bus_space_read_1(iot, ioh, EL_RBH) << 8; 547 DPRINTF(("receive len=%d rxstat=%x ", len, rxstat)); 548 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); 549 550 /* Pass data up to upper levels. */ 551 elread(sc, len); 552 553 /* Is there another packet? */ 554 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) 555 break; 556 557 #if NRND > 0 558 rnd_add_uint32(&sc->rnd_source, rxstat); 559 #endif 560 561 DPRINTF(("<rescan> ")); 562 } 563 564 (void)bus_space_read_1(iot, ioh, EL_RXC); 565 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 566 return 1; 567 } 568 569 /* 570 * Pass a packet to the higher levels. 571 */ 572 void 573 elread(sc, len) 574 struct el_softc *sc; 575 int len; 576 { 577 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 578 struct mbuf *m; 579 580 if (len <= sizeof(struct ether_header) || 581 len > ETHER_MAX_LEN) { 582 printf("%s: invalid packet size %d; dropping\n", 583 sc->sc_dev.dv_xname, len); 584 ifp->if_ierrors++; 585 return; 586 } 587 588 /* Pull packet off interface. */ 589 m = elget(sc, len); 590 if (m == 0) { 591 ifp->if_ierrors++; 592 return; 593 } 594 595 ifp->if_ipackets++; 596 597 #if NBPFILTER > 0 598 /* 599 * Check if there's a BPF listener on this interface. 600 * If so, hand off the raw packet to BPF. 601 */ 602 if (ifp->if_bpf) 603 bpf_mtap(ifp->if_bpf, m); 604 #endif 605 606 (*ifp->if_input)(ifp, m); 607 } 608 609 /* 610 * Pull read data off a interface. Len is length of data, with local net 611 * header stripped. We copy the data into mbufs. When full cluster sized 612 * units are present we copy into clusters. 613 */ 614 struct mbuf * 615 elget(sc, totlen) 616 struct el_softc *sc; 617 int totlen; 618 { 619 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 620 bus_space_tag_t iot = sc->sc_iot; 621 bus_space_handle_t ioh = sc->sc_ioh; 622 struct mbuf *m, *m0, *newm; 623 int len; 624 625 MGETHDR(m0, M_DONTWAIT, MT_DATA); 626 if (m0 == 0) 627 return (0); 628 m0->m_pkthdr.rcvif = ifp; 629 m0->m_pkthdr.len = totlen; 630 len = MHLEN; 631 m = m0; 632 633 bus_space_write_1(iot, ioh, EL_GPBL, 0); 634 bus_space_write_1(iot, ioh, EL_GPBH, 0); 635 636 while (totlen > 0) { 637 if (totlen >= MINCLSIZE) { 638 MCLGET(m, M_DONTWAIT); 639 if ((m->m_flags & M_EXT) == 0) 640 goto bad; 641 len = MCLBYTES; 642 } 643 644 m->m_len = len = min(totlen, len); 645 bus_space_read_multi_1(iot, ioh, EL_BUF, mtod(m, u_int8_t *), len); 646 647 totlen -= len; 648 if (totlen > 0) { 649 MGET(newm, M_DONTWAIT, MT_DATA); 650 if (newm == 0) 651 goto bad; 652 len = MLEN; 653 m = m->m_next = newm; 654 } 655 } 656 657 bus_space_write_1(iot, ioh, EL_RBC, 0); 658 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RX); 659 660 return (m0); 661 662 bad: 663 m_freem(m0); 664 return (0); 665 } 666 667 /* 668 * Process an ioctl request. This code needs some work - it looks pretty ugly. 669 */ 670 int 671 elioctl(ifp, cmd, data) 672 struct ifnet *ifp; 673 u_long cmd; 674 caddr_t data; 675 { 676 struct el_softc *sc = ifp->if_softc; 677 struct ifaddr *ifa = (struct ifaddr *)data; 678 int s, error = 0; 679 680 s = splnet(); 681 682 switch (cmd) { 683 684 case SIOCSIFADDR: 685 ifp->if_flags |= IFF_UP; 686 687 switch (ifa->ifa_addr->sa_family) { 688 #ifdef INET 689 case AF_INET: 690 elinit(sc); 691 arp_ifinit(ifp, ifa); 692 break; 693 #endif 694 #ifdef NS 695 /* XXX - This code is probably wrong. */ 696 case AF_NS: 697 { 698 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 699 700 if (ns_nullhost(*ina)) 701 ina->x_host = 702 *(union ns_host *)LLADDR(ifp->if_sadl); 703 else 704 memcpy(LLADDR(ifp->if_sadl), ina->x_host.c_host, 705 ETHER_ADDR_LEN); 706 /* Set new address. */ 707 elinit(sc); 708 break; 709 } 710 #endif 711 default: 712 elinit(sc); 713 break; 714 } 715 break; 716 717 case SIOCSIFFLAGS: 718 if ((ifp->if_flags & IFF_UP) == 0 && 719 (ifp->if_flags & IFF_RUNNING) != 0) { 720 /* 721 * If interface is marked down and it is running, then 722 * stop it. 723 */ 724 elstop(sc); 725 ifp->if_flags &= ~IFF_RUNNING; 726 } else if ((ifp->if_flags & IFF_UP) != 0 && 727 (ifp->if_flags & IFF_RUNNING) == 0) { 728 /* 729 * If interface is marked up and it is stopped, then 730 * start it. 731 */ 732 elinit(sc); 733 } else { 734 /* 735 * Some other important flag might have changed, so 736 * reset. 737 */ 738 elreset(sc); 739 } 740 break; 741 742 default: 743 error = EINVAL; 744 break; 745 } 746 747 splx(s); 748 return error; 749 } 750 751 /* 752 * Device timeout routine. 753 */ 754 void 755 elwatchdog(ifp) 756 struct ifnet *ifp; 757 { 758 struct el_softc *sc = ifp->if_softc; 759 760 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 761 sc->sc_ethercom.ec_if.if_oerrors++; 762 763 elreset(sc); 764 } 765