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