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