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