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