if_el.c revision 1.12 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.12 1994/05/11 12:09:21 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_type = IFT_ETHER;
200 ifp->if_addrlen = ETHER_ADDR_LEN;
201 ifp->if_hdrlen = 14;
202 ifp->if_mtu = ETHERMTU;
203 ifp->if_output = ether_output;
204 ifp->if_start = el_start;
205 ifp->if_ioctl = el_ioctl;
206 ifp->if_watchdog = el_watchdog;
207 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
208
209 /* Now we can attach the interface. */
210 dprintf(("Attaching interface...\n"));
211 if_attach(ifp);
212
213 /*
214 * Put the station address in the ifa address list's AF_LINK entry, if
215 * any.
216 */
217 ifa = ifp->if_addrlist;
218 while (ifa && ifa->ifa_addr) {
219 if (ifa->ifa_addr->sa_family == AF_LINK) {
220 /*
221 * Fill in the link-level address for this interface.
222 */
223 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
224 sdl->sdl_type = IFT_ETHER;
225 sdl->sdl_alen = ETHER_ADDR_LEN;
226 sdl->sdl_slen = 0;
227 bcopy(sc->sc_arpcom.ac_enaddr, LLADDR(sdl),
228 ETHER_ADDR_LEN);
229 break;
230 } else
231 ifa = ifa->ifa_next;
232 }
233
234 /* Print out some information for the user. */
235 printf("%s: address %s\n", sc->sc_dev.dv_xname,
236 ether_sprintf(sc->sc_arpcom.ac_enaddr));
237
238 /* Finally, attach to bpf filter if it is present. */
239 #if NBPFILTER > 0
240 dprintf(("Attaching to BPF...\n"));
241 bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
242 #endif
243
244 sc->sc_ih.ih_fun = elintr;
245 sc->sc_ih.ih_arg = sc;
246 sc->sc_ih.ih_level = IPL_NET;
247 intr_establish(ia->ia_irq, &sc->sc_ih);
248
249 dprintf(("elattach() finished.\n"));
250 }
251
252 /*
253 * Reset interface.
254 */
255 static void
256 el_reset(sc)
257 struct el_softc *sc;
258 {
259 int s;
260
261 dprintf(("elreset()\n"));
262 s = splimp();
263 el_stop(sc);
264 el_init(sc);
265 splx(s);
266 }
267
268 /*
269 * Stop interface.
270 */
271 static void
272 el_stop(sc)
273 struct el_softc *sc;
274 {
275
276 outb(sc->sc_iobase+EL_AC, 0);
277 }
278
279 /*
280 * Do a hardware reset of the board, and upload the ethernet address again in
281 * case the board forgets.
282 */
283 static inline void
284 el_hardreset(sc)
285 struct el_softc *sc;
286 {
287 u_short iobase = sc->sc_iobase;
288 int i;
289
290 outb(iobase+EL_AC, EL_AC_RESET);
291 delay(5);
292 outb(iobase+EL_AC, 0);
293
294 for (i = 0; i < ETHER_ADDR_LEN; i++)
295 outb(iobase+i, sc->sc_arpcom.ac_enaddr[i]);
296 }
297
298 /*
299 * Initialize interface.
300 */
301 static int
302 el_init(sc)
303 struct el_softc *sc;
304 {
305 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
306 u_short iobase = sc->sc_iobase;
307 int s;
308
309 /* If address not known, do nothing. */
310 if (ifp->if_addrlist == 0)
311 return;
312
313 s = splimp();
314
315 /* First, reset the board. */
316 el_hardreset(sc);
317
318 /* Configure rx. */
319 dprintf(("Configuring rx...\n"));
320 if (ifp->if_flags & IFF_PROMISC)
321 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
322 else
323 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
324 outb(iobase+EL_RBC, 0);
325
326 /* Configure TX. */
327 dprintf(("Configuring tx...\n"));
328 outb(iobase+EL_TXC, 0);
329
330 /* Start reception. */
331 dprintf(("Starting reception...\n"));
332 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
333
334 /* Set flags appropriately. */
335 ifp->if_flags |= IFF_RUNNING;
336 ifp->if_flags &= ~IFF_OACTIVE;
337
338 /* And start output. */
339 el_start(ifp);
340
341 splx(s);
342 }
343
344 /*
345 * Start output on interface. Get datagrams from the queue and output them,
346 * giving the receiver a chance between datagrams. Call only from splimp or
347 * interrupt level!
348 */
349 static int
350 el_start(ifp)
351 struct ifnet *ifp;
352 {
353 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
354 u_short iobase = sc->sc_iobase;
355 struct mbuf *m, *m0;
356 int s, i, len, retries, done;
357
358 dprintf(("el_start()...\n"));
359 s = splimp();
360
361 /* Don't do anything if output is active. */
362 if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
363 return;
364 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
365
366 /*
367 * The main loop. They warned me against endless loops, but would I
368 * listen? NOOO....
369 */
370 for (;;) {
371 /* Dequeue the next datagram. */
372 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
373
374 /* If there's nothing to send, return. */
375 if (!m0) {
376 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
377 splx(s);
378 return;
379 }
380
381 /* Disable the receiver. */
382 outb(iobase+EL_AC, EL_AC_HOST);
383 outb(iobase+EL_RBC, 0);
384
385 /* Copy the datagram to the buffer. */
386 len = 0;
387 for (m = m0; m; m = m->m_next) {
388 if (m->m_len == 0)
389 continue;
390 bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
391 len += m->m_len;
392 }
393 m_freem(m0);
394
395 len = max(len, ETHER_MIN_LEN);
396
397 /* Give the packet to the bpf, if any. */
398 #if NBPFILTER > 0
399 if (sc->sc_bpf)
400 bpf_tap(sc->sc_bpf, sc->sc_pktbuf, len);
401 #endif
402
403 /* Transfer datagram to board. */
404 dprintf(("el: xfr pkt length=%d...\n", len));
405 i = EL_BUFSIZ - len;
406 outb(iobase+EL_GPBL, i);
407 outb(iobase+EL_GPBH, i >> 8);
408 outsb(iobase+EL_BUF, sc->sc_pktbuf, len);
409
410 /* Now transmit the datagram. */
411 retries = 0;
412 done = 0;
413 while (!done) {
414 if (el_xmit(sc, len)) {
415 /* Something went wrong. */
416 done = -1;
417 break;
418 }
419 /* Check out status. */
420 i = inb(iobase+EL_TXS);
421 dprintf(("tx status=0x%x\n", i));
422 if ((i & EL_TXS_READY) == 0) {
423 dprintf(("el: err txs=%x\n", i));
424 sc->sc_arpcom.ac_if.if_oerrors++;
425 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) {
426 if ((i & EL_TXC_DCOLL16) == 0 &&
427 retries < 15) {
428 retries++;
429 outb(iobase+EL_AC, EL_AC_HOST);
430 }
431 } else
432 done = 1;
433 } else {
434 sc->sc_arpcom.ac_if.if_opackets++;
435 done = 1;
436 }
437 }
438 if (done == -1)
439 /* Packet not transmitted. */
440 continue;
441
442 /*
443 * Now give the card a chance to receive.
444 * Gotta love 3c501s...
445 */
446 (void)inb(iobase+EL_AS);
447 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
448 splx(s);
449 /* Interrupt here. */
450 s = splimp();
451 }
452 }
453
454 /*
455 * This function actually attempts to transmit a datagram downloaded to the
456 * board. Call at splimp or interrupt, after downloading data! Returns 0 on
457 * success, non-0 on failure.
458 */
459 static int
460 el_xmit(sc, len)
461 struct el_softc *sc;
462 int len;
463 {
464 u_short iobase = sc->sc_iobase;
465 int gpl;
466 int i;
467
468 gpl = EL_BUFSIZ - len;
469 dprintf(("el: xmit..."));
470 outb(iobase+EL_GPBL, gpl);
471 outb(iobase+EL_GPBH, gpl >> 8);
472 outb(iobase+EL_AC, EL_AC_TXFRX);
473 i = 20000;
474 while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0))
475 i--;
476 if (i == 0) {
477 dprintf(("tx not ready\n"));
478 sc->sc_arpcom.ac_if.if_oerrors++;
479 return -1;
480 }
481 dprintf(("%d cycles.\n", 20000 - i));
482 return 0;
483 }
484
485 /*
486 * Controller interrupt.
487 */
488 int
489 elintr(sc)
490 register struct el_softc *sc;
491 {
492 u_short iobase = sc->sc_iobase;
493 int stat, rxstat, len, done;
494
495 dprintf(("elintr: "));
496
497 /* Check board status. */
498 stat = inb(iobase+EL_AS);
499 if (stat & EL_AS_RXBUSY) {
500 (void)inb(iobase+EL_RXC);
501 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
502 return 0;
503 }
504
505 done = 0;
506 while (!done) {
507 rxstat = inb(iobase+EL_RXS);
508 if (rxstat & EL_RXS_STALE) {
509 (void)inb(iobase+EL_RXC);
510 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
511 return 1;
512 }
513
514 /* If there's an overflow, reinit the board. */
515 if ((rxstat & EL_RXS_NOFLOW) == 0) {
516 dprintf(("overflow.\n"));
517 el_hardreset(sc);
518 /* Put board back into receive mode. */
519 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
520 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
521 else
522 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
523 (void)inb(iobase+EL_AS);
524 outb(iobase+EL_RBC, 0);
525 (void)inb(iobase+EL_RXC);
526 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
527 return 1;
528 }
529
530 /* Incoming packet. */
531 len = inb(iobase+EL_RBL);
532 len |= inb(iobase+EL_RBH) << 8;
533 dprintf(("receive len=%d rxstat=%x ", len, rxstat));
534 outb(iobase+EL_AC, EL_AC_HOST);
535
536 /*
537 * If packet too short or too long, restore rx mode and return.
538 */
539 if (len <= sizeof(struct ether_header) ||
540 len > ETHER_MAX_LEN) {
541 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
542 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
543 else
544 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
545 (void)inb(iobase+EL_AS);
546 outb(iobase+EL_RBC, 0);
547 (void)inb(iobase+EL_RXC);
548 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
549 return 1;
550 }
551
552 sc->sc_arpcom.ac_if.if_ipackets++;
553
554 /* Copy the data into our buffer. */
555 outb(iobase+EL_GPBL, 0);
556 outb(iobase+EL_GPBH, 0);
557 insb(iobase+EL_BUF, sc->sc_pktbuf, len);
558 outb(iobase+EL_RBC, 0);
559 outb(iobase+EL_AC, EL_AC_RX);
560 dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
561 dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
562
563 /* Pass data up to upper levels. */
564 len -= sizeof(struct ether_header);
565 elread(sc, (caddr_t)sc->sc_pktbuf, len);
566
567 /* Is there another packet? */
568 stat = inb(iobase+EL_AS);
569
570 /* If so, do it all again (i.e. don't set done to 1). */
571 if ((stat & EL_AS_RXBUSY) == 0)
572 dprintf(("<rescan> "));
573 else
574 done = 1;
575 }
576
577 (void)inb(iobase+EL_RXC);
578 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
579 return 1;
580 }
581
582 /*
583 * Pass a packet up to the higher levels. Deal with trailer protocol.
584 */
585 static inline void
586 elread(sc, buf, len)
587 struct el_softc *sc;
588 caddr_t buf;
589 int len;
590 {
591 register struct ether_header *eh;
592 struct mbuf *m;
593 int off, resid;
594 u_short etype;
595
596 /*
597 * Deal with trailer protocol: if type is trailer type get true type
598 * from first 16-bit word past data. Remember that type was trailer by
599 * setting off.
600 */
601 eh = (struct ether_header *)buf;
602 etype = ntohs(eh->ether_type);
603 #define eldataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
604 if (etype >= ETHERTYPE_TRAIL &&
605 etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
606 off = (etype - ETHERTYPE_TRAIL) << 9;
607 if ((off + sizeof(struct trailer_header)) > len)
608 return;
609 eh->ether_type = *eldataaddr(eh, off, u_short *);
610 resid = ntohs(*eldataaddr(eh, off+2, u_short *));
611 if ((off + resid) > len)
612 return;
613 len = off + resid;
614 } else
615 off = 0;
616
617 if (len <= 0)
618 return;
619
620 #if NBPFILTER > 0
621 /*
622 * Check if there's a bpf filter listening on this interface. If so,
623 * hand off the raw packet to bpf, which must deal with trailers in its
624 * own way.
625 *
626 * Comparing to if_ed, this code does bpf on trailer packets
627 * incorrectly -- the ether type's already been copied over...
628 * XXX - cgd
629 */
630 if (sc->sc_bpf) {
631 bpf_tap(sc->sc_bpf, buf, len + sizeof(struct ether_header));
632
633 /*
634 * Note that the interface cannot be in promiscuous mode if
635 * there are no bpf listeners. And if el are in promiscuous
636 * mode, el have to check if this packet is really ours.
637 *
638 * XXX This test does not support multicasts.
639 */
640 if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
641 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
642 sizeof(eh->ether_dhost)) != 0 &&
643 bcmp(eh->ether_dhost, etherbroadcastaddr,
644 sizeof(eh->ether_dhost)) != 0)
645 return;
646 }
647 #endif
648
649 /*
650 * Pull packet off interface. Off is nonzero if packet has trailing
651 * header; neget will then force this header information to be at the
652 * front, but we still have to drop the type and length which are at
653 * the front of any trailer data.
654 */
655 m = elget(buf, len, off, &sc->sc_arpcom.ac_if);
656 if (!m)
657 return;
658
659 ether_input(&sc->sc_arpcom.ac_if, eh, m);
660 }
661
662 /*
663 * Pull read data off a interface. Len is length of data, with local net
664 * header stripped. Off is non-zero if a trailer protocol was used, and gives
665 * the offset of the trailer information. We copy the trailer information and
666 * then all the normal data into mbufs. When full cluster sized units are
667 * present we copy into clusters.
668 */
669 struct mbuf *
670 elget(buf, totlen, off0, ifp)
671 caddr_t buf;
672 int totlen, off0;
673 struct ifnet *ifp;
674 {
675 struct mbuf *top, **mp, *m, *p;
676 int off = off0, len;
677 register caddr_t cp = buf;
678 char *epkt;
679
680 buf += sizeof(struct ether_header);
681 cp = buf;
682 epkt = cp + totlen;
683
684 if (off) {
685 cp += off + 2 * sizeof(u_short);
686 totlen -= 2 * sizeof(u_short);
687 }
688
689 MGETHDR(m, M_DONTWAIT, MT_DATA);
690 if (!m)
691 return 0;
692 m->m_pkthdr.rcvif = ifp;
693 m->m_pkthdr.len = totlen;
694 m->m_len = MHLEN;
695 top = 0;
696 mp = ⊤
697 while (totlen > 0) {
698 if (top) {
699 MGET(m, M_DONTWAIT, MT_DATA);
700 if (m == 0) {
701 m_freem(top);
702 return 0;
703 }
704 m->m_len = MLEN;
705 }
706 len = min(totlen, epkt - cp);
707 if (len >= MINCLSIZE) {
708 MCLGET(m, M_DONTWAIT);
709 if (m->m_flags & M_EXT)
710 m->m_len = len = min(len, MCLBYTES);
711 else
712 len = m->m_len;
713 } else {
714 /*
715 * Place initial small packet/header at end of mbuf.
716 */
717 if (len < m->m_len) {
718 if (top == 0 && len + max_linkhdr <= m->m_len)
719 m->m_data += max_linkhdr;
720 m->m_len = len;
721 } else
722 len = m->m_len;
723 }
724 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
725 cp += len;
726 *mp = m;
727 mp = &m->m_next;
728 totlen -= len;
729 if (cp == epkt)
730 cp = buf;
731 }
732 return top;
733 }
734
735 /*
736 * Process an ioctl request. This code needs some work - it looks pretty ugly.
737 */
738 static int
739 el_ioctl(ifp, command, data)
740 register struct ifnet *ifp;
741 int command;
742 caddr_t data;
743 {
744 struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
745 register struct ifaddr *ifa = (struct ifaddr *)data;
746 struct ifreq *ifr = (struct ifreq *)data;
747 int s, error = 0;
748
749 s = splimp();
750
751 switch (command) {
752
753 case SIOCSIFADDR:
754 ifp->if_flags |= IFF_UP;
755
756 switch (ifa->ifa_addr->sa_family) {
757 #ifdef INET
758 case AF_INET:
759 el_init(sc); /* before arpwhohas */
760 /*
761 * See if another station has *our* IP address.
762 * i.e.: There is an address conflict! If a
763 * conflict exists, a message is sent to the
764 * console.
765 */
766 sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
767 arpwhohas(&sc->sc_arpcom, &IA_SIN(ifa)->sin_addr);
768 break;
769 #endif
770 #ifdef NS
771 /*
772 * XXX - This code is probably wrong.
773 */
774 case AF_NS:
775 {
776 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
777
778 if (ns_nullhost(*ina))
779 ina->x_host =
780 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
781 else {
782 /*
783 *
784 */
785 bcopy((caddr_t)ina->x_host.c_host,
786 (caddr_t)sc->sc_arpcom.ac_enaddr,
787 sizeof(sc->sc_arpcom.ac_enaddr));
788 }
789 /* Set new address. */
790 el_init(sc);
791 break;
792 }
793 #endif
794 default:
795 el_init(sc);
796 break;
797 }
798 break;
799
800 case SIOCSIFFLAGS:
801 if ((ifp->if_flags & IFF_UP) == 0 &&
802 (ifp->if_flags & IFF_RUNNING)) {
803 /*
804 * If interface is marked down and it is running, then
805 * stop it.
806 */
807 el_stop(sc);
808 ifp->if_flags &= ~IFF_RUNNING;
809 } else if ((ifp->if_flags & IFF_UP) &&
810 (ifp->if_flags & IFF_RUNNING) == 0) {
811 /*
812 * If interface is marked up and it is stopped, then
813 * start it.
814 */
815 el_init(sc);
816 } else {
817 /*
818 * Some other important flag might have changed, so
819 * reset.
820 */
821 el_reset(sc);
822 }
823
824 default:
825 error = EINVAL;
826 }
827 (void) splx(s);
828 return error;
829 }
830
831 /*
832 * Device timeout routine.
833 */
834 static int
835 el_watchdog(unit)
836 int unit;
837 {
838 struct el_softc *sc = elcd.cd_devs[unit];
839
840 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
841 sc->sc_arpcom.ac_if.if_oerrors++;
842
843 el_reset(sc);
844 }
845