if_le.c revision 1.19 1 /* $NetBSD: if_le.c,v 1.19 1995/04/16 01:52:07 gwr Exp $ */
2
3 /*
4 * LANCE Ethernet driver
5 *
6 * Copyright (c) 1995 Gordon W. Ross
7 * Copyright (c) 1994 Charles Hannum.
8 *
9 * Copyright (C) 1993, Paul Richards. This software may be used, modified,
10 * copied, distributed, and sold, in both source and binary form provided
11 * that the above copyright and these terms are retained. Under no
12 * circumstances is the author responsible for the proper functioning
13 * of this software, nor does the author assume any responsibility
14 * for damages incurred with its use.
15 */
16
17 #include "bpfilter.h"
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/errno.h>
22 #include <sys/ioctl.h>
23 #include <sys/mbuf.h>
24 #include <sys/socket.h>
25 #include <sys/syslog.h>
26 #include <sys/device.h>
27
28 #include <net/if.h>
29 #include <net/if_dl.h>
30 #include <net/if_types.h>
31 #include <net/netisr.h>
32
33 #ifdef INET
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/in_var.h>
37 #include <netinet/ip.h>
38 #include <netinet/if_ether.h>
39 #endif
40
41 #ifdef NS
42 #include <netns/ns.h>
43 #include <netns/ns_if.h>
44 #endif
45
46 #if NBPFILTER > 0
47 #include <net/bpf.h>
48 #include <net/bpfdesc.h>
49 #endif
50
51 #include <machine/autoconf.h>
52 #include <machine/cpu.h>
53
54 /* #define LEDEBUG 1 */
55
56 #include "if_lereg.h"
57 #include "if_le.h"
58 #include "if_le_subr.h"
59
60 #define RMD_BITS "\20\20own\17err\16fram\15oflo\14crc\13rbuf\12stp\11enp"
61
62 #define ETHER_MIN_LEN 64
63 #define ETHER_MAX_LEN 1518
64
65 /*
66 * The lance has only 24 address lines. When it accesses memory,
67 * the high address lines are hard-wired to 0xFF, so we must:
68 * (1) put what we want the LANCE to see above 0xFF000000, and
69 * (2) mask our CPU addresses down to 24 bits for the LANCE.
70 */
71 #define LANCE_ADDR(sc,x) ((u_int)(x) & 0xFFffff)
72
73 #ifdef PACKETSTATS
74 long lexpacketsizes[LEMTU+1];
75 long lerpacketsizes[LEMTU+1];
76 #endif
77
78 /* autoconfiguration driver */
79 void le_attach(struct device *, struct device *, void *);
80
81 struct cfdriver lecd = {
82 NULL, "le", le_md_match, le_attach,
83 DV_IFNET, sizeof(struct le_softc),
84 };
85
86 int leioctl __P((struct ifnet *, u_long, caddr_t));
87 void lestart __P((struct ifnet *));
88 void lewatchdog __P((/* short */));
89 static inline void lewrcsr __P((/* struct le_softc *, u_short, u_short */));
90 static inline u_short lerdcsr __P((/* struct le_softc *, u_short */));
91 void leinit __P((struct le_softc *));
92 void lememinit __P((struct le_softc *));
93 void lereset __P((struct le_softc *));
94 void lestop __P((struct le_softc *));
95 void letint __P((struct le_softc *));
96 void lerint __P((struct le_softc *));
97 void leread __P((struct le_softc *, u_char *, int));
98 struct mbuf *leget __P((u_char *, int, struct ifnet *));
99 void lesetladrf __P((struct arpcom *, u_long *));
100 #ifdef LEDEBUG
101 void recv_print __P((struct le_softc *, int));
102 void xmit_print __P((struct le_softc *, int));
103 #endif
104
105 /*
106 * Inline routines to read and write the LANCE registers.
107 */
108
109 static inline void
110 lewrcsr(sc, regnum, value)
111 struct le_softc *sc;
112 u_short regnum;
113 u_short value;
114 {
115 volatile struct le_regs *regs = sc->sc_regs;
116
117 regs->lereg_addr = regnum;
118 regs->lereg_data = value;
119 }
120
121 static inline u_short
122 lerdcsr(sc, regnum)
123 struct le_softc *sc;
124 u_short regnum;
125 {
126 volatile struct le_regs *regs = sc->sc_regs;
127 u_short value;
128
129 regs->lereg_addr = regnum;
130 value = regs->lereg_data;
131
132 return (value);
133 }
134
135 /*
136 * The probe is done in if_le_subr.c:if_md_match()
137 */
138
139 /*
140 * Interface exists: make available by filling in network interface
141 * record. System will initialize the interface when it is ready
142 * to accept packets. We get the ethernet address here.
143 */
144 void
145 le_attach(parent, self, aux)
146 struct device *parent, *self;
147 void *aux;
148 {
149 struct le_softc *sc = (void *)self;
150 struct confargs *ca = aux;
151 struct ifnet *ifp = &sc->sc_if;
152 int pri;
153 u_int a;
154
155 le_md_attach(parent, self, aux);
156 printf(" hwaddr %s\n", ether_sprintf(sc->sc_enaddr));
157
158 /*
159 * Initialize and attach S/W interface
160 */
161 ifp->if_unit = sc->sc_dev.dv_unit;
162 ifp->if_name = lecd.cd_name;
163 ifp->if_start = lestart;
164 ifp->if_ioctl = leioctl;
165 ifp->if_watchdog = lewatchdog;
166 ifp->if_flags =
167 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
168
169 /* Attach the interface. */
170 if_attach(ifp);
171 ether_ifattach(ifp);
172 #if NBPFILTER > 0
173 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
174 #endif
175 }
176
177 void
178 lereset(sc)
179 struct le_softc *sc;
180 {
181
182 leinit(sc);
183 }
184
185 void
186 lewatchdog(unit)
187 short unit;
188 {
189 struct le_softc *sc = lecd.cd_devs[unit];
190
191 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
192 ++sc->sc_if.if_oerrors;
193 lereset(sc);
194 }
195
196 /* LANCE initialization block set up. */
197 void
198 lememinit(sc)
199 register struct le_softc *sc;
200 {
201 struct ifnet *ifp = &sc->sc_if;
202 int i;
203 void *mem;
204 u_long a;
205
206 /*
207 * At this point we assume that the memory allocated to the Lance is
208 * quadword aligned. If it isn't then the initialisation is going
209 * fail later on.
210 */
211 mem = sc->sc_mem;
212
213 sc->sc_init = mem;
214 #if NBPFILTER > 0
215 if (ifp->if_flags & IFF_PROMISC)
216 sc->sc_init->mode = LE_NORMAL | LE_PROM;
217 else
218 #endif
219 sc->sc_init->mode = LE_NORMAL;
220
221 /* Set the Ethernet address (have to byte-swap) */
222 for (i = 0; i < 6; i += 2) {
223 sc->sc_init->padr[i] = sc->sc_enaddr[i+1];
224 sc->sc_init->padr[i+1] = sc->sc_enaddr[i];
225 }
226 lesetladrf(&sc->sc_ac, sc->sc_init->ladrf);
227 mem += sizeof(struct init_block);
228
229 sc->sc_rd = mem;
230 a = LANCE_ADDR(sc, mem);
231 sc->sc_init->rdra = a;
232 sc->sc_init->rlen = ((a >> 16) & 0xff) | (RLEN << 13);
233 mem += NRBUF * sizeof(struct mds);
234
235 sc->sc_td = mem;
236 a = LANCE_ADDR(sc, mem);
237 sc->sc_init->tdra = a;
238 sc->sc_init->tlen = ((a >> 16) & 0xff) | (TLEN << 13);
239 mem += NTBUF * sizeof(struct mds);
240
241 /*
242 * Set up receive ring descriptors.
243 */
244 sc->sc_rbuf = mem;
245 for (i = 0; i < NRBUF; i++) {
246 a = LANCE_ADDR(sc, mem);
247 sc->sc_rd[i].addr = a;
248 sc->sc_rd[i].flags = ((a >> 16) & 0xff) | LE_OWN;
249 sc->sc_rd[i].bcnt = -BUFSIZE;
250 sc->sc_rd[i].mcnt = 0;
251 mem += BUFSIZE;
252 }
253
254 /*
255 * Set up transmit ring descriptors.
256 */
257 sc->sc_tbuf = mem;
258 for (i = 0; i < NTBUF; i++) {
259 a = LANCE_ADDR(sc, mem);
260 sc->sc_td[i].addr = a;
261 sc->sc_td[i].flags= ((a >> 16) & 0xff);
262 sc->sc_td[i].bcnt = 0xf000;
263 sc->sc_td[i].mcnt = 0;
264 mem += BUFSIZE;
265 }
266
267 #ifdef DIAGNOSTIC
268 if (mem > (sc->sc_mem + MEMSIZE))
269 panic("lememinit: used 0x%x\n", mem - sc->sc_mem);
270 #endif
271 }
272
273 void
274 lestop(sc)
275 struct le_softc *sc;
276 {
277
278 lewrcsr(sc, 0, LE_STOP);
279 }
280
281 /*
282 * Initialization of interface; set up initialization block
283 * and transmit/receive descriptor rings.
284 */
285 void
286 leinit(sc)
287 register struct le_softc *sc;
288 {
289 struct ifnet *ifp = &sc->sc_if;
290 int s;
291 register int timo;
292 u_long a;
293
294 /* Address not known. */
295 if (!ifp->if_addrlist)
296 return;
297
298 s = splimp();
299
300 /* Don't want to get in a weird state. */
301 lewrcsr(sc, 0, LE_STOP);
302 delay(100);
303
304 sc->sc_last_rd = sc->sc_last_td = sc->sc_no_td = 0;
305
306 /* Set up LANCE init block. */
307 lememinit(sc);
308
309 /* Set byte swapping etc. */
310 lewrcsr(sc, 3, LE_CONF3);
311
312 /* Give LANCE the physical address of its init block. */
313 a = LANCE_ADDR(sc, sc->sc_init);
314 lewrcsr(sc, 1, a);
315 lewrcsr(sc, 2, (a >> 16) & 0xff);
316
317 /* Try to initialize the LANCE. */
318 delay(100);
319 lewrcsr(sc, 0, LE_INIT);
320
321 /* Wait for initialization to finish. */
322 for (timo = 1000; timo; timo--)
323 if (lerdcsr(sc, 0) & LE_IDON)
324 break;
325
326 if (lerdcsr(sc, 0) & LE_IDON) {
327 /* Start the LANCE. */
328 lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON);
329 ifp->if_flags |= IFF_RUNNING;
330 ifp->if_flags &= ~IFF_OACTIVE;
331 lestart(ifp);
332 } else
333 printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname);
334
335 (void) splx(s);
336 }
337
338 /*
339 * Controller interrupt.
340 */
341 int
342 leintr(vsc)
343 void *vsc;
344 {
345 register struct le_softc *sc = vsc;
346 register u_short isr;
347
348 isr = lerdcsr(sc, 0);
349 #ifdef LEDEBUG
350 if (sc->sc_debug)
351 printf("%s: leintr entering with isr=%04x\n",
352 sc->sc_dev.dv_xname, isr);
353 #endif
354 if ((isr & LE_INTR) == 0)
355 return 0;
356
357 do {
358 lewrcsr(sc, 0,
359 isr & (LE_INEA | LE_BABL | LE_MISS | LE_MERR |
360 LE_RINT | LE_TINT | LE_IDON));
361 if (isr & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) {
362 if (isr & LE_BABL) {
363 printf("%s: babble\n", sc->sc_dev.dv_xname);
364 sc->sc_if.if_oerrors++;
365 }
366 #if 0
367 if (isr & LE_CERR) {
368 printf("%s: collision error\n", sc->sc_dev.dv_xname);
369 sc->sc_if.if_collisions++;
370 }
371 #endif
372 if (isr & LE_MISS) {
373 #if 0
374 printf("%s: missed packet\n", sc->sc_dev.dv_xname);
375 #endif
376 sc->sc_if.if_ierrors++;
377 }
378 if (isr & LE_MERR) {
379 printf("%s: memory error\n", sc->sc_dev.dv_xname);
380 lereset(sc);
381 goto out;
382 }
383 }
384
385 if ((isr & LE_RXON) == 0) {
386 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
387 sc->sc_if.if_ierrors++;
388 lereset(sc);
389 goto out;
390 }
391 if ((isr & LE_TXON) == 0) {
392 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
393 sc->sc_if.if_oerrors++;
394 lereset(sc);
395 goto out;
396 }
397
398 if (isr & LE_RINT) {
399 /* Reset watchdog timer. */
400 sc->sc_if.if_timer = 0;
401 lerint(sc);
402 }
403 if (isr & LE_TINT) {
404 /* Reset watchdog timer. */
405 sc->sc_if.if_timer = 0;
406 letint(sc);
407 }
408
409 isr = lerdcsr(sc, 0);
410 } while ((isr & LE_INTR) != 0);
411
412 #ifdef LEDEBUG
413 if (sc->sc_debug)
414 printf("%s: leintr returning with isr=%04x\n",
415 sc->sc_dev.dv_xname, isr);
416 #endif
417
418 out:
419 return 1;
420 }
421
422 #define NEXTTDS \
423 if (++tmd == NTBUF) tmd=0, cdm=sc->sc_td; else ++cdm
424
425 /*
426 * Setup output on interface.
427 * Get another datagram to send off of the interface queue, and map it to the
428 * interface before starting the output.
429 * Called only at splimp or interrupt level.
430 */
431 void
432 lestart(ifp)
433 struct ifnet *ifp;
434 {
435 register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
436 register int tmd;
437 volatile struct mds *cdm;
438 struct mbuf *m0, *m;
439 u_char *buffer;
440 int len;
441
442 if ((sc->sc_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
443 IFF_RUNNING)
444 return;
445
446 tmd = sc->sc_last_td;
447 cdm = &sc->sc_td[tmd];
448
449 for (;;) {
450 if (sc->sc_no_td >= NTBUF) {
451 sc->sc_if.if_flags |= IFF_OACTIVE;
452 #ifdef LEDEBUG
453 if (sc->sc_debug)
454 printf("no_td = %d, last_td = %d\n", sc->sc_no_td,
455 sc->sc_last_td);
456 #endif
457 break;
458 }
459
460 #ifdef LEDEBUG
461 if (cdm->flags & LE_OWN) {
462 sc->sc_if.if_flags |= IFF_OACTIVE;
463 printf("missing buffer, no_td = %d, last_td = %d\n",
464 sc->sc_no_td, sc->sc_last_td);
465 }
466 #endif
467
468 IF_DEQUEUE(&sc->sc_if.if_snd, m);
469 if (!m)
470 break;
471
472 ++sc->sc_no_td;
473
474 /*
475 * Copy the mbuf chain into the transmit buffer.
476 */
477 buffer = sc->sc_tbuf + (BUFSIZE * sc->sc_last_td);
478 len = 0;
479 for (m0 = m; m; m = m->m_next) {
480 bcopy(mtod(m, caddr_t), buffer, m->m_len);
481 buffer += m->m_len;
482 len += m->m_len;
483 }
484
485 #ifdef LEDEBUG
486 if (len > ETHER_MAX_LEN)
487 printf("packet length %d\n", len);
488 #endif
489
490 #if NBPFILTER > 0
491 if (sc->sc_if.if_bpf)
492 bpf_mtap(sc->sc_if.if_bpf, m0);
493 #endif
494
495 m_freem(m0);
496 len = max(len, ETHER_MIN_LEN);
497
498 /*
499 * Init transmit registers, and set transmit start flag.
500 */
501 cdm->bcnt = -len;
502 cdm->mcnt = 0;
503 cdm->flags |= LE_OWN | LE_STP | LE_ENP;
504
505 #ifdef LEDEBUG
506 if (sc->sc_debug)
507 xmit_print(sc, sc->sc_last_td);
508 #endif
509
510 lewrcsr(sc, 0, LE_INEA | LE_TDMD);
511
512 NEXTTDS;
513 }
514
515 sc->sc_last_td = tmd;
516 }
517
518 void
519 letint(sc)
520 struct le_softc *sc;
521 {
522 register int tmd = (sc->sc_last_td - sc->sc_no_td + NTBUF) % NTBUF;
523 volatile struct mds *cdm;
524
525 cdm = &sc->sc_td[tmd];
526 if (cdm->flags & LE_OWN) {
527 /* Race condition with loop below. */
528 #ifdef LEDEBUG
529 if (sc->sc_debug)
530 printf("%s: extra tint\n", sc->sc_dev.dv_xname);
531 #endif
532 return;
533 }
534
535 sc->sc_if.if_flags &= ~IFF_OACTIVE;
536
537 do {
538 if (sc->sc_no_td <= 0)
539 break;
540 #ifdef LEDEBUG
541 if (sc->sc_debug)
542 printf("trans cdm = %x\n", cdm);
543 #endif
544 sc->sc_if.if_opackets++;
545 --sc->sc_no_td;
546 if (cdm->mcnt & (LE_TBUFF | LE_UFLO | LE_LCOL | LE_LCAR | LE_RTRY)) {
547 if (cdm->mcnt & LE_TBUFF)
548 printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname);
549 if ((cdm->mcnt & (LE_TBUFF | LE_UFLO)) == LE_UFLO)
550 printf("%s: underflow\n", sc->sc_dev.dv_xname);
551 if (cdm->mcnt & LE_UFLO) {
552 lereset(sc);
553 return;
554 }
555 #if 0
556 if (cdm->mcnt & LE_LCOL) {
557 printf("%s: late collision\n", sc->sc_dev.dv_xname);
558 sc->sc_if.if_collisions++;
559 }
560 if (cdm->mcnt & LE_LCAR)
561 printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
562 if (cdm->mcnt & LE_RTRY) {
563 printf("%s: excessive collisions, tdr %d\n",
564 sc->sc_dev.dv_xname, cdm->flags & 0x1ff);
565 sc->sc_if.if_collisions += 16;
566 }
567 #endif
568 } else if (cdm->flags & LE_ONE)
569 sc->sc_if.if_collisions++;
570 else if (cdm->flags & LE_MORE)
571 /* Real number is unknown. */
572 sc->sc_if.if_collisions += 2;
573 NEXTTDS;
574 } while ((cdm->flags & LE_OWN) == 0);
575
576 lestart(&sc->sc_if);
577 }
578
579 #define NEXTRDS \
580 if (++rmd == NRBUF) rmd=0, cdm=sc->sc_rd; else ++cdm
581
582 /* only called from one place, so may as well integrate */
583 void
584 lerint(sc)
585 struct le_softc *sc;
586 {
587 register int rmd = sc->sc_last_rd;
588 volatile struct mds *cdm;
589
590 cdm = &sc->sc_rd[rmd];
591 if (cdm->flags & LE_OWN) {
592 /* Race condition with loop below. */
593 #ifdef LEDEBUG
594 if (sc->sc_debug)
595 printf("%s: extra rint\n", sc->sc_dev.dv_xname);
596 #endif
597 return;
598 }
599
600 /* Process all buffers with valid data. */
601 do {
602 if (cdm->flags & LE_ERR) {
603 #ifdef LEDEBUG
604 /*
605 * XXX - These happen a LOT on the Sun3/50 so
606 * it is really NOT appropriate to print them.
607 */
608 printf("%s: error, cdm->flags=%b\n",
609 sc->sc_dev.dv_xname, cdm->flags, RMD_BITS);
610 #endif
611 sc->sc_if.if_ierrors++;
612 } else if (cdm->flags & (LE_STP | LE_ENP) != (LE_STP | LE_ENP)) {
613 do {
614 cdm->mcnt = 0;
615 cdm->flags |= LE_OWN;
616 NEXTRDS;
617 } while ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) == 0);
618 sc->sc_last_rd = rmd;
619 printf("%s: chained buffer\n", sc->sc_dev.dv_xname);
620 if ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) != LE_ENP) {
621 lereset(sc);
622 return;
623 }
624 } else {
625 #ifdef LEDEBUG
626 if (sc->sc_debug)
627 recv_print(sc, sc->sc_last_rd);
628 #endif
629 leread(sc, sc->sc_rbuf + (BUFSIZE * rmd),
630 (int)cdm->mcnt);
631 sc->sc_if.if_ipackets++;
632 }
633
634 cdm->bcnt = -BUFSIZE;
635 cdm->mcnt = 0;
636 cdm->flags |= LE_OWN;
637 NEXTRDS;
638 #ifdef LEDEBUG
639 if (sc->sc_debug)
640 printf("sc->sc_last_rd = %x, cdm = %x\n",
641 sc->sc_last_rd, cdm);
642 #endif
643 } while ((cdm->flags & LE_OWN) == 0);
644
645 sc->sc_last_rd = rmd;
646 }
647
648 /*
649 * Pass a packet to the higher levels.
650 */
651 void
652 leread(sc, buf, len)
653 register struct le_softc *sc;
654 u_char *buf;
655 int len;
656 {
657 struct ifnet *ifp;
658 struct mbuf *m;
659 struct ether_header *eh;
660
661 len -= 4;
662 if (len <= 0)
663 return;
664
665 /* Pull packet off interface. */
666 ifp = &sc->sc_if;
667 m = leget(buf, len, ifp);
668 if (m == 0)
669 return;
670
671 /* We assume that the header fit entirely in one mbuf. */
672 eh = mtod(m, struct ether_header *);
673
674 #if NBPFILTER > 0
675 /*
676 * Check if there's a BPF listener on this interface.
677 * If so, hand off the raw packet to BPF.
678 */
679 if (ifp->if_bpf) {
680 bpf_mtap(ifp->if_bpf, m);
681
682 /*
683 * Note that the interface cannot be in promiscuous mode if
684 * there are no BPF listeners. And if we are in promiscuous
685 * mode, we have to check if this packet is really ours.
686 */
687 if ((ifp->if_flags & IFF_PROMISC) &&
688 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
689 bcmp(eh->ether_dhost, sc->sc_enaddr,
690 sizeof(eh->ether_dhost)) != 0) {
691 m_freem(m);
692 return;
693 }
694 }
695 #endif
696
697 /* We assume that the header fit entirely in one mbuf. */
698 m->m_pkthdr.len -= sizeof(*eh);
699 m->m_len -= sizeof(*eh);
700 m->m_data += sizeof(*eh);
701
702 ether_input(ifp, eh, m);
703 }
704
705 /*
706 * Supporting routines
707 */
708
709 /*
710 * Pull data off an interface.
711 * Len is length of data, with local net header stripped.
712 * We copy the data into mbufs. When full cluster sized units are present
713 * we copy into clusters.
714 */
715 struct mbuf *
716 leget(buf, totlen, ifp)
717 u_char *buf;
718 int totlen;
719 struct ifnet *ifp;
720 {
721 struct mbuf *top, **mp, *m;
722 int len;
723
724 MGETHDR(m, M_DONTWAIT, MT_DATA);
725 if (m == 0)
726 return 0;
727 m->m_pkthdr.rcvif = ifp;
728 m->m_pkthdr.len = totlen;
729 len = MHLEN;
730 top = 0;
731 mp = ⊤
732
733 while (totlen > 0) {
734 if (top) {
735 MGET(m, M_DONTWAIT, MT_DATA);
736 if (m == 0) {
737 m_freem(top);
738 return 0;
739 }
740 len = MLEN;
741 }
742 if (totlen >= MINCLSIZE) {
743 MCLGET(m, M_DONTWAIT);
744 if (m->m_flags & M_EXT)
745 len = MCLBYTES;
746 }
747 m->m_len = len = min(totlen, len);
748 bcopy((caddr_t)buf, mtod(m, caddr_t), len);
749 buf += len;
750 totlen -= len;
751 *mp = m;
752 mp = &m->m_next;
753 }
754
755 return top;
756 }
757
758 /*
759 * Process an ioctl request.
760 */
761 int
762 leioctl(ifp, cmd, data)
763 register struct ifnet *ifp;
764 u_long cmd;
765 caddr_t data;
766 {
767 struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
768 struct ifaddr *ifa = (struct ifaddr *)data;
769 struct ifreq *ifr = (struct ifreq *)data;
770 int s, error = 0;
771
772 s = splimp();
773
774 switch (cmd) {
775
776 case SIOCSIFADDR:
777 ifp->if_flags |= IFF_UP;
778
779 switch (ifa->ifa_addr->sa_family) {
780 #ifdef INET
781 case AF_INET:
782 leinit(sc);
783 arp_ifinit(&sc->sc_ac, ifa);
784 break;
785 #endif
786 #ifdef NS
787 /* XXX - This code is probably wrong. */
788 case AF_NS:
789 {
790 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
791
792 if (ns_nullhost(*ina))
793 ina->x_host =
794 *(union ns_host *)(sc->sc_enaddr);
795 else
796 bcopy(ina->x_host.c_host,
797 sc->sc_enaddr,
798 sizeof(sc->sc_enaddr));
799 /* Set new address. */
800 leinit(sc);
801 break;
802 }
803 #endif
804 default:
805 leinit(sc);
806 break;
807 }
808 break;
809
810 case SIOCSIFFLAGS:
811 /*
812 * If interface is marked down and it is running, then stop it
813 */
814 if ((ifp->if_flags & IFF_UP) == 0 &&
815 (ifp->if_flags & IFF_RUNNING) != 0) {
816 /*
817 * If interface is marked down and it is running, then
818 * stop it.
819 */
820 lestop(sc);
821 ifp->if_flags &= ~IFF_RUNNING;
822 } else if ((ifp->if_flags & IFF_UP) != 0 &&
823 (ifp->if_flags & IFF_RUNNING) == 0) {
824 /*
825 * If interface is marked up and it is stopped, then
826 * start it.
827 */
828 leinit(sc);
829 } else {
830 /*
831 * Reset the interface to pick up changes in any other
832 * flags that affect hardware registers.
833 */
834 /*lestop(sc);*/
835 leinit(sc);
836 }
837 #ifdef LEDEBUG
838 if (ifp->if_flags & IFF_DEBUG)
839 sc->sc_debug = 1;
840 else
841 sc->sc_debug = 0;
842 #endif
843 break;
844
845 case SIOCADDMULTI:
846 case SIOCDELMULTI:
847 error = (cmd == SIOCADDMULTI) ?
848 ether_addmulti(ifr, &sc->sc_ac):
849 ether_delmulti(ifr, &sc->sc_ac);
850
851 if (error == ENETRESET) {
852 /*
853 * Multicast list has changed; set the hardware filter
854 * accordingly.
855 */
856 leinit(sc);
857 error = 0;
858 }
859 break;
860
861 default:
862 error = EINVAL;
863 }
864 (void) splx(s);
865 return error;
866 }
867
868 #ifdef LEDEBUG
869 void
870 recv_print(sc, no)
871 struct le_softc *sc;
872 int no;
873 {
874 struct mds *rmd;
875 int i, printed = 0;
876 u_short len;
877
878 rmd = &sc->sc_rd[no];
879 len = rmd->mcnt;
880 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
881 len);
882 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
883 for (i = 0; i < len; i++) {
884 if (!printed) {
885 printed = 1;
886 printf("%s: data: ", sc->sc_dev.dv_xname);
887 }
888 printf("%x ", *(sc->sc_rbuf + (BUFSIZE*no) + i));
889 }
890 if (printed)
891 printf("\n");
892 }
893
894 void
895 xmit_print(sc, no)
896 struct le_softc *sc;
897 int no;
898 {
899 struct mds *rmd;
900 int i, printed=0;
901 u_short len;
902
903 rmd = &sc->sc_td[no];
904 len = -rmd->bcnt;
905 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
906 len);
907 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
908 printf("%s: addr %x, flags %x, bcnt %x, mcnt %x\n",
909 sc->sc_dev.dv_xname, rmd->addr, rmd->flags, rmd->bcnt, rmd->mcnt);
910 for (i = 0; i < len; i++) {
911 if (!printed) {
912 printed = 1;
913 printf("%s: data: ", sc->sc_dev.dv_xname);
914 }
915 printf("%x ", *(sc->sc_tbuf + (BUFSIZE*no) + i));
916 }
917 if (printed)
918 printf("\n");
919 }
920 #endif /* LEDEBUG */
921
922 /*
923 * Set up the logical address filter.
924 */
925 void
926 lesetladrf(ac, af)
927 struct arpcom *ac;
928 u_long *af;
929 {
930 struct ifnet *ifp = &ac->ac_if;
931 struct ether_multi *enm;
932 register u_char *cp, c;
933 register u_long crc;
934 register int i, len;
935 struct ether_multistep step;
936
937 /*
938 * Set up multicast address filter by passing all multicast addresses
939 * through a crc generator, and then using the high order 6 bits as an
940 * index into the 64 bit logical address filter. The high order bit
941 * selects the word, while the rest of the bits select the bit within
942 * the word.
943 */
944
945 if (ifp->if_flags & IFF_PROMISC) {
946 ifp->if_flags |= IFF_ALLMULTI;
947 af[0] = af[1] = 0xffffffff;
948 return;
949 }
950
951 af[0] = af[1] = 0;
952 ETHER_FIRST_MULTI(step, ac, enm);
953 while (enm != NULL) {
954 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
955 sizeof(enm->enm_addrlo)) != 0) {
956 /*
957 * We must listen to a range of multicast addresses.
958 * For now, just accept all multicasts, rather than
959 * trying to set only those filter bits needed to match
960 * the range. (At this time, the only use of address
961 * ranges is for IP multicast routing, for which the
962 * range is big enough to require all bits set.)
963 */
964 ifp->if_flags |= IFF_ALLMULTI;
965 af[0] = af[1] = 0xffffffff;
966 return;
967 }
968
969 cp = enm->enm_addrlo;
970 crc = 0xffffffff;
971 for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
972 c = *cp++;
973 for (i = 8; --i >= 0;) {
974 if ((crc & 0x01) ^ (c & 0x01)) {
975 crc >>= 1;
976 crc ^= 0x6db88320 | 0x80000000;
977 } else
978 crc >>= 1;
979 c >>= 1;
980 }
981 }
982 /* Just want the 6 most significant bits. */
983 crc >>= 26;
984
985 /* Turn on the corresponding bit in the filter. */
986 af[crc >> 5] |= 1 << ((crc & 0x1f) ^ 0);
987
988 ETHER_NEXT_MULTI(step, enm);
989 }
990 ifp->if_flags &= ~IFF_ALLMULTI;
991 }
992