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