if_le.c revision 1.23 1 /* $NetBSD: if_le.c,v 1.23 1995/12/02 18:22:02 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)if_le.c 7.6 (Berkeley) 5/8/91
36 */
37
38 #include "le.h"
39 #if NLE > 0
40
41 #include "bpfilter.h"
42
43 /*
44 * AMD 7990 LANCE
45 */
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/mbuf.h>
50 #include <sys/buf.h>
51 #include <sys/socket.h>
52 #include <sys/syslog.h>
53 #include <sys/ioctl.h>
54 #include <sys/malloc.h>
55 #include <sys/errno.h>
56
57 #include <net/if.h>
58 #include <net/netisr.h>
59 #include <net/route.h>
60 #if NBPFILTER > 0
61 #include <net/bpf.h>
62 #include <net/bpfdesc.h>
63 #endif
64
65 #ifdef INET
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/in_var.h>
69 #include <netinet/ip.h>
70 #include <netinet/if_ether.h>
71 #endif
72
73 #ifdef NS
74 #include <netns/ns.h>
75 #include <netns/ns_if.h>
76 #endif
77
78 #include <machine/cpu.h>
79 #include <machine/mtpr.h>
80 #include <hp300/hp300/isr.h>
81 #ifdef USELEDS
82 #include <hp300/hp300/led.h>
83 #endif
84
85 #include <hp300/dev/device.h>
86 #include <hp300/dev/if_lereg.h>
87
88
89 #define ETHER_MIN_LEN 64
90 #define ETHER_MAX_LEN 1518
91 #define ETHER_ADDR_LEN 6
92
93
94 /* offsets for: ID, REGS, MEM, NVRAM */
95 int lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
96
97 struct isr le_isr[NLE];
98
99 /*
100 * Ethernet software status per interface.
101 *
102 * Each interface is referenced by a network interface structure,
103 * arpcom.ac_if, which the routing code uses to locate the interface.
104 * This structure contains the output queue for the interface, its address, ...
105 */
106 struct le_softc {
107 struct hp_device *sc_hd;
108 struct arpcom sc_arpcom; /* common Ethernet structures */
109 struct lereg0 *sc_r0; /* DIO registers */
110 struct lereg1 *sc_r1; /* LANCE registers */
111 void *sc_mem;
112 struct init_block *sc_init;
113 struct mds *sc_rd, *sc_td;
114 u_char *sc_rbuf, *sc_tbuf;
115 int sc_last_rd, sc_last_td;
116 int sc_no_td;
117 #ifdef LEDEBUG
118 int sc_debug;
119 #endif
120 } le_softc[NLE];
121
122 int leintr __P((int));
123 int leioctl __P((struct ifnet *, u_long, caddr_t));
124 void lestart __P((struct ifnet *));
125 void lewatchdog __P((int));
126 static inline void lewrcsr __P((/* struct le_softc *, u_short, u_short */));
127 static inline u_short lerdcsr __P((/* struct le_softc *, u_short */));
128 void leinit __P((struct le_softc *));
129 void lememinit __P((struct le_softc *));
130 void lereset __P((struct le_softc *));
131 void lestop __P((struct le_softc *));
132 void letint __P((int));
133 void lerint __P((int));
134 void leread __P((struct le_softc *, u_char *, int));
135 struct mbuf *leget __P((u_char *, int, struct ifnet *));
136 #ifdef LEDEBUG
137 void recv_print __P((struct le_softc *, int));
138 void xmit_print __P((struct le_softc *, int));
139 #endif
140 void lesetladrf __P((struct arpcom *, u_long *));
141
142 int lematch __P((struct hp_device *));
143 void leattach __P((struct hp_device *));
144
145 struct driver ledriver = {
146 lematch, leattach, "le",
147 };
148
149 static inline void
150 lewrcsr(sc, port, val)
151 struct le_softc *sc;
152 register u_short port;
153 register u_short val;
154 {
155 register struct lereg0 *ler0 = sc->sc_r0;
156 register struct lereg1 *ler1 = sc->sc_r1;
157
158 do {
159 ler1->ler1_rap = port;
160 } while ((ler0->ler0_status & LE_ACK) == 0);
161 do {
162 ler1->ler1_rdp = val;
163 } while ((ler0->ler0_status & LE_ACK) == 0);
164 }
165
166 static inline u_short
167 lerdcsr(sc, port)
168 struct le_softc *sc;
169 register u_short port;
170 {
171 register struct lereg0 *ler0 = sc->sc_r0;
172 register struct lereg1 *ler1 = sc->sc_r1;
173 register u_short val;
174
175 do {
176 ler1->ler1_rap = port;
177 } while ((ler0->ler0_status & LE_ACK) == 0);
178 do {
179 val = ler1->ler1_rdp;
180 } while ((ler0->ler0_status & LE_ACK) == 0);
181 return (val);
182 }
183
184 int
185 lematch(hd)
186 struct hp_device *hd;
187 {
188 register struct lereg0 *ler0;
189 struct le_softc *sc = &le_softc[hd->hp_unit];
190
191 ler0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
192 if (ler0->ler0_id != LEID)
193 return (0);
194
195 hd->hp_ipl = LE_IPL(ler0->ler0_status);
196 sc->sc_hd = hd;
197
198 return (1);
199 }
200
201 /*
202 * Interface exists: make available by filling in network interface
203 * record. System will initialize the interface when it is ready
204 * to accept packets.
205 */
206 void
207 leattach(hd)
208 struct hp_device *hd;
209 {
210 register struct lereg0 *ler0;
211 struct le_softc *sc = &le_softc[hd->hp_unit];
212 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
213 char *cp;
214 int i;
215
216 ler0 = sc->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
217 sc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
218 sc->sc_mem = (void *)(lestd[2] + (int)hd->hp_addr);
219 le_isr[hd->hp_unit].isr_intr = leintr;
220 le_isr[hd->hp_unit].isr_ipl = hd->hp_ipl;
221 le_isr[hd->hp_unit].isr_arg = hd->hp_unit;
222 ler0->ler0_id = 0xFF;
223 DELAY(100);
224
225 /*
226 * Read the ethernet address off the board, one nibble at a time.
227 */
228 cp = (char *)(lestd[3] + (int)hd->hp_addr);
229 for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) {
230 sc->sc_arpcom.ac_enaddr[i] = (*++cp & 0xF) << 4;
231 cp++;
232 sc->sc_arpcom.ac_enaddr[i] |= *++cp & 0xF;
233 cp++;
234 }
235 printf(": hardware address %s\n",
236 ether_sprintf(sc->sc_arpcom.ac_enaddr));
237
238 isrlink(&le_isr[hd->hp_unit]);
239 ler0->ler0_status = LE_IE;
240
241 ifp->if_unit = hd->hp_unit;
242 ifp->if_name = "le";
243 ifp->if_output = ether_output;
244 ifp->if_start = lestart;
245 ifp->if_ioctl = leioctl;
246 ifp->if_watchdog = lewatchdog;
247 ifp->if_flags =
248 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
249
250 if_attach(ifp);
251 ether_ifattach(ifp);
252
253 #if NBPFILTER > 0
254 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
255 #endif
256 }
257
258 void
259 lereset(sc)
260 struct le_softc *sc;
261 {
262
263 leinit(sc);
264 }
265
266 void
267 lewatchdog(unit)
268 int unit;
269 {
270 struct le_softc *sc = &le_softc[unit];
271
272 log(LOG_ERR, "%s: device timeout\n", sc->sc_hd->hp_xname);
273 ++sc->sc_arpcom.ac_if.if_oerrors;
274
275 lereset(sc);
276 }
277
278 #define LANCE_ADDR(sc, a) \
279 ((u_long)(a) - (u_long)sc->sc_mem)
280
281 /* LANCE initialization block set up. */
282 void
283 lememinit(sc)
284 register struct le_softc *sc;
285 {
286 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
287 int i;
288 void *mem;
289 u_long a;
290
291 /*
292 * At this point we assume that the memory allocated to the Lance is
293 * quadword aligned. If it isn't then the initialisation is going
294 * fail later on.
295 */
296 mem = sc->sc_mem;
297
298 sc->sc_init = mem;
299 #if NBPFILTER > 0
300 if (ifp->if_flags & IFF_PROMISC)
301 sc->sc_init->mode = LE_NORMAL | LE_PROM;
302 else
303 #endif
304 sc->sc_init->mode = LE_NORMAL;
305 for (i = 0; i < ETHER_ADDR_LEN; i++)
306 sc->sc_init->padr[i] = sc->sc_arpcom.ac_enaddr[i^1];
307 lesetladrf(&sc->sc_arpcom, sc->sc_init->ladrf);
308 mem += sizeof(struct init_block);
309
310 sc->sc_rd = mem;
311 a = LANCE_ADDR(sc, mem);
312 sc->sc_init->rdra = a;
313 sc->sc_init->rlen = ((a >> 16) & 0xff) | (RLEN << 13);
314 mem += NRBUF * sizeof(struct mds);
315
316 sc->sc_td = mem;
317 a = LANCE_ADDR(sc, mem);
318 sc->sc_init->tdra = a;
319 sc->sc_init->tlen = ((a >> 16) & 0xff) | (TLEN << 13);
320 mem += NTBUF * sizeof(struct mds);
321
322 /*
323 * Set up receive ring descriptors.
324 */
325 sc->sc_rbuf = mem;
326 for (i = 0; i < NRBUF; i++) {
327 a = LANCE_ADDR(sc, mem);
328 sc->sc_rd[i].addr = a;
329 sc->sc_rd[i].flags = ((a >> 16) & 0xff) | LE_OWN;
330 sc->sc_rd[i].bcnt = -BUFSIZE;
331 sc->sc_rd[i].mcnt = 0;
332 mem += BUFSIZE;
333 }
334
335 /*
336 * Set up transmit ring descriptors.
337 */
338 sc->sc_tbuf = mem;
339 for (i = 0; i < NTBUF; i++) {
340 a = LANCE_ADDR(sc, mem);
341 sc->sc_td[i].addr = a;
342 sc->sc_td[i].flags= ((a >> 16) & 0xff);
343 sc->sc_td[i].bcnt = 0xf000;
344 sc->sc_td[i].mcnt = 0;
345 mem += BUFSIZE;
346 }
347 }
348
349 void
350 lestop(sc)
351 struct le_softc *sc;
352 {
353
354 lewrcsr(sc, 0, LE_STOP);
355 }
356
357 /*
358 * Initialization of interface; set up initialization block
359 * and transmit/receive descriptor rings.
360 */
361 void
362 leinit(sc)
363 register struct le_softc *sc;
364 {
365 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
366 int s;
367 register int timo;
368 u_long a;
369
370 s = splimp();
371
372 /* Don't want to get in a weird state. */
373 lewrcsr(sc, 0, LE_STOP);
374 DELAY(100);
375
376 sc->sc_last_rd = sc->sc_last_td = sc->sc_no_td = 0;
377
378 /* Set up LANCE init block. */
379 lememinit(sc);
380
381 /* Turn on byte swapping. */
382 lewrcsr(sc, 3, LE_BSWP);
383
384 /* Give LANCE the physical address of its init block. */
385 a = LANCE_ADDR(sc, sc->sc_init);
386 lewrcsr(sc, 1, a);
387 lewrcsr(sc, 2, (a >> 16) & 0xff);
388
389 /* Try to initialize the LANCE. */
390 DELAY(100);
391 lewrcsr(sc, 0, LE_INIT);
392
393 /* Wait for initialization to finish. */
394 for (timo = 100000; timo; timo--)
395 if (lerdcsr(sc, 0) & LE_IDON)
396 break;
397
398 if (lerdcsr(sc, 0) & LE_IDON) {
399 /* Start the LANCE. */
400 lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON);
401 ifp->if_flags |= IFF_RUNNING;
402 ifp->if_flags &= ~IFF_OACTIVE;
403 lestart(ifp);
404 } else
405 printf("%s: card failed to initialize\n", sc->sc_hd->hp_xname);
406
407 (void) splx(s);
408 }
409
410 /*
411 * Controller interrupt.
412 */
413 int
414 leintr(unit)
415 int unit;
416 {
417 register struct le_softc *sc = &le_softc[unit];
418 register u_short isr;
419
420 isr = lerdcsr(sc, 0);
421 #ifdef LEDEBUG
422 if (sc->sc_debug)
423 printf("%s: leintr entering with isr=%04x\n",
424 sc->sc_hd->hp_xname, isr);
425 #endif
426 if ((isr & LE_INTR) == 0)
427 return 0;
428
429 do {
430 lewrcsr(sc, 0,
431 isr & (LE_INEA | LE_BABL | LE_MISS | LE_MERR |
432 LE_RINT | LE_TINT | LE_IDON));
433 if (isr & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) {
434 if (isr & LE_BABL) {
435 printf("%s: BABL\n", sc->sc_hd->hp_xname);
436 sc->sc_arpcom.ac_if.if_oerrors++;
437 }
438 #if 0
439 if (isr & LE_CERR) {
440 printf("%s: CERR\n", sc->sc_hd->hp_xname);
441 sc->sc_arpcom.ac_if.if_collisions++;
442 }
443 #endif
444 if (isr & LE_MISS) {
445 #if 0
446 printf("%s: MISS\n", sc->sc_hd->hp_xname);
447 #endif
448 sc->sc_arpcom.ac_if.if_ierrors++;
449 }
450 if (isr & LE_MERR) {
451 printf("%s: MERR\n", sc->sc_hd->hp_xname);
452 lereset(sc);
453 goto out;
454 }
455 }
456
457 if ((isr & LE_RXON) == 0) {
458 printf("%s: receiver disabled\n", sc->sc_hd->hp_xname);
459 sc->sc_arpcom.ac_if.if_ierrors++;
460 lereset(sc);
461 goto out;
462 }
463 if ((isr & LE_TXON) == 0) {
464 printf("%s: transmitter disabled\n",
465 sc->sc_hd->hp_xname);
466 sc->sc_arpcom.ac_if.if_oerrors++;
467 lereset(sc);
468 goto out;
469 }
470
471 if (isr & LE_RINT) {
472 /* Reset watchdog timer. */
473 sc->sc_arpcom.ac_if.if_timer = 0;
474 lerint(unit);
475 }
476 if (isr & LE_TINT) {
477 /* Reset watchdog timer. */
478 sc->sc_arpcom.ac_if.if_timer = 0;
479 letint(unit);
480 }
481
482 isr = lerdcsr(sc, 0);
483 } while ((isr & LE_INTR) != 0);
484
485 #ifdef LEDEBUG
486 if (sc->sc_debug)
487 printf("%s: leintr returning with isr=%04x\n",
488 sc->sc_hd->hp_xname, isr);
489 #endif
490
491 out:
492 return 1;
493 }
494
495 #define NEXTTDS \
496 if (++tmd == NTBUF) tmd=0, cdm=sc->sc_td; else ++cdm
497
498 /*
499 * Setup output on interface.
500 * Get another datagram to send off of the interface queue, and map it to the
501 * interface before starting the output.
502 * Called only at splimp or interrupt level.
503 */
504 void
505 lestart(ifp)
506 struct ifnet *ifp;
507 {
508 register struct le_softc *sc = &le_softc[ifp->if_unit];
509 register int tmd;
510 struct mds *cdm;
511 struct mbuf *m0, *m;
512 u_char *buffer;
513 int len;
514
515 if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
516 IFF_RUNNING)
517 return;
518
519 tmd = sc->sc_last_td;
520 cdm = &sc->sc_td[tmd];
521
522 for (;;) {
523 if (sc->sc_no_td >= NTBUF) {
524 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
525 #ifdef LEDEBUG
526 if (sc->sc_debug)
527 printf("no_td = %d, last_td = %d\n", sc->sc_no_td,
528 sc->sc_last_td);
529 #endif
530 break;
531 }
532
533 #ifdef LEDEBUG
534 if (cdm->flags & LE_OWN) {
535 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
536 printf("missing buffer, no_td = %d, last_td = %d\n",
537 sc->sc_no_td, sc->sc_last_td);
538 }
539 #endif
540
541 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
542 if (!m)
543 break;
544
545 ++sc->sc_no_td;
546
547 /*
548 * Copy the mbuf chain into the transmit buffer.
549 */
550 buffer = sc->sc_tbuf + (BUFSIZE * sc->sc_last_td);
551 len = 0;
552 for (m0 = m; m; m = m->m_next) {
553 bcopy(mtod(m, caddr_t), buffer, m->m_len);
554 buffer += m->m_len;
555 len += m->m_len;
556 }
557
558 #ifdef LEDEBUG
559 if (len > ETHER_MAX_LEN)
560 printf("packet length %d\n", len);
561 #endif
562
563 #if NBPFILTER > 0
564 if (sc->sc_arpcom.ac_if.if_bpf)
565 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
566 #endif
567
568 m_freem(m0);
569 len = max(len, ETHER_MIN_LEN);
570
571 /*
572 * Init transmit registers, and set transmit start flag.
573 */
574 cdm->bcnt = -len;
575 cdm->mcnt = 0;
576 cdm->flags |= LE_OWN | LE_STP | LE_ENP;
577
578 #ifdef LEDEBUG
579 if (sc->sc_debug)
580 xmit_print(sc, sc->sc_last_td);
581 #endif
582
583 lewrcsr(sc, 0, LE_INEA | LE_TDMD);
584
585 NEXTTDS;
586 }
587
588 sc->sc_last_td = tmd;
589 }
590
591 void
592 letint(unit)
593 int unit;
594 {
595 register struct le_softc *sc = &le_softc[unit];
596 register int tmd = (sc->sc_last_td - sc->sc_no_td + NTBUF) % NTBUF;
597 struct mds *cdm = &sc->sc_td[tmd];
598
599 #ifdef USELEDS
600 if (inledcontrol == 0)
601 ledcontrol(0, 0, LED_LANXMT);
602 #endif
603
604 if (cdm->flags & LE_OWN) {
605 /* Race condition with loop below. */
606 #ifdef LEDEBUG
607 if (sc->sc_debug)
608 printf("%s: extra tint\n", sc->sc_hd->hp_xname);
609 #endif
610 return;
611 }
612
613 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
614
615 do {
616 if (sc->sc_no_td <= 0)
617 break;
618 #ifdef LEDEBUG
619 if (sc->sc_debug)
620 printf("trans cdm = %x\n", cdm);
621 #endif
622 sc->sc_arpcom.ac_if.if_opackets++;
623 --sc->sc_no_td;
624 if (cdm->mcnt & (LE_TBUFF | LE_UFLO | LE_LCOL | LE_LCAR | LE_RTRY)) {
625 if (cdm->mcnt & LE_TBUFF)
626 printf("%s: TBUFF\n", sc->sc_hd->hp_xname);
627 if ((cdm->mcnt & (LE_TBUFF | LE_UFLO)) == LE_UFLO)
628 printf("%s: UFLO\n", sc->sc_hd->hp_xname);
629 if (cdm->mcnt & LE_UFLO) {
630 lereset(sc);
631 return;
632 }
633 #if 0
634 if (cdm->mcnt & LE_LCOL) {
635 printf("%s: late collision\n",
636 sc->sc_hd->hp_xname);
637 sc->sc_arpcom.ac_if.if_collisions++;
638 }
639 if (cdm->mcnt & LE_LCAR)
640 printf("%s: lost carrier\n",
641 sc->sc_hd->hp_xname);
642 if (cdm->mcnt & LE_RTRY) {
643 printf("%s: excessive collisions, tdr %d\n",
644 sc->sc_hd->hp_xname, cdm->mcnt & 0x1ff);
645 sc->sc_arpcom.ac_if.if_collisions += 16;
646 }
647 #endif
648 } else if (cdm->flags & LE_ONE)
649 sc->sc_arpcom.ac_if.if_collisions++;
650 else if (cdm->flags & LE_MORE)
651 /* Real number is unknown. */
652 sc->sc_arpcom.ac_if.if_collisions += 2;
653 NEXTTDS;
654 } while ((cdm->flags & LE_OWN) == 0);
655
656 lestart(&sc->sc_arpcom.ac_if);
657 }
658
659 #define NEXTRDS \
660 if (++rmd == NRBUF) rmd=0, cdm=sc->sc_rd; else ++cdm
661
662 /* only called from one place, so may as well integrate */
663 void
664 lerint(unit)
665 int unit;
666 {
667 register struct le_softc *sc = &le_softc[unit];
668 register int rmd = sc->sc_last_rd;
669 struct mds *cdm = &sc->sc_rd[rmd];
670
671 #ifdef USELEDS
672 if (inledcontrol == 0)
673 ledcontrol(0, 0, LED_LANRCV);
674 #endif
675
676 if (cdm->flags & LE_OWN) {
677 /* Race condition with loop below. */
678 #ifdef LEDEBUG
679 if (sc->sc_debug)
680 printf("%s: extra rint\n", sc->sc_hd->hp_xname);
681 #endif
682 return;
683 }
684
685 /* Process all buffers with valid data. */
686 do {
687 if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) {
688 if ((cdm->flags & (LE_FRAM | LE_OFLO | LE_ENP)) == (LE_FRAM | LE_ENP))
689 printf("%s: FRAM\n", sc->sc_hd->hp_xname);
690 if ((cdm->flags & (LE_OFLO | LE_ENP)) == LE_OFLO)
691 printf("%s: OFLO\n", sc->sc_hd->hp_xname);
692 if ((cdm->flags & (LE_CRC | LE_OFLO | LE_ENP)) == (LE_CRC | LE_ENP))
693 printf("%s: CRC\n", sc->sc_hd->hp_xname);
694 if (cdm->flags & LE_RBUFF)
695 printf("%s: RBUFF\n", sc->sc_hd->hp_xname);
696 } else if (cdm->flags & (LE_STP | LE_ENP) != (LE_STP | LE_ENP)) {
697 do {
698 cdm->mcnt = 0;
699 cdm->flags |= LE_OWN;
700 NEXTRDS;
701 } while ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) == 0);
702 sc->sc_last_rd = rmd;
703 printf("%s: chained buffer\n", sc->sc_hd->hp_xname);
704 if ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) != LE_ENP) {
705 lereset(sc);
706 return;
707 }
708 } else {
709 #ifdef LEDEBUG
710 if (sc->sc_debug)
711 recv_print(sc, sc->sc_last_rd);
712 #endif
713 leread(sc, sc->sc_rbuf + (BUFSIZE * rmd),
714 (int)cdm->mcnt);
715 sc->sc_arpcom.ac_if.if_ipackets++;
716 }
717
718 cdm->mcnt = 0;
719 cdm->flags |= LE_OWN;
720 NEXTRDS;
721 #ifdef LEDEBUG
722 if (sc->sc_debug)
723 printf("sc->sc_last_rd = %x, cdm = %x\n",
724 sc->sc_last_rd, cdm);
725 #endif
726 } while ((cdm->flags & LE_OWN) == 0);
727
728 sc->sc_last_rd = rmd;
729 }
730
731 /*
732 * Pass a packet to the higher levels.
733 */
734 void
735 leread(sc, buf, len)
736 register struct le_softc *sc;
737 u_char *buf;
738 int len;
739 {
740 struct ifnet *ifp;
741 struct mbuf *m;
742 struct ether_header *eh;
743
744 len -= 4;
745 if (len <= 0)
746 return;
747
748 /* Pull packet off interface. */
749 ifp = &sc->sc_arpcom.ac_if;
750 m = leget(buf, len, ifp);
751 if (m == 0)
752 return;
753
754 /* We assume that the header fit entirely in one mbuf. */
755 eh = mtod(m, struct ether_header *);
756
757 #if NBPFILTER > 0
758 /*
759 * Check if there's a BPF listener on this interface.
760 * If so, hand off the raw packet to BPF.
761 */
762 if (ifp->if_bpf) {
763 bpf_mtap(ifp->if_bpf, m);
764
765 /*
766 * Note that the interface cannot be in promiscuous mode if
767 * there are no BPF listeners. And if we are in promiscuous
768 * mode, we have to check if this packet is really ours.
769 */
770 if ((ifp->if_flags & IFF_PROMISC) &&
771 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
772 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
773 sizeof(eh->ether_dhost)) != 0) {
774 m_freem(m);
775 return;
776 }
777 }
778 #endif
779
780 /* We assume that the header fit entirely in one mbuf. */
781 m->m_pkthdr.len -= sizeof(*eh);
782 m->m_len -= sizeof(*eh);
783 m->m_data += sizeof(*eh);
784
785 ether_input(ifp, eh, m);
786 }
787
788 /*
789 * Supporting routines
790 */
791
792 /*
793 * Pull data off an interface.
794 * Len is length of data, with local net header stripped.
795 * We copy the data into mbufs. When full cluster sized units are present
796 * we copy into clusters.
797 */
798 struct mbuf *
799 leget(buf, totlen, ifp)
800 u_char *buf;
801 int totlen;
802 struct ifnet *ifp;
803 {
804 struct mbuf *top, **mp, *m;
805 int len;
806
807 MGETHDR(m, M_DONTWAIT, MT_DATA);
808 if (m == 0)
809 return 0;
810 m->m_pkthdr.rcvif = ifp;
811 m->m_pkthdr.len = totlen;
812 len = MHLEN;
813 top = 0;
814 mp = ⊤
815
816 while (totlen > 0) {
817 if (top) {
818 MGET(m, M_DONTWAIT, MT_DATA);
819 if (m == 0) {
820 m_freem(top);
821 return 0;
822 }
823 len = MLEN;
824 }
825 if (totlen >= MINCLSIZE) {
826 MCLGET(m, M_DONTWAIT);
827 if (m->m_flags & M_EXT)
828 len = MCLBYTES;
829 }
830 m->m_len = len = min(totlen, len);
831 bcopy((caddr_t)buf, mtod(m, caddr_t), len);
832 buf += len;
833 totlen -= len;
834 *mp = m;
835 mp = &m->m_next;
836 }
837
838 return top;
839 }
840
841 /*
842 * Process an ioctl request.
843 */
844 int
845 leioctl(ifp, cmd, data)
846 register struct ifnet *ifp;
847 u_long cmd;
848 caddr_t data;
849 {
850 struct le_softc *sc = &le_softc[ifp->if_unit];
851 struct ifaddr *ifa = (struct ifaddr *)data;
852 struct ifreq *ifr = (struct ifreq *)data;
853 int s, error = 0;
854
855 s = splimp();
856
857 switch (cmd) {
858
859 case SIOCSIFADDR:
860 ifp->if_flags |= IFF_UP;
861
862 switch (ifa->ifa_addr->sa_family) {
863 #ifdef INET
864 case AF_INET:
865 leinit(sc);
866 arp_ifinit(&sc->sc_arpcom, ifa);
867 break;
868 #endif
869 #ifdef NS
870 /* XXX - This code is probably wrong. */
871 case AF_NS:
872 {
873 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
874
875 if (ns_nullhost(*ina))
876 ina->x_host =
877 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
878 else
879 bcopy(ina->x_host.c_host,
880 sc->sc_arpcom.ac_enaddr,
881 sizeof(sc->sc_arpcom.ac_enaddr));
882 /* Set new address. */
883 leinit(sc);
884 break;
885 }
886 #endif
887 default:
888 leinit(sc);
889 break;
890 }
891 break;
892
893 case SIOCSIFFLAGS:
894 /*
895 * If interface is marked down and it is running, then stop it
896 */
897 if ((ifp->if_flags & IFF_UP) == 0 &&
898 (ifp->if_flags & IFF_RUNNING) != 0) {
899 /*
900 * If interface is marked down and it is running, then
901 * stop it.
902 */
903 lestop(sc);
904 ifp->if_flags &= ~IFF_RUNNING;
905 } else if ((ifp->if_flags & IFF_UP) != 0 &&
906 (ifp->if_flags & IFF_RUNNING) == 0) {
907 /*
908 * If interface is marked up and it is stopped, then
909 * start it.
910 */
911 leinit(sc);
912 } else {
913 /*
914 * Reset the interface to pick up changes in any other
915 * flags that affect hardware registers.
916 */
917 /*lestop(sc);*/
918 leinit(sc);
919 }
920 #ifdef LEDEBUG
921 if (ifp->if_flags & IFF_DEBUG)
922 sc->sc_debug = 1;
923 else
924 sc->sc_debug = 0;
925 #endif
926 break;
927
928 case SIOCADDMULTI:
929 case SIOCDELMULTI:
930 error = (cmd == SIOCADDMULTI) ?
931 ether_addmulti(ifr, &sc->sc_arpcom):
932 ether_delmulti(ifr, &sc->sc_arpcom);
933
934 if (error == ENETRESET) {
935 /*
936 * Multicast list has changed; set the hardware filter
937 * accordingly.
938 */
939 leinit(sc);
940 error = 0;
941 }
942 break;
943
944 default:
945 error = EINVAL;
946 }
947 (void) splx(s);
948 return error;
949 }
950
951 #ifdef LEDEBUG
952 void
953 recv_print(sc, no)
954 struct le_softc *sc;
955 int no;
956 {
957 struct mds *rmd;
958 int i, printed = 0;
959 u_short len;
960
961 rmd = &sc->sc_rd[no];
962 len = rmd->mcnt;
963 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
964 len);
965 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
966 for (i = 0; i < len; i++) {
967 if (!printed) {
968 printed = 1;
969 printf("%s: data: ", sc->sc_dev.dv_xname);
970 }
971 printf("%x ", *(sc->sc_rbuf + (BUFSIZE*no) + i));
972 }
973 if (printed)
974 printf("\n");
975 }
976
977 void
978 xmit_print(sc, no)
979 struct le_softc *sc;
980 int no;
981 {
982 struct mds *rmd;
983 int i, printed=0;
984 u_short len;
985
986 rmd = &sc->sc_td[no];
987 len = -rmd->bcnt;
988 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
989 len);
990 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
991 printf("%s: addr %x, flags %x, bcnt %x, mcnt %x\n",
992 sc->sc_dev.dv_xname, rmd->addr, rmd->flags, rmd->bcnt, rmd->mcnt);
993 for (i = 0; i < len; i++) {
994 if (!printed) {
995 printed = 1;
996 printf("%s: data: ", sc->sc_dev.dv_xname);
997 }
998 printf("%x ", *(sc->sc_tbuf + (BUFSIZE*no) + i));
999 }
1000 if (printed)
1001 printf("\n");
1002 }
1003 #endif /* LEDEBUG */
1004
1005 /*
1006 * Set up the logical address filter.
1007 */
1008 void
1009 lesetladrf(ac, af)
1010 struct arpcom *ac;
1011 u_long *af;
1012 {
1013 struct ifnet *ifp = &ac->ac_if;
1014 struct ether_multi *enm;
1015 register u_char *cp, c;
1016 register u_long crc;
1017 register int i, len;
1018 struct ether_multistep step;
1019
1020 /*
1021 * Set up multicast address filter by passing all multicast addresses
1022 * through a crc generator, and then using the high order 6 bits as an
1023 * index into the 64 bit logical address filter. The high order bit
1024 * selects the word, while the rest of the bits select the bit within
1025 * the word.
1026 */
1027
1028 if (ifp->if_flags & IFF_PROMISC) {
1029 ifp->if_flags |= IFF_ALLMULTI;
1030 af[0] = af[1] = 0xffffffff;
1031 return;
1032 }
1033
1034 af[0] = af[1] = 0;
1035 ETHER_FIRST_MULTI(step, ac, enm);
1036 while (enm != NULL) {
1037 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1038 sizeof(enm->enm_addrlo)) != 0) {
1039 /*
1040 * We must listen to a range of multicast addresses.
1041 * For now, just accept all multicasts, rather than
1042 * trying to set only those filter bits needed to match
1043 * the range. (At this time, the only use of address
1044 * ranges is for IP multicast routing, for which the
1045 * range is big enough to require all bits set.)
1046 */
1047 ifp->if_flags |= IFF_ALLMULTI;
1048 af[0] = af[1] = 0xffffffff;
1049 return;
1050 }
1051
1052 cp = enm->enm_addrlo;
1053 crc = 0xffffffff;
1054 for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1055 c = *cp++;
1056 for (i = 8; --i >= 0;) {
1057 if ((crc & 0x01) ^ (c & 0x01)) {
1058 crc >>= 1;
1059 crc ^= 0x6db88320 | 0x80000000;
1060 } else
1061 crc >>= 1;
1062 c >>= 1;
1063 }
1064 }
1065 /* Just want the 6 most significant bits. */
1066 crc >>= 26;
1067
1068 /* Turn on the corresponding bit in the filter. */
1069 af[crc >> 5] |= 1 << ((crc & 0x1f) ^ 16);
1070
1071 ETHER_NEXT_MULTI(step, enm);
1072 }
1073 ifp->if_flags &= ~IFF_ALLMULTI;
1074 }
1075
1076 #endif /* NLE > 0 */
1077