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