if_el.c revision 1.11 1 /*
2 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted
3 * to use, copy, modify and distribute this software provided that both
4 * the copyright notice and this permission notice appear in all copies
5 * of the software, derivative works or modified versions, and any
6 * portions thereof.
7 */
8
9 /*
10 * 3COM Etherlink 3C501 device driver
11 *
12 * $Id: if_el.c,v 1.11 1994/04/24 01:30:00 mycroft Exp $
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
23 #include <sys/param.h>
24 #include <sys/errno.h>
25 #include <sys/ioctl.h>
26 #include <sys/mbuf.h>
27 #include <sys/socket.h>
28 #include <sys/syslog.h>
29 #include <sys/device.h>
30
31 #include <net/if.h>
32 #include <net/if_dl.h>
33 #include <net/if_types.h>
34
35 #ifdef INET
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38 #include <netinet/in_var.h>
39 #include <netinet/ip.h>
40 #include <netinet/if_ether.h>
41 #endif
42
43 #ifdef NS
44 #include <netns/ns.h>
45 #include <netns/ns_if.h>
46 #endif
47
48 #if NBPFILTER > 0
49 #include <net/bpf.h>
50 #include <net/bpfdesc.h>
51 #endif
52
53 #include <machine/cpu.h>
54 #include <machine/pio.h>
55
56 #include <i386/isa/isavar.h>
57 #include <i386/isa/icu.h>
58 #include <i386/isa/if_elreg.h>
59
60 #define ETHER_MIN_LEN 64
61 #define ETHER_MAX_LEN 1518
62 #define ETHER_ADDR_LEN 6
63
64 /* for debugging convenience */
65 #ifdef EL_DEBUG
66 #define dprintf(x) printf x
67 #else
68 #define dprintf(x)
69 #endif
70
71 /*
72 * per-line info and status
73 */
74 struct el_softc {
75 struct device sc_dev;
76 struct intrhand sc_ih;
77
78 struct arpcom sc_arpcom; /* ethernet common */
79 u_short sc_iobase; /* base I/O addr */
80 caddr_t sc_bpf; /* BPF magic cookie */
81 char sc_pktbuf[EL_BUFSIZ]; /* frame buffer */
82 };
83
84 /*
85 * prototypes
86 */
87 int elintr __P((struct el_softc *));
88 static int el_init __P((struct el_softc *));
89 static int el_ioctl __P((struct ifnet *, int, caddr_t));
90 static int el_start __P((struct ifnet *));
91 static int el_watchdog __P((int));
92 static void el_reset __P((struct el_softc *));
93 static void el_stop __P((struct el_softc *));
94 static int el_xmit __P((struct el_softc *, int));
95 static inline void elread __P((struct el_softc *, caddr_t, int));
96 static struct mbuf *elget __P((caddr_t, int, int, struct ifnet *));
97 static inline void el_hardreset __P((struct el_softc *));
98
99 int elprobe();
100 void elattach();
101
102 /* isa_driver structure for autoconf */
103 struct cfdriver elcd = {
104 NULL, "el", elprobe, elattach, DV_IFNET, sizeof(struct el_softc)
105 };
106
107 struct trailer_header {
108 u_short ether_type;
109 u_short ether_residual;
110 };
111
112 /*
113 * Probe routine.
114 *
115 * See if the card is there and at the right place.
116 * (XXX - cgd -- needs help)
117 */
118 int
119 elprobe(parent, self, aux)
120 struct device *parent, *self;
121 void *aux;
122 {
123 struct el_softc *sc = (void *)self;
124 struct isa_attach_args *ia = aux;
125 u_short iobase = ia->ia_iobase;
126 u_char station_addr[ETHER_ADDR_LEN];
127 int i;
128
129 /* First check the base. */
130 if (iobase < 0x280 || iobase > 0x3f0)
131 return 0;
132
133 /* Grab some info for our structure. */
134 sc->sc_iobase = iobase;
135
136 /*
137 * Now attempt to grab the station address from the PROM and see if it
138 * contains the 3com vendor code.
139 */
140 dprintf(("Probing 3c501 at 0x%x...\n", iobase));
141
142 /* Reset the board. */
143 dprintf(("Resetting board...\n"));
144 outb(iobase+EL_AC, EL_AC_RESET);
145 delay(5);
146 outb(iobase+EL_AC, 0);
147
148 /* Now read the address. */
149 dprintf(("Reading station address...\n"));
150 for (i = 0; i < ETHER_ADDR_LEN; i++) {
151 outb(iobase+EL_GPBL, i);
152 station_addr[i] = inb(iobase+EL_EAW);
153 }
154 dprintf(("Address is %s\n", ether_sprintf(station_addr)));
155
156 /*
157 * If the vendor code is ok, return a 1. We'll assume that whoever
158 * configured this system is right about the IRQ.
159 */
160 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 ||
161 station_addr[2] != 0x8c) {
162 dprintf(("Bad vendor code.\n"));
163 return 0;
164 }
165
166 dprintf(("Vendor code ok.\n"));
167 /* Copy the station address into the arpcom structure. */
168 bcopy(station_addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
169
170 ia->ia_iosize = 4; /* XXX */
171 ia->ia_msize = 0;
172 return 1;
173 }
174
175 /*
176 * Attach the interface to the kernel data structures. By the time this is
177 * called, we know that the card exists at the given I/O address. We still
178 * assume that the IRQ given is correct.
179 */
180 void
181 elattach(parent, self, aux)
182 struct device *parent, *self;
183 void *aux;
184 {
185 struct el_softc *sc = (void *)self;
186 struct isa_attach_args *ia = aux;
187 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
188 struct ifaddr *ifa;
189 struct sockaddr_dl *sdl;
190
191 dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));
192
193 /* Stop the board. */
194 el_stop(sc);
195
196 /* Initialize ifnet structure. */
197 ifp->if_unit = sc->sc_dev.dv_unit;
198 ifp->if_name = elcd.cd_name;
199 ifp->if_mtu = ETHERMTU;
200 ifp->if_output = ether_output;
201 ifp->if_start = el_start;
202 ifp->if_ioctl = el_ioctl;
203 ifp->if_watchdog = el_watchdog;
204 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
205
206 /* Now we can attach the interface. */
207 dprintf(("Attaching interface...\n"));
208 if_attach(ifp);
209
210 /*
211 * Put the station address in the ifa address list's AF_LINK entry, if
212 * any.
213 */
214 ifa = ifp->if_addrlist;
215 while (ifa && ifa->ifa_addr) {
216 if (ifa->ifa_addr->sa_family == AF_LINK) {
217 /*
218 * Fill in the link-level address for this interface.
219 */
220 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
221 sdl->sdl_type = IFT_ETHER;
222 sdl->sdl_alen = ETHER_ADDR_LEN;
223 sdl->sdl_slen = 0;
224 bcopy(sc->sc_arpcom.ac_enaddr, LLADDR(sdl),
225 ETHER_ADDR_LEN);
226 break;
227 } else
228 ifa = ifa->ifa_next;
229 }
230
231 /* Print out some information for the user. */
232 printf("%s: address %s\n", sc->sc_dev.dv_xname,
233 ether_sprintf(sc->sc_arpcom.ac_enaddr));
234
235 /* Finally, attach to bpf filter if it is present. */
236 #if NBPFILTER > 0
237 dprintf(("Attaching to BPF...\n"));
238 bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
239 #endif
240
241 sc->sc_ih.ih_fun = elintr;
242 sc->sc_ih.ih_arg = sc;
243 sc->sc_ih.ih_level = IPL_NET;
244 intr_establish(ia->ia_irq, &sc->sc_ih);
245
246 dprintf(("elattach() finished.\n"));
247 }
248
249 /*
250 * Reset interface.
251 */
252 static void
253 el_reset(sc)
254 struct el_softc *sc;
255 {
256 int s;
257
258 dprintf(("elreset()\n"));
259 s = splimp();
260 el_stop(sc);
261 el_init(sc);
262 splx(s);
263 }
264
265 /*
266 * Stop interface.
267 */
268 static void
269 el_stop(sc)
270 struct el_softc *sc;
271 {
272
273 outb(sc->sc_iobase+EL_AC, 0);
274 }
275
276 /*
277 * Do a hardware reset of the board, and upload the ethernet address again in
278 * case the board forgets.
279 */
280 static inline void
281 el_hardreset(sc)
282 struct el_softc *sc;
283 {
284 u_short iobase = sc->sc_iobase;
285 int i;
286
287 outb(iobase+EL_AC, EL_AC_RESET);
288 delay(5);
289 outb(iobase+EL_AC, 0);
290
291 for (i = 0; i < ETHER_ADDR_LEN; i++)
292 outb(iobase+i, sc->sc_arpcom.ac_enaddr[i]);
293 }
294
295 /*
296 * Initialize interface.
297 */
298 static int
299 el_init(sc)
300 struct el_softc *sc;
301 {
302 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
303 u_short iobase = sc->sc_iobase;
304 int s;
305
306 /* If address not known, do nothing. */
307 if (ifp->if_addrlist == 0)
308 return;
309
310 s = splimp();
311
312 /* First, reset the board. */
313 el_hardreset(sc);
314
315 /* Configure rx. */
316 dprintf(("Configuring rx...\n"));
317 if (ifp->if_flags & IFF_PROMISC)
318 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
319 else
320 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
321 outb(iobase+EL_RBC, 0);
322
323 /* Configure TX. */
324 dprintf(("Configuring tx...\n"));
325 outb(iobase+EL_TXC, 0);
326
327 /* Start reception. */
328 dprintf(("Starting reception...\n"));
329 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
330
331 /* Set flags appropriately. */
332 ifp->if_flags |= IFF_RUNNING;
333 ifp->if_flags &= ~IFF_OACTIVE;
334
335 /* And start output. */
336 el_start(ifp);
337
338 splx(s);
339 }
340
341 /*
342 * Start output on interface. Get datagrams from the queue and output them,
343 * giving the receiver a chance between datagrams. Call only from splimp or
344 * interrupt level!
345 */
346 static int
347 el_start(ifp)
348 struct ifnet *ifp;
349 {
350 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
351 u_short iobase = sc->sc_iobase;
352 struct mbuf *m, *m0;
353 int s, i, len, retries, done;
354
355 dprintf(("el_start()...\n"));
356 s = splimp();
357
358 /* Don't do anything if output is active. */
359 if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
360 return;
361 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
362
363 /*
364 * The main loop. They warned me against endless loops, but would I
365 * listen? NOOO....
366 */
367 for (;;) {
368 /* Dequeue the next datagram. */
369 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
370
371 /* If there's nothing to send, return. */
372 if (!m0) {
373 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
374 splx(s);
375 return;
376 }
377
378 /* Disable the receiver. */
379 outb(iobase+EL_AC, EL_AC_HOST);
380 outb(iobase+EL_RBC, 0);
381
382 /* Copy the datagram to the buffer. */
383 len = 0;
384 for (m = m0; m; m = m->m_next) {
385 if (m->m_len == 0)
386 continue;
387 bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
388 len += m->m_len;
389 }
390 m_freem(m0);
391
392 len = max(len, ETHER_MIN_LEN);
393
394 /* Give the packet to the bpf, if any. */
395 #if NBPFILTER > 0
396 if (sc->sc_bpf)
397 bpf_tap(sc->sc_bpf, sc->sc_pktbuf, len);
398 #endif
399
400 /* Transfer datagram to board. */
401 dprintf(("el: xfr pkt length=%d...\n", len));
402 i = EL_BUFSIZ - len;
403 outb(iobase+EL_GPBL, i);
404 outb(iobase+EL_GPBH, i >> 8);
405 outsb(iobase+EL_BUF, sc->sc_pktbuf, len);
406
407 /* Now transmit the datagram. */
408 retries = 0;
409 done = 0;
410 while (!done) {
411 if (el_xmit(sc, len)) {
412 /* Something went wrong. */
413 done = -1;
414 break;
415 }
416 /* Check out status. */
417 i = inb(iobase+EL_TXS);
418 dprintf(("tx status=0x%x\n", i));
419 if ((i & EL_TXS_READY) == 0) {
420 dprintf(("el: err txs=%x\n", i));
421 sc->sc_arpcom.ac_if.if_oerrors++;
422 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) {
423 if ((i & EL_TXC_DCOLL16) == 0 &&
424 retries < 15) {
425 retries++;
426 outb(iobase+EL_AC, EL_AC_HOST);
427 }
428 } else
429 done = 1;
430 } else {
431 sc->sc_arpcom.ac_if.if_opackets++;
432 done = 1;
433 }
434 }
435 if (done == -1)
436 /* Packet not transmitted. */
437 continue;
438
439 /*
440 * Now give the card a chance to receive.
441 * Gotta love 3c501s...
442 */
443 (void)inb(iobase+EL_AS);
444 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
445 splx(s);
446 /* Interrupt here. */
447 s = splimp();
448 }
449 }
450
451 /*
452 * This function actually attempts to transmit a datagram downloaded to the
453 * board. Call at splimp or interrupt, after downloading data! Returns 0 on
454 * success, non-0 on failure.
455 */
456 static int
457 el_xmit(sc, len)
458 struct el_softc *sc;
459 int len;
460 {
461 u_short iobase = sc->sc_iobase;
462 int gpl;
463 int i;
464
465 gpl = EL_BUFSIZ - len;
466 dprintf(("el: xmit..."));
467 outb(iobase+EL_GPBL, gpl);
468 outb(iobase+EL_GPBH, gpl >> 8);
469 outb(iobase+EL_AC, EL_AC_TXFRX);
470 i = 20000;
471 while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0))
472 i--;
473 if (i == 0) {
474 dprintf(("tx not ready\n"));
475 sc->sc_arpcom.ac_if.if_oerrors++;
476 return -1;
477 }
478 dprintf(("%d cycles.\n", 20000 - i));
479 return 0;
480 }
481
482 /*
483 * Controller interrupt.
484 */
485 int
486 elintr(sc)
487 register struct el_softc *sc;
488 {
489 u_short iobase = sc->sc_iobase;
490 int stat, rxstat, len, done;
491
492 dprintf(("elintr: "));
493
494 /* Check board status. */
495 stat = inb(iobase+EL_AS);
496 if (stat & EL_AS_RXBUSY) {
497 (void)inb(iobase+EL_RXC);
498 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
499 return 0;
500 }
501
502 done = 0;
503 while (!done) {
504 rxstat = inb(iobase+EL_RXS);
505 if (rxstat & EL_RXS_STALE) {
506 (void)inb(iobase+EL_RXC);
507 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
508 return 1;
509 }
510
511 /* If there's an overflow, reinit the board. */
512 if ((rxstat & EL_RXS_NOFLOW) == 0) {
513 dprintf(("overflow.\n"));
514 el_hardreset(sc);
515 /* Put board back into receive mode. */
516 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
517 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
518 else
519 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
520 (void)inb(iobase+EL_AS);
521 outb(iobase+EL_RBC, 0);
522 (void)inb(iobase+EL_RXC);
523 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
524 return 1;
525 }
526
527 /* Incoming packet. */
528 len = inb(iobase+EL_RBL);
529 len |= inb(iobase+EL_RBH) << 8;
530 dprintf(("receive len=%d rxstat=%x ", len, rxstat));
531 outb(iobase+EL_AC, EL_AC_HOST);
532
533 /*
534 * If packet too short or too long, restore rx mode and return.
535 */
536 if (len <= sizeof(struct ether_header) ||
537 len > ETHER_MAX_LEN) {
538 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
539 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
540 else
541 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
542 (void)inb(iobase+EL_AS);
543 outb(iobase+EL_RBC, 0);
544 (void)inb(iobase+EL_RXC);
545 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
546 return 1;
547 }
548
549 sc->sc_arpcom.ac_if.if_ipackets++;
550
551 /* Copy the data into our buffer. */
552 outb(iobase+EL_GPBL, 0);
553 outb(iobase+EL_GPBH, 0);
554 insb(iobase+EL_BUF, sc->sc_pktbuf, len);
555 outb(iobase+EL_RBC, 0);
556 outb(iobase+EL_AC, EL_AC_RX);
557 dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
558 dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
559
560 /* Pass data up to upper levels. */
561 len -= sizeof(struct ether_header);
562 elread(sc, (caddr_t)sc->sc_pktbuf, len);
563
564 /* Is there another packet? */
565 stat = inb(iobase+EL_AS);
566
567 /* If so, do it all again (i.e. don't set done to 1). */
568 if ((stat & EL_AS_RXBUSY) == 0)
569 dprintf(("<rescan> "));
570 else
571 done = 1;
572 }
573
574 (void)inb(iobase+EL_RXC);
575 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
576 return 1;
577 }
578
579 /*
580 * Pass a packet up to the higher levels. Deal with trailer protocol.
581 */
582 static inline void
583 elread(sc, buf, len)
584 struct el_softc *sc;
585 caddr_t buf;
586 int len;
587 {
588 register struct ether_header *eh;
589 struct mbuf *m;
590 int off, resid;
591 u_short etype;
592
593 /*
594 * Deal with trailer protocol: if type is trailer type get true type
595 * from first 16-bit word past data. Remember that type was trailer by
596 * setting off.
597 */
598 eh = (struct ether_header *)buf;
599 etype = ntohs(eh->ether_type);
600 #define eldataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
601 if (etype >= ETHERTYPE_TRAIL &&
602 etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
603 off = (etype - ETHERTYPE_TRAIL) << 9;
604 if ((off + sizeof(struct trailer_header)) > len)
605 return;
606 eh->ether_type = *eldataaddr(eh, off, u_short *);
607 resid = ntohs(*eldataaddr(eh, off+2, u_short *));
608 if ((off + resid) > len)
609 return;
610 len = off + resid;
611 } else
612 off = 0;
613
614 if (len <= 0)
615 return;
616
617 #if NBPFILTER > 0
618 /*
619 * Check if there's a bpf filter listening on this interface. If so,
620 * hand off the raw packet to bpf, which must deal with trailers in its
621 * own way.
622 *
623 * Comparing to if_ed, this code does bpf on trailer packets
624 * incorrectly -- the ether type's already been copied over...
625 * XXX - cgd
626 */
627 if (sc->sc_bpf) {
628 bpf_tap(sc->sc_bpf, buf, len + sizeof(struct ether_header));
629
630 /*
631 * Note that the interface cannot be in promiscuous mode if
632 * there are no bpf listeners. And if el are in promiscuous
633 * mode, el have to check if this packet is really ours.
634 *
635 * XXX This test does not support multicasts.
636 */
637 if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
638 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
639 sizeof(eh->ether_dhost)) != 0 &&
640 bcmp(eh->ether_dhost, etherbroadcastaddr,
641 sizeof(eh->ether_dhost)) != 0)
642 return;
643 }
644 #endif
645
646 /*
647 * Pull packet off interface. Off is nonzero if packet has trailing
648 * header; neget will then force this header information to be at the
649 * front, but we still have to drop the type and length which are at
650 * the front of any trailer data.
651 */
652 m = elget(buf, len, off, &sc->sc_arpcom.ac_if);
653 if (!m)
654 return;
655
656 ether_input(&sc->sc_arpcom.ac_if, eh, m);
657 }
658
659 /*
660 * Pull read data off a interface. Len is length of data, with local net
661 * header stripped. Off is non-zero if a trailer protocol was used, and gives
662 * the offset of the trailer information. We copy the trailer information and
663 * then all the normal data into mbufs. When full cluster sized units are
664 * present we copy into clusters.
665 */
666 struct mbuf *
667 elget(buf, totlen, off0, ifp)
668 caddr_t buf;
669 int totlen, off0;
670 struct ifnet *ifp;
671 {
672 struct mbuf *top, **mp, *m, *p;
673 int off = off0, len;
674 register caddr_t cp = buf;
675 char *epkt;
676
677 buf += sizeof(struct ether_header);
678 cp = buf;
679 epkt = cp + totlen;
680
681 if (off) {
682 cp += off + 2 * sizeof(u_short);
683 totlen -= 2 * sizeof(u_short);
684 }
685
686 MGETHDR(m, M_DONTWAIT, MT_DATA);
687 if (!m)
688 return 0;
689 m->m_pkthdr.rcvif = ifp;
690 m->m_pkthdr.len = totlen;
691 m->m_len = MHLEN;
692 top = 0;
693 mp = ⊤
694 while (totlen > 0) {
695 if (top) {
696 MGET(m, M_DONTWAIT, MT_DATA);
697 if (m == 0) {
698 m_freem(top);
699 return 0;
700 }
701 m->m_len = MLEN;
702 }
703 len = min(totlen, epkt - cp);
704 if (len >= MINCLSIZE) {
705 MCLGET(m, M_DONTWAIT);
706 if (m->m_flags & M_EXT)
707 m->m_len = len = min(len, MCLBYTES);
708 else
709 len = m->m_len;
710 } else {
711 /*
712 * Place initial small packet/header at end of mbuf.
713 */
714 if (len < m->m_len) {
715 if (top == 0 && len + max_linkhdr <= m->m_len)
716 m->m_data += max_linkhdr;
717 m->m_len = len;
718 } else
719 len = m->m_len;
720 }
721 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
722 cp += len;
723 *mp = m;
724 mp = &m->m_next;
725 totlen -= len;
726 if (cp == epkt)
727 cp = buf;
728 }
729 return top;
730 }
731
732 /*
733 * Process an ioctl request. This code needs some work - it looks pretty ugly.
734 */
735 static int
736 el_ioctl(ifp, command, data)
737 register struct ifnet *ifp;
738 int command;
739 caddr_t data;
740 {
741 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
742 register struct ifaddr *ifa = (struct ifaddr *)data;
743 struct ifreq *ifr = (struct ifreq *)data;
744 int s, error = 0;
745
746 s = splimp();
747
748 switch (command) {
749
750 case SIOCSIFADDR:
751 ifp->if_flags |= IFF_UP;
752
753 switch (ifa->ifa_addr->sa_family) {
754 #ifdef INET
755 case AF_INET:
756 el_init(sc); /* before arpwhohas */
757 /*
758 * See if another station has *our* IP address.
759 * i.e.: There is an address conflict! If a
760 * conflict exists, a message is sent to the
761 * console.
762 */
763 sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
764 arpwhohas(&sc->sc_arpcom, &IA_SIN(ifa)->sin_addr);
765 break;
766 #endif
767 #ifdef NS
768 /*
769 * XXX - This code is probably wrong.
770 */
771 case AF_NS:
772 {
773 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
774
775 if (ns_nullhost(*ina))
776 ina->x_host =
777 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
778 else {
779 /*
780 *
781 */
782 bcopy((caddr_t)ina->x_host.c_host,
783 (caddr_t)sc->sc_arpcom.ac_enaddr,
784 sizeof(sc->sc_arpcom.ac_enaddr));
785 }
786 /* Set new address. */
787 el_init(sc);
788 break;
789 }
790 #endif
791 default:
792 el_init(sc);
793 break;
794 }
795 break;
796
797 case SIOCSIFFLAGS:
798 if ((ifp->if_flags & IFF_UP) == 0 &&
799 (ifp->if_flags & IFF_RUNNING)) {
800 /*
801 * If interface is marked down and it is running, then
802 * stop it.
803 */
804 el_stop(sc);
805 ifp->if_flags &= ~IFF_RUNNING;
806 } else if ((ifp->if_flags & IFF_UP) &&
807 (ifp->if_flags & IFF_RUNNING) == 0) {
808 /*
809 * If interface is marked up and it is stopped, then
810 * start it.
811 */
812 el_init(sc);
813 } else {
814 /*
815 * Some other important flag might have changed, so
816 * reset.
817 */
818 el_reset(sc);
819 }
820
821 default:
822 error = EINVAL;
823 }
824 (void) splx(s);
825 return error;
826 }
827
828 /*
829 * Device timeout routine.
830 */
831 static int
832 el_watchdog(unit)
833 int unit;
834 {
835 struct el_softc *sc = elcd.cd_devs[unit];
836
837 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
838 sc->sc_arpcom.ac_if.if_oerrors++;
839
840 el_reset(sc);
841 }
842