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