1 /* $NetBSD: if_el.c,v 1.71 2004/09/14 20:20:47 drochner 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.71 2004/09/14 20:20:47 drochner 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 == ISA_UNKNOWN_PORT) 149 return (0); 150 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 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 for (i = 0; 436 i < ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len; i++) 437 bus_space_write_1(iot, ioh, EL_BUF, 0); 438 439 m_freem(m0); 440 441 /* Now transmit the datagram. */ 442 retries = 0; 443 for (;;) { 444 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff); 445 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff); 446 if (el_xmit(sc)) { 447 ifp->if_oerrors++; 448 break; 449 } 450 /* Check out status. */ 451 i = bus_space_read_1(iot, ioh, EL_TXS); 452 DPRINTF(("tx status=0x%x\n", i)); 453 if ((i & EL_TXS_READY) == 0) { 454 DPRINTF(("el: err txs=%x\n", i)); 455 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) { 456 ifp->if_collisions++; 457 if ((i & EL_TXC_DCOLL16) == 0 && 458 retries < 15) { 459 retries++; 460 bus_space_write_1(iot, ioh, 461 EL_AC, EL_AC_HOST); 462 } 463 } else { 464 ifp->if_oerrors++; 465 break; 466 } 467 } else { 468 ifp->if_opackets++; 469 break; 470 } 471 } 472 473 /* 474 * Now give the card a chance to receive. 475 * Gotta love 3c501s... 476 */ 477 (void)bus_space_read_1(iot, ioh, EL_AS); 478 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 479 splx(s); 480 /* Interrupt here. */ 481 s = splnet(); 482 } 483 484 (void)bus_space_read_1(iot, ioh, EL_AS); 485 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 486 ifp->if_flags &= ~IFF_OACTIVE; 487 splx(s); 488 } 489 490 /* 491 * This function actually attempts to transmit a datagram downloaded to the 492 * board. Call at splnet or interrupt, after downloading data! Returns 0 on 493 * success, non-0 on failure. 494 */ 495 static int 496 el_xmit(sc) 497 struct el_softc *sc; 498 { 499 bus_space_tag_t iot = sc->sc_iot; 500 bus_space_handle_t ioh = sc->sc_ioh; 501 int i; 502 503 /* 504 * XXX 505 * This busy-waits for the tx completion. Can we get an interrupt 506 * instead? 507 */ 508 509 DPRINTF(("el: xmit...")); 510 bus_space_write_1(iot, ioh, EL_AC, EL_AC_TXFRX); 511 i = 20000; 512 while ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_TXBUSY) && (i > 0)) 513 i--; 514 if (i == 0) { 515 DPRINTF(("tx not ready\n")); 516 return -1; 517 } 518 DPRINTF(("%d cycles.\n", 20000 - i)); 519 return 0; 520 } 521 522 /* 523 * Controller interrupt. 524 */ 525 int 526 elintr(arg) 527 void *arg; 528 { 529 struct el_softc *sc = arg; 530 bus_space_tag_t iot = sc->sc_iot; 531 bus_space_handle_t ioh = sc->sc_ioh; 532 u_int8_t rxstat; 533 int len; 534 535 DPRINTF(("elintr: ")); 536 537 /* Check board status. */ 538 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) { 539 (void)bus_space_read_1(iot, ioh, EL_RXC); 540 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 541 return 0; 542 } 543 544 for (;;) { 545 rxstat = bus_space_read_1(iot, ioh, EL_RXS); 546 if (rxstat & EL_RXS_STALE) 547 break; 548 549 /* If there's an overflow, reinit the board. */ 550 if ((rxstat & EL_RXS_NOFLOW) == 0) { 551 DPRINTF(("overflow.\n")); 552 el_hardreset(sc); 553 /* Put board back into receive mode. */ 554 if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) 555 bus_space_write_1(iot, ioh, EL_RXC, 556 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 557 EL_RXC_DOFLOW | EL_RXC_PROMISC); 558 else 559 bus_space_write_1(iot, ioh, EL_RXC, 560 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 561 EL_RXC_DOFLOW | EL_RXC_ABROAD); 562 (void)bus_space_read_1(iot, ioh, EL_AS); 563 bus_space_write_1(iot, ioh, EL_RBC, 0); 564 break; 565 } 566 567 /* Incoming packet. */ 568 len = bus_space_read_1(iot, ioh, EL_RBL); 569 len |= bus_space_read_1(iot, ioh, EL_RBH) << 8; 570 DPRINTF(("receive len=%d rxstat=%x ", len, rxstat)); 571 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); 572 573 /* Pass data up to upper levels. */ 574 elread(sc, len); 575 576 /* Is there another packet? */ 577 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) 578 break; 579 580 #if NRND > 0 581 rnd_add_uint32(&sc->rnd_source, rxstat); 582 #endif 583 584 DPRINTF(("<rescan> ")); 585 } 586 587 (void)bus_space_read_1(iot, ioh, EL_RXC); 588 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 589 return 1; 590 } 591 592 /* 593 * Pass a packet to the higher levels. 594 */ 595 void 596 elread(sc, len) 597 struct el_softc *sc; 598 int len; 599 { 600 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 601 struct mbuf *m; 602 603 if (len <= sizeof(struct ether_header) || 604 len > ETHER_MAX_LEN) { 605 printf("%s: invalid packet size %d; dropping\n", 606 sc->sc_dev.dv_xname, len); 607 ifp->if_ierrors++; 608 return; 609 } 610 611 /* Pull packet off interface. */ 612 m = elget(sc, len); 613 if (m == 0) { 614 ifp->if_ierrors++; 615 return; 616 } 617 618 ifp->if_ipackets++; 619 620 #if NBPFILTER > 0 621 /* 622 * Check if there's a BPF listener on this interface. 623 * If so, hand off the raw packet to BPF. 624 */ 625 if (ifp->if_bpf) 626 bpf_mtap(ifp->if_bpf, m); 627 #endif 628 629 (*ifp->if_input)(ifp, m); 630 } 631 632 /* 633 * Pull read data off a interface. Len is length of data, with local net 634 * header stripped. We copy the data into mbufs. When full cluster sized 635 * units are present we copy into clusters. 636 */ 637 struct mbuf * 638 elget(sc, totlen) 639 struct el_softc *sc; 640 int totlen; 641 { 642 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 643 bus_space_tag_t iot = sc->sc_iot; 644 bus_space_handle_t ioh = sc->sc_ioh; 645 struct mbuf *m, *m0, *newm; 646 int len; 647 648 MGETHDR(m0, M_DONTWAIT, MT_DATA); 649 if (m0 == 0) 650 return (0); 651 m0->m_pkthdr.rcvif = ifp; 652 m0->m_pkthdr.len = totlen; 653 len = MHLEN; 654 m = m0; 655 656 bus_space_write_1(iot, ioh, EL_GPBL, 0); 657 bus_space_write_1(iot, ioh, EL_GPBH, 0); 658 659 while (totlen > 0) { 660 if (totlen >= MINCLSIZE) { 661 MCLGET(m, M_DONTWAIT); 662 if ((m->m_flags & M_EXT) == 0) 663 goto bad; 664 len = MCLBYTES; 665 } 666 667 m->m_len = len = min(totlen, len); 668 bus_space_read_multi_1(iot, ioh, EL_BUF, mtod(m, u_int8_t *), len); 669 670 totlen -= len; 671 if (totlen > 0) { 672 MGET(newm, M_DONTWAIT, MT_DATA); 673 if (newm == 0) 674 goto bad; 675 len = MLEN; 676 m = m->m_next = newm; 677 } 678 } 679 680 bus_space_write_1(iot, ioh, EL_RBC, 0); 681 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RX); 682 683 return (m0); 684 685 bad: 686 m_freem(m0); 687 return (0); 688 } 689 690 /* 691 * Process an ioctl request. This code needs some work - it looks pretty ugly. 692 */ 693 int 694 elioctl(ifp, cmd, data) 695 struct ifnet *ifp; 696 u_long cmd; 697 caddr_t data; 698 { 699 struct el_softc *sc = ifp->if_softc; 700 struct ifaddr *ifa = (struct ifaddr *)data; 701 int s, error = 0; 702 703 s = splnet(); 704 705 switch (cmd) { 706 707 case SIOCSIFADDR: 708 ifp->if_flags |= IFF_UP; 709 710 switch (ifa->ifa_addr->sa_family) { 711 #ifdef INET 712 case AF_INET: 713 elinit(sc); 714 arp_ifinit(ifp, ifa); 715 break; 716 #endif 717 #ifdef NS 718 /* XXX - This code is probably wrong. */ 719 case AF_NS: 720 { 721 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 722 723 if (ns_nullhost(*ina)) 724 ina->x_host = 725 *(union ns_host *)LLADDR(ifp->if_sadl); 726 else 727 memcpy(LLADDR(ifp->if_sadl), ina->x_host.c_host, 728 ETHER_ADDR_LEN); 729 /* Set new address. */ 730 elinit(sc); 731 break; 732 } 733 #endif 734 default: 735 elinit(sc); 736 break; 737 } 738 break; 739 740 case SIOCSIFFLAGS: 741 if ((ifp->if_flags & IFF_UP) == 0 && 742 (ifp->if_flags & IFF_RUNNING) != 0) { 743 /* 744 * If interface is marked down and it is running, then 745 * stop it. 746 */ 747 elstop(sc); 748 ifp->if_flags &= ~IFF_RUNNING; 749 } else if ((ifp->if_flags & IFF_UP) != 0 && 750 (ifp->if_flags & IFF_RUNNING) == 0) { 751 /* 752 * If interface is marked up and it is stopped, then 753 * start it. 754 */ 755 elinit(sc); 756 } else { 757 /* 758 * Some other important flag might have changed, so 759 * reset. 760 */ 761 elreset(sc); 762 } 763 break; 764 765 default: 766 error = EINVAL; 767 break; 768 } 769 770 splx(s); 771 return error; 772 } 773 774 /* 775 * Device timeout routine. 776 */ 777 void 778 elwatchdog(ifp) 779 struct ifnet *ifp; 780 { 781 struct el_softc *sc = ifp->if_softc; 782 783 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 784 sc->sc_ethercom.ec_if.if_oerrors++; 785 786 elreset(sc); 787 } 788