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