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