if_le.c revision 1.13 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.13 1994/07/06 01:36:23 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 * Setup output on interface.
395 * Get another datagram to send off of the interface queue, and map it to the
396 * interface before starting the output.
397 * Called only at splimp or interrupt level.
398 */
399 int
400 lestart(ifp)
401 struct ifnet *ifp;
402 {
403 register struct le_softc *sc = &le_softc[ifp->if_unit];
404 struct mbuf *m0, *m;
405 u_char *buffer;
406 int len;
407 int i;
408 struct mds *cdm;
409
410 if ((sc->sc_arpcom.ac_if.if_flags ^ IFF_RUNNING) &
411 (IFF_RUNNING | IFF_OACTIVE))
412 return;
413
414 outloop:
415 if (sc->sc_no_td >= NTBUF) {
416 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
417 #ifdef LEDEBUG
418 if (sc->sc_debug)
419 printf("no_td = %x, last_td = %x\n", sc->sc_no_td,
420 sc->sc_last_td);
421 #endif
422 return;
423 }
424
425 cdm = &sc->sc_td[sc->sc_last_td];
426 #if 0 /* XXX redundant */
427 if (cdm->flags & LE_OWN)
428 return;
429 #endif
430
431 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
432 if (!m)
433 return;
434
435 ++sc->sc_no_td;
436
437 /*
438 * Copy the mbuf chain into the transmit buffer.
439 */
440 buffer = sc->sc_tbuf + (BUFSIZE * sc->sc_last_td);
441 len = 0;
442 for (m0 = m; m; m = m->m_next) {
443 bcopy(mtod(m, caddr_t), buffer, m->m_len);
444 buffer += m->m_len;
445 len += m->m_len;
446 }
447
448 #if NBPFILTER > 0
449 if (sc->sc_arpcom.ac_if.if_bpf)
450 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
451 #endif
452
453 m_freem(m0);
454 len = max(len, ETHER_MIN_LEN);
455
456 /*
457 * Init transmit registers, and set transmit start flag.
458 */
459 cdm->bcnt = -len;
460 cdm->mcnt = 0;
461 cdm->flags |= LE_OWN | LE_STP | LE_ENP;
462
463 #ifdef LEDEBUG
464 if (sc->sc_debug)
465 xmit_print(sc, sc->sc_last_td);
466 #endif
467
468 lewrcsr(sc, 0, LE_INEA | LE_TDMD);
469
470 /* possible more packets */
471 if (++sc->sc_last_td >= NTBUF)
472 sc->sc_last_td = 0;
473 goto outloop;
474 }
475
476 /*
477 * Controller interrupt.
478 */
479 int
480 leintr(unit)
481 int unit;
482 {
483 register struct le_softc *sc = &le_softc[unit];
484 register u_short isr;
485
486 isr = lerdcsr(sc, 0);
487 #ifdef LEDEBUG
488 if (sc->sc_debug)
489 printf("le%d: leintr entering with isr=%04x\n",
490 unit, isr);
491 #endif
492 if ((isr & LE_INTR) == 0)
493 return 0;
494
495 do {
496 lewrcsr(sc, 0,
497 isr & (LE_INEA | LE_BABL | LE_MISS | LE_MERR |
498 LE_RINT | LE_TINT | LE_IDON));
499 if (isr & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) {
500 if (isr & LE_BABL) {
501 printf("le%d: BABL\n", unit);
502 sc->sc_arpcom.ac_if.if_oerrors++;
503 }
504 #if 0
505 if (isr & LE_CERR) {
506 printf("le%d: CERR\n", unit);
507 sc->sc_arpcom.ac_if.if_collisions++;
508 }
509 #endif
510 if (isr & LE_MISS) {
511 printf("le%d: MISS\n", unit);
512 sc->sc_arpcom.ac_if.if_ierrors++;
513 }
514 if (isr & LE_MERR) {
515 printf("le%d: MERR\n", unit);
516 lereset(sc);
517 goto out;
518 }
519 }
520
521 if ((isr & LE_RXON) == 0) {
522 printf("le%d: receiver disabled\n", unit);
523 sc->sc_arpcom.ac_if.if_ierrors++;
524 lereset(sc);
525 goto out;
526 }
527 if ((isr & LE_TXON) == 0) {
528 printf("le%d: transmitter disabled\n", unit);
529 sc->sc_arpcom.ac_if.if_oerrors++;
530 lereset(sc);
531 goto out;
532 }
533
534 if (isr & LE_RINT) {
535 /* Reset watchdog timer. */
536 sc->sc_arpcom.ac_if.if_timer = 0;
537 lerint(unit);
538 }
539 if (isr & LE_TINT) {
540 /* Reset watchdog timer. */
541 sc->sc_arpcom.ac_if.if_timer = 0;
542 letint(unit);
543 }
544
545 isr = lerdcsr(sc, 0);
546 } while ((isr & LE_INTR) != 0);
547
548 #ifdef LEDEBUG
549 if (sc->sc_debug)
550 printf("le%d: leintr returning with isr=%04x\n",
551 unit, isr);
552 #endif
553
554 out:
555 return 1;
556 }
557
558 #define NEXTTDS \
559 if (++tmd == NTBUF) tmd=0, cdm=sc->sc_td; else ++cdm
560
561 void
562 letint(unit)
563 int unit;
564 {
565 register struct le_softc *sc = &le_softc[unit];
566 register int tmd = (sc->sc_last_td - sc->sc_no_td + NTBUF) % NTBUF;
567 struct mds *cdm = &sc->sc_td[tmd];
568
569 if (cdm->flags & LE_OWN) {
570 /* Race condition with loop below. */
571 #ifdef LEDEBUG
572 if (sc->sc_debug)
573 printf("le%d: extra tint\n", unit);
574 #endif
575 return;
576 }
577
578 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
579
580 do {
581 if (sc->sc_no_td <= 0)
582 break;
583 #ifdef LEDEBUG
584 if (sc->sc_debug)
585 printf("trans cdm = %x\n", cdm);
586 #endif
587 sc->sc_arpcom.ac_if.if_opackets++;
588 --sc->sc_no_td;
589 if (cdm->flags & (LE_TBUFF | LE_UFLO | LE_LCOL | LE_LCAR | LE_RTRY)) {
590 if (cdm->flags & LE_TBUFF)
591 printf("le%d: TBUFF\n", unit);
592 if ((cdm->flags & (LE_TBUFF | LE_UFLO)) == LE_UFLO)
593 printf("le%d: UFLO\n", unit);
594 if (cdm->flags & LE_UFLO) {
595 lereset(sc);
596 return;
597 }
598 #if 0
599 if (cdm->flags & LE_LCOL) {
600 printf("le%d: late collision\n", unit);
601 sc->sc_arpcom.ac_if.if_collisions++;
602 }
603 if (cdm->flags & LE_LCAR)
604 printf("le%d: lost carrier\n", unit);
605 if (cdm->flags & LE_RTRY) {
606 printf("le%d: excessive collisions, tdr %d\n",
607 unit, cdm->flags & 0x1ff);
608 sc->sc_arpcom.ac_if.if_collisions++;
609 }
610 #endif
611 }
612 NEXTTDS;
613 } while ((cdm->flags & LE_OWN) == 0);
614
615 lestart(&sc->sc_arpcom.ac_if);
616 }
617
618 #define NEXTRDS \
619 if (++rmd == NRBUF) rmd=0, cdm=sc->sc_rd; else ++cdm
620
621 /* only called from one place, so may as well integrate */
622 void
623 lerint(unit)
624 int unit;
625 {
626 register struct le_softc *sc = &le_softc[unit];
627 register int rmd = sc->sc_last_rd;
628 struct mds *cdm = &sc->sc_rd[rmd];
629
630 if (cdm->flags & LE_OWN) {
631 /* Race condition with loop below. */
632 #ifdef LEDEBUG
633 if (sc->sc_debug)
634 printf("le%d: extra rint\n", unit);
635 #endif
636 return;
637 }
638
639 /* Process all buffers with valid data. */
640 do {
641 if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) {
642 if ((cdm->flags & (LE_FRAM | LE_OFLO | LE_ENP)) == (LE_FRAM | LE_ENP))
643 printf("le%d: FRAM\n", unit);
644 if ((cdm->flags & (LE_OFLO | LE_ENP)) == LE_OFLO)
645 printf("le%d: OFLO\n", unit);
646 if ((cdm->flags & (LE_CRC | LE_OFLO | LE_ENP)) == (LE_CRC | LE_ENP))
647 printf("le%d: CRC\n", unit);
648 if (cdm->flags & LE_RBUFF)
649 printf("le%d: RBUFF\n", unit);
650 } else if (cdm->flags & (LE_STP | LE_ENP) != (LE_STP | LE_ENP)) {
651 do {
652 cdm->mcnt = 0;
653 cdm->flags |= LE_OWN;
654 NEXTRDS;
655 } while ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) == 0);
656 sc->sc_last_rd = rmd;
657 printf("le%d: chained buffer\n", unit);
658 if ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) != LE_ENP) {
659 lereset(sc);
660 return;
661 }
662 } else {
663 #ifdef LEDEBUG
664 if (sc->sc_debug)
665 recv_print(sc, sc->sc_last_rd);
666 #endif
667 leread(sc, sc->sc_rbuf + (BUFSIZE * rmd),
668 (int)cdm->mcnt);
669 sc->sc_arpcom.ac_if.if_ipackets++;
670 }
671
672 cdm->mcnt = 0;
673 cdm->flags |= LE_OWN;
674 NEXTRDS;
675 #ifdef LEDEBUG
676 if (sc->sc_debug)
677 printf("sc->sc_last_rd = %x, cdm = %x\n",
678 sc->sc_last_rd, cdm);
679 #endif
680 } while ((cdm->flags & LE_OWN) == 0);
681
682 sc->sc_last_rd = rmd;
683 }
684
685 /*
686 * Pass a packet to the higher levels.
687 */
688 void
689 leread(sc, buf, len)
690 register struct le_softc *sc;
691 u_char *buf;
692 int len;
693 {
694 struct ether_header *eh;
695 struct mbuf *m;
696
697 eh = (struct ether_header *)buf;
698 len -= sizeof(struct ether_header) + 4;
699 if (len <= 0)
700 return;
701
702 /* Pull packet off interface. */
703 m = leget(buf, len, &sc->sc_arpcom.ac_if);
704 if (m == 0)
705 return;
706
707 #if NBPFILTER > 0
708 /*
709 * Check if there's a BPF listener on this interface.
710 * If so, hand off the raw packet to BPF.
711 */
712 if (sc->sc_arpcom.ac_if.if_bpf) {
713 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
714
715 /*
716 * Note that the interface cannot be in promiscuous mode if
717 * there are no BPF listeners. And if we are in promiscuous
718 * mode, we have to check if this packet is really ours.
719 */
720 if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
721 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
722 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
723 sizeof(eh->ether_dhost)) != 0) {
724 m_freem(m);
725 return;
726 }
727 }
728 #endif
729
730 ether_input(&sc->sc_arpcom.ac_if, eh, m);
731 }
732
733 /*
734 * Supporting routines
735 */
736
737 /*
738 * Pull data off an interface.
739 * Len is length of data, with local net header stripped.
740 * We copy the data into mbufs. When full cluster sized units are present
741 * we copy into clusters.
742 */
743 struct mbuf *
744 leget(buf, totlen, ifp)
745 u_char *buf;
746 int totlen;
747 struct ifnet *ifp;
748 {
749 struct mbuf *top, **mp, *m, *p;
750 int len;
751 register caddr_t cp = buf;
752 char *epkt;
753
754 buf += sizeof(struct ether_header);
755 cp = buf;
756 epkt = cp + totlen;
757
758 MGETHDR(m, M_DONTWAIT, MT_DATA);
759 if (m == 0)
760 return 0;
761 m->m_pkthdr.rcvif = ifp;
762 m->m_pkthdr.len = totlen;
763 m->m_len = MHLEN;
764 top = 0;
765 mp = ⊤
766
767 while (totlen > 0) {
768 if (top) {
769 MGET(m, M_DONTWAIT, MT_DATA);
770 if (m == 0) {
771 m_freem(top);
772 return 0;
773 }
774 m->m_len = MLEN;
775 }
776 len = min(totlen, epkt - cp);
777 if (len >= MINCLSIZE) {
778 MCLGET(m, M_DONTWAIT);
779 if (m->m_flags & M_EXT)
780 m->m_len = len = min(len, MCLBYTES);
781 else
782 len = m->m_len;
783 } else {
784 /*
785 * Place initial small packet/header at end of mbuf.
786 */
787 if (len < m->m_len) {
788 if (top == 0 && len + max_linkhdr <= m->m_len)
789 m->m_data += max_linkhdr;
790 m->m_len = len;
791 } else
792 len = m->m_len;
793 }
794 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
795 cp += len;
796 *mp = m;
797 mp = &m->m_next;
798 totlen -= len;
799 if (cp == epkt)
800 cp = buf;
801 }
802
803 return top;
804 }
805
806 /*
807 * Process an ioctl request.
808 */
809 int
810 leioctl(ifp, cmd, data)
811 register struct ifnet *ifp;
812 int cmd;
813 caddr_t data;
814 {
815 struct le_softc *sc = &le_softc[ifp->if_unit];
816 struct ifaddr *ifa = (struct ifaddr *)data;
817 struct ifreq *ifr = (struct ifreq *)data;
818 int s, error = 0;
819
820 s = splimp();
821
822 switch (cmd) {
823
824 case SIOCSIFADDR:
825 ifp->if_flags |= IFF_UP;
826
827 switch (ifa->ifa_addr->sa_family) {
828 #ifdef INET
829 case AF_INET:
830 leinit(sc); /* before arpwhohas */
831 /*
832 * See if another station has *our* IP address.
833 * i.e.: There is an address conflict! If a
834 * conflict exists, a message is sent to the
835 * console.
836 */
837 sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
838 arpwhohas(&sc->sc_arpcom, &IA_SIN(ifa)->sin_addr);
839 break;
840 #endif
841 #ifdef NS
842 /* XXX - This code is probably wrong. */
843 case AF_NS:
844 {
845 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
846
847 if (ns_nullhost(*ina))
848 ina->x_host =
849 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
850 else
851 bcopy(ina->x_host.c_host,
852 sc->sc_arpcom.ac_enaddr,
853 sizeof(sc->sc_arpcom.ac_enaddr));
854 /* Set new address. */
855 leinit(sc);
856 break;
857 }
858 #endif
859 default:
860 leinit(sc);
861 break;
862 }
863 break;
864
865 case SIOCSIFFLAGS:
866 /*
867 * If interface is marked down and it is running, then stop it
868 */
869 if ((ifp->if_flags & IFF_UP) == 0 &&
870 (ifp->if_flags & IFF_RUNNING) != 0) {
871 /*
872 * If interface is marked down and it is running, then
873 * stop it.
874 */
875 lestop(sc);
876 ifp->if_flags &= ~IFF_RUNNING;
877 } else if ((ifp->if_flags & IFF_UP) != 0 &&
878 (ifp->if_flags & IFF_RUNNING) == 0) {
879 /*
880 * If interface is marked up and it is stopped, then
881 * start it.
882 */
883 leinit(sc);
884 } else {
885 /*
886 * Reset the interface to pick up changes in any other
887 * flags that affect hardware registers.
888 */
889 /*lestop(sc);*/
890 leinit(sc);
891 }
892 #ifdef LEDEBUG
893 if (ifp->if_flags & IFF_DEBUG)
894 sc->sc_debug = 1;
895 else
896 sc->sc_debug = 0;
897 #endif
898 break;
899
900 case SIOCADDMULTI:
901 case SIOCDELMULTI:
902 error = (cmd == SIOCADDMULTI) ?
903 ether_addmulti(ifr, &sc->sc_arpcom):
904 ether_delmulti(ifr, &sc->sc_arpcom);
905
906 if (error == ENETRESET) {
907 /*
908 * Multicast list has changed; set the hardware filter
909 * accordingly.
910 */
911 leinit(sc);
912 error = 0;
913 }
914 break;
915
916 default:
917 error = EINVAL;
918 }
919 (void) splx(s);
920 return error;
921 }
922
923 #ifdef LEDEBUG
924 void
925 recv_print(sc, no)
926 struct le_softc *sc;
927 int no;
928 {
929 struct mds *rmd;
930 int i, printed = 0;
931 u_short len;
932
933 rmd = &sc->sc_rd[no];
934 len = rmd->mcnt;
935 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
936 len);
937 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
938 for (i = 0; i < len; i++) {
939 if (!printed) {
940 printed = 1;
941 printf("%s: data: ", sc->sc_dev.dv_xname);
942 }
943 printf("%x ", *(sc->sc_rbuf + (BUFSIZE*no) + i));
944 }
945 if (printed)
946 printf("\n");
947 }
948
949 void
950 xmit_print(sc, no)
951 struct le_softc *sc;
952 int no;
953 {
954 struct mds *rmd;
955 int i, printed=0;
956 u_short len;
957
958 rmd = &sc->sc_td[no];
959 len = -rmd->bcnt;
960 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
961 len);
962 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
963 printf("%s: addr %x, flags %x, bcnt %x, mcnt %x\n",
964 sc->sc_dev.dv_xname, rmd->addr, rmd->flags, rmd->bcnt, rmd->mcnt);
965 for (i = 0; i < len; i++) {
966 if (!printed) {
967 printed = 1;
968 printf("%s: data: ", sc->sc_dev.dv_xname);
969 }
970 printf("%x ", *(sc->sc_tbuf + (BUFSIZE*no) + i));
971 }
972 if (printed)
973 printf("\n");
974 }
975 #endif /* LEDEBUG */
976
977 /*
978 * Set up the logical address filter.
979 */
980 void
981 lesetladrf(ac, af)
982 struct arpcom *ac;
983 u_long *af;
984 {
985 struct ifnet *ifp = &ac->ac_if;
986 struct ether_multi *enm;
987 register u_char *cp, c;
988 register u_long crc;
989 register int i, len;
990 struct ether_multistep step;
991
992 /*
993 * Set up multicast address filter by passing all multicast addresses
994 * through a crc generator, and then using the high order 6 bits as an
995 * index into the 64 bit logical address filter. The high order bit
996 * selects the word, while the rest of the bits select the bit within
997 * the word.
998 */
999
1000 if (ifp->if_flags & IFF_PROMISC) {
1001 ifp->if_flags |= IFF_ALLMULTI;
1002 af[0] = af[1] = 0xffffffff;
1003 return;
1004 }
1005
1006 af[0] = af[1] = 0;
1007 ETHER_FIRST_MULTI(step, ac, enm);
1008 while (enm != NULL) {
1009 if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1010 sizeof(enm->enm_addrlo)) != 0) {
1011 /*
1012 * We must listen to a range of multicast addresses.
1013 * For now, just accept all multicasts, rather than
1014 * trying to set only those filter bits needed to match
1015 * the range. (At this time, the only use of address
1016 * ranges is for IP multicast routing, for which the
1017 * range is big enough to require all bits set.)
1018 */
1019 ifp->if_flags |= IFF_ALLMULTI;
1020 af[0] = af[1] = 0xffffffff;
1021 return;
1022 }
1023
1024 cp = enm->enm_addrlo;
1025 crc = 0xffffffff;
1026 for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1027 c = *cp++;
1028 for (i = 8; --i >= 0;) {
1029 if ((crc & 0x01) ^ (c & 0x01)) {
1030 crc >>= 1;
1031 crc ^= 0x6db88320 | 0x80000000;
1032 } else
1033 crc >>= 1;
1034 c >>= 1;
1035 }
1036 }
1037 /* Just want the 6 most significant bits. */
1038 crc >>= 26;
1039
1040 /* Turn on the corresponding bit in the filter. */
1041 af[crc >> 5] |= 1 << (crc & 0x1f);
1042
1043 ETHER_NEXT_MULTI(step, enm);
1044 }
1045 ifp->if_flags &= ~IFF_ALLMULTI;
1046 }
1047