if_le.c revision 1.10 1 /* $NetBSD: if_le.c,v 1.10 1995/02/12 19:19:13 chopps 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 * This driver will generate and accept tailer encapsulated packets even
47 * though it buys us nothing. The motivation was to avoid incompatibilities
48 * with VAXen, SUNs, and others that handle and benefit from them.
49 * This reasoning is dubious.
50 */
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/mbuf.h>
54 #include <sys/buf.h>
55 #include <sys/protosw.h>
56 #include <sys/socket.h>
57 #include <sys/syslog.h>
58 #include <sys/ioctl.h>
59 #include <sys/errno.h>
60 #include <sys/device.h>
61
62 #include <net/if.h>
63 #include <net/netisr.h>
64 #include <net/route.h>
65
66 #ifdef INET
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/in_var.h>
70 #include <netinet/ip.h>
71 #include <netinet/if_ether.h>
72 #endif
73
74 #ifdef NS
75 #include <netns/ns.h>
76 #include <netns/ns_if.h>
77 #endif
78
79 #include <machine/cpu.h>
80 #include <machine/mtpr.h>
81 #include <amiga/amiga/device.h>
82 #include <amiga/amiga/isr.h>
83 #include <amiga/dev/zbusvar.h>
84 #include <amiga/dev/if_lereg.h>
85
86 /*
87 * Ethernet software status per interface.
88 *
89 * Each interface is referenced by a network interface structure,
90 * le_if, which the routing code uses to locate the interface.
91 * This structure contains the output queue for the interface, its address, ...
92 */
93 struct le_softc {
94 struct isr sc_isr;
95 struct arpcom sc_ac; /* common Ethernet structures */
96 #define sc_if sc_ac.ac_if /* network-visible interface */
97 #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
98 void *sc_base; /* base address of board */
99 struct lereg1 *sc_r1; /* LANCE registers */
100 struct lereg2 *sc_r2; /* dual-port RAM */
101 int sc_rmd; /* predicted next rmd to process */
102 int sc_tmd; /* next tmd to use */
103 int sc_no_td; /* number of tmds in use */
104 int sc_runt;
105 int sc_jab;
106 int sc_merr;
107 int sc_babl;
108 int sc_cerr;
109 int sc_miss;
110 int sc_xint;
111 int sc_xown;
112 int sc_uflo;
113 int sc_rxlen;
114 int sc_rxoff;
115 int sc_txoff;
116 int sc_busy;
117 short sc_iflags;
118 #if NBPFILTER > 0
119 caddr_t sc_bpf;
120 #endif
121 } le_softc[NLE];
122
123 #if NBPFILTER > 0
124 #include <net/bpf.h>
125 #include <net/bpfdesc.h>
126 #endif
127
128 /* offsets for: ID, REGS, MEM */
129 int lestd[] = { 0, 0x4000, 0x8000 };
130
131 /* console error messages */
132 int ledebug = 0;
133
134 int leintr(), lestart(), leioctl(), ether_output();
135 void leinit();
136
137 struct mbuf *leget();
138 extern struct ifnet loif;
139
140 void leattach __P((struct device *, struct device *, void *));
141 int lematch __P((struct device *, struct cfdata *, void *args));
142
143 struct cfdriver lecd = {
144 NULL, "le", (cfmatch_t)lematch, leattach, DV_IFNET,
145 sizeof(struct le_softc), NULL, 0};
146
147 int
148 lematch(pdp, cfp, auxp)
149 struct device *pdp;
150 struct cfdata *cfp;
151 void *auxp;
152 {
153
154 struct zbus_args *zap;
155
156 zap = (struct zbus_args *)auxp;
157
158 /* Commodore ethernet card */
159 if ( zap->manid == 514 && zap->prodid == 112)
160 return(1);
161
162 /* Ameristar ethernet card */
163 if ( zap->manid == 1053 && zap->prodid == 1)
164 return(1);
165
166 return (0);
167 }
168
169 /*
170 * Interface exists: make available by filling in network interface
171 * record. System will initialize the interface when it is ready
172 * to accept packets.
173 */
174 void
175 leattach(pdp, dp, auxp)
176 struct device *pdp, *dp;
177 void *auxp;
178 {
179 register struct lereg0 *ler0;
180 register struct lereg2 *ler2;
181 struct zbus_args *zap;
182 struct lereg2 *lemem = (struct lereg2 *) 0x8000;
183 struct le_softc *le = &le_softc[dp->dv_unit];
184 struct ifnet *ifp = &le->sc_if;
185 char *cp;
186 int i;
187 unsigned long ser;
188 int s = splhigh ();
189
190 zap =(struct zbus_args *)auxp;
191
192 /*
193 * Make config msgs look nicer.
194 */
195 printf("\n");
196
197 ler0 = le->sc_base = zap->va;
198 le->sc_r1 = (struct lereg1 *)(lestd[1] + (int)zap->va);
199 ler2 = le->sc_r2 = (struct lereg2 *)(lestd[2] + (int)zap->va);
200
201 /*
202 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID.
203 */
204 if ( zap->manid == 514 && zap->prodid == 112) {
205 /* Commodore 2065 */
206 le->sc_addr[0] = 0x00;
207 le->sc_addr[1] = 0x80;
208 le->sc_addr[2] = 0x10;
209 }
210 if ( zap->manid == 1053 && zap->prodid == 1) {
211 le->sc_addr[0] = 0x00;
212 le->sc_addr[1] = 0x00;
213 le->sc_addr[2] = 0x9f;
214 }
215
216 /*
217 * Serial number for board is used as host ID.
218 */
219 ser = (unsigned long) zap->serno;
220
221 le->sc_addr[3] = (ser >> 16) & 0xff;
222 le->sc_addr[4] = (ser >> 8) & 0xff;
223 le->sc_addr[5] = (ser ) & 0xff;
224
225 #ifdef LE_USE_16K
226 printf("le%d: hardware address %s 16K\n",
227 #else
228 printf("le%d: hardware address %s 32K\n",
229 #endif
230 dp->dv_unit, ether_sprintf(le->sc_addr));
231
232 /*
233 * Setup for transmit/receive
234 */
235 ler2->ler2_mode = LE_MODE;
236 ler2->ler2_padr[0] = le->sc_addr[1];
237 ler2->ler2_padr[1] = le->sc_addr[0];
238 ler2->ler2_padr[2] = le->sc_addr[3];
239 ler2->ler2_padr[3] = le->sc_addr[2];
240 ler2->ler2_padr[4] = le->sc_addr[5];
241 ler2->ler2_padr[5] = le->sc_addr[4];
242 ler2->ler2_ladrf0 = 0;
243 ler2->ler2_ladrf1 = 0;
244 ler2->ler2_rlen = LE_RLEN;
245 ler2->ler2_rdra = (int)lemem->ler2_rmd;
246 ler2->ler2_tlen = LE_TLEN;
247 ler2->ler2_tdra = (int)lemem->ler2_tmd;
248
249 splx (s);
250
251 ifp->if_unit = dp->dv_unit;
252 ifp->if_name = "le";
253 ifp->if_mtu = ETHERMTU;
254 ifp->if_ioctl = leioctl;
255 ifp->if_output = ether_output;
256 ifp->if_start = lestart;
257 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
258
259 #if NBPFILTER > 0
260 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
261 #endif
262 if_attach(ifp);
263 ether_ifattach(ifp);
264
265 le->sc_isr.isr_intr = leintr;
266 le->sc_isr.isr_arg = le;
267 le->sc_isr.isr_ipl = 2;
268 add_isr (&le->sc_isr);
269
270 return;
271 }
272
273 ledrinit(ler2)
274 register struct lereg2 *ler2;
275 {
276 register struct lereg2 *lemem = (struct lereg2 *) 0x8000;
277 register int i;
278
279 for (i = 0; i < LERBUF; i++) {
280 ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
281 ler2->ler2_rmd[i].rmd1 = LE_OWN;
282 ler2->ler2_rmd[i].rmd2 = -LEMTU;
283 ler2->ler2_rmd[i].rmd3 = 0;
284 }
285
286 for (i = 0; i < LETBUF; i++) {
287 ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
288 ler2->ler2_tmd[i].tmd1 = 0;
289 ler2->ler2_tmd[i].tmd2 = 0;
290 ler2->ler2_tmd[i].tmd3 = 0;
291 }
292 }
293
294 void
295 lereset(unit)
296 register int unit;
297 {
298 register struct le_softc *le = &le_softc[unit];
299 register struct lereg1 *ler1 = le->sc_r1;
300 /*
301 * This structure is referenced from the CARDS/LANCE point of
302 * view, thus the 0x8000 address which is the buffer RAM area of
303 * the Commodore and Ameristar cards. This pointer is manipulated
304 * with the LANCE's view of memory and NOT the Amiga's. FYI.
305 */
306 register struct lereg2 *lemem = (struct lereg2 *) 0x8000;
307
308 register int timo = 100000;
309 register int stat;
310
311 #ifdef lint
312 stat = unit;
313 #endif
314 #if NBPFILTER > 0
315 if (le->sc_if.if_flags & IFF_PROMISC)
316 /* set the promiscuous bit */
317 le->sc_r2->ler2_mode = LE_MODE|0x8000;
318 else
319 le->sc_r2->ler2_mode = LE_MODE;
320 #endif
321 ler1->ler1_rap = LE_CSR0;
322 ler1->ler1_rdp = LE_STOP;
323
324 ledrinit(le->sc_r2);
325
326 le->sc_rmd = le->sc_tmd = le->sc_no_td = 0;
327 ler1->ler1_rap = LE_CSR1;
328 ler1->ler1_rdp = (int)&lemem->ler2_mode;
329 ler1->ler1_rap = LE_CSR2;
330 ler1->ler1_rdp = 0;
331 ler1->ler1_rap = LE_CSR0;
332 ler1->ler1_rdp = LE_INIT;
333
334 do {
335 if (--timo == 0) {
336 printf("le%d: init timeout, stat = 0x%x\n",
337 unit, stat);
338 break;
339 }
340 stat = ler1->ler1_rdp;
341 } while ((stat & LE_IDON) == 0);
342
343 ler1->ler1_rdp = LE_STOP;
344 ler1->ler1_rap = LE_CSR3;
345 ler1->ler1_rdp = LE_BSWP;
346 ler1->ler1_rap = LE_CSR0;
347 ler1->ler1_rdp = LE_STRT | LE_INEA;
348 le->sc_if.if_flags &= ~IFF_OACTIVE;
349
350 return;
351 }
352
353 /*
354 * Initialization of interface
355 */
356 void
357 leinit(unit)
358 int unit;
359 {
360 struct le_softc *le = &le_softc[unit];
361 register struct ifnet *ifp = &le->sc_if;
362 int s;
363
364 /* not yet, if address still unknown */
365 if (ifp->if_addrlist == (struct ifaddr *)0)
366 return;
367
368 if ((ifp->if_flags & IFF_RUNNING) == 0) {
369 s = splimp();
370 ifp->if_flags |= IFF_RUNNING;
371 lereset(unit);
372 (void) lestart(ifp);
373 splx(s);
374 }
375
376 return;
377 }
378
379 #define LENEXTTMP \
380 if (++bix == LETBUF) bix = 0, tmd = le->sc_r2->ler2_tmd; else ++tmd
381
382 /*
383 * Start output on interface. Get another datagram to send
384 * off of the interface queue, and copy it to the interface
385 * before starting the output.
386 */
387 lestart(ifp)
388 struct ifnet *ifp;
389 {
390 register struct le_softc *le = &le_softc[ifp->if_unit];
391 register int bix;
392 register struct letmd *tmd;
393 register struct mbuf *m;
394 int len;
395
396 if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
397 return (0);
398
399 bix = le->sc_tmd;
400 tmd = &le->sc_r2->ler2_tmd[bix];
401
402 for (;;) {
403 if (le->sc_no_td >= LETBUF) {
404 le->sc_if.if_flags |= IFF_OACTIVE;
405 break;
406 }
407
408 IF_DEQUEUE(&le->sc_if.if_snd, m);
409 if (m == 0)
410 break;
411
412 ++le->sc_no_td;
413
414 len = leput(le->sc_r2->ler2_tbuf[bix], m);
415
416 #if NBPFILTER > 0
417 /*
418 * If bpf is listening on this interface, let it
419 * see the packet before we commit it to the wire.
420 */
421 if (le->sc_bpf)
422 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[bix], len);
423 #endif
424
425 tmd->tmd3 = 0;
426 tmd->tmd2 = -len;
427 tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
428
429 LENEXTTMP;
430 }
431
432 le->sc_tmd = bix;
433
434 return (0);
435 }
436
437 leintr(le)
438 struct le_softc *le;
439 {
440 #if 0
441 register struct le_softc *le = &le_softc[unit];
442 #else
443 int unit = le->sc_if.if_unit;
444 #endif
445 register struct lereg1 *ler1;
446 register int stat;
447
448 /* if not even initialized, don't do anything further.. */
449 if (! le->sc_base)
450 return 0;
451
452 ler1 = le->sc_r1;
453 stat = ler1->ler1_rdp;
454
455 if (! (stat & LE_INTR))
456 return 0;
457
458 if (stat & LE_SERR) {
459 leerror(unit, stat);
460 if (stat & LE_MERR) {
461 le->sc_merr++;
462 lereset(unit);
463 return(1);
464 }
465 if (stat & LE_BABL)
466 le->sc_babl++;
467 if (stat & LE_CERR)
468 le->sc_cerr++;
469 if (stat & LE_MISS)
470 le->sc_miss++;
471 ler1->ler1_rdp = LE_BABL|LE_CERR|LE_MISS|LE_INEA;
472 }
473 if ((stat & LE_RXON) == 0) {
474 le->sc_rxoff++;
475 lereset(unit);
476 return(1);
477 }
478 if ((stat & LE_TXON) == 0) {
479 le->sc_txoff++;
480 lereset(unit);
481 return(1);
482 }
483 if (stat & LE_RINT) {
484 /* interrupt is cleared in lerint */
485 lerint(unit);
486 }
487 if (stat & LE_TINT) {
488 ler1->ler1_rdp = LE_TINT|LE_INEA;
489 lexint(unit);
490 }
491 return(1);
492 }
493
494 /*
495 * Ethernet interface transmitter interrupt.
496 * Start another output if more data to send.
497 */
498 lexint(unit)
499 register int unit;
500 {
501 register struct le_softc *le = &le_softc[unit];
502 register int bix = (le->sc_tmd - le->sc_no_td + LETBUF) % LETBUF;
503 register struct letmd *tmd = &le->sc_r2->ler2_tmd[bix];
504
505 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
506 le->sc_xint++;
507 return;
508 }
509 if (tmd->tmd1 & LE_OWN) {
510 printf("le%d: extra xint\n", unit);
511 le->sc_xown++;
512 return;
513 }
514 le->sc_if.if_flags &= ~IFF_OACTIVE;
515
516 do {
517 if (le->sc_no_td <= 0)
518 break;
519 --le->sc_no_td;
520
521 if (tmd->tmd1 & LE_ERR) {
522 err:
523 printf("le%d: xint error\n", unit);
524 lexerror(unit);
525 le->sc_if.if_oerrors++;
526 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
527 le->sc_uflo++;
528 lereset(unit);
529 return;
530 }
531 else if (tmd->tmd3 & LE_LCOL)
532 le->sc_if.if_collisions++;
533 else if (tmd->tmd3 & LE_RTRY)
534 le->sc_if.if_collisions += 16;
535 }
536 else if (tmd->tmd3 & LE_TBUFF)
537 /* XXX documentation says BUFF not included in ERR */
538 goto err;
539 else if (tmd->tmd1 & LE_ONE)
540 le->sc_if.if_collisions++;
541 else if (tmd->tmd1 & LE_MORE)
542 /* what is the real number? */
543 le->sc_if.if_collisions += 2;
544 else
545 le->sc_if.if_opackets++;
546 LENEXTTMP;
547 } while ((tmd->tmd1 & LE_OWN) == 0);
548
549 (void) lestart(&le->sc_if);
550 }
551
552 #define LENEXTRMP \
553 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
554
555 /*
556 * Ethernet interface receiver interrupt.
557 * If input error just drop packet.
558 * Decapsulate packet based on type and pass to type specific
559 * higher-level input routine.
560 */
561 lerint(unit)
562 int unit;
563 {
564 register struct le_softc *le = &le_softc[unit];
565 register int bix = le->sc_rmd;
566 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
567
568 /*
569 * Out of sync with hardware, should never happen?
570 */
571 if (rmd->rmd1 & LE_OWN) {
572 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA;
573 return;
574 }
575
576 /*
577 * Process all buffers with valid data
578 */
579 while ((rmd->rmd1 & LE_OWN) == 0) {
580 int len = rmd->rmd3;
581
582 /* Clear interrupt to avoid race condition */
583 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA;
584
585 if (rmd->rmd1 & LE_ERR) {
586 le->sc_rmd = bix;
587 lererror(unit, "bad packet");
588 le->sc_if.if_ierrors++;
589 } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
590 /*
591 * Find the end of the packet so we can see how long
592 * it was. We still throw it away.
593 */
594 do {
595 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA;
596 rmd->rmd3 = 0;
597 rmd->rmd1 = LE_OWN;
598 LENEXTRMP;
599 } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
600
601 le->sc_rmd = bix;
602 lererror(unit, "chained buffer");
603 le->sc_rxlen++;
604
605 /*
606 * If search terminated without successful completion
607 * we reset the hardware (conservative).
608 */
609 if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != LE_ENP) {
610 lereset(unit);
611 return;
612 }
613 } else
614 leread(unit, le->sc_r2->ler2_rbuf[bix], len);
615
616 rmd->rmd3 = 0;
617 rmd->rmd1 = LE_OWN;
618 LENEXTRMP;
619
620 }
621
622 le->sc_rmd = bix;
623 }
624
625 leread(unit, buf, len)
626 int unit;
627 char *buf;
628 int len;
629 {
630 register struct le_softc *le = &le_softc[unit];
631 register struct ether_header *et;
632 struct mbuf *m;
633 int off, resid;
634
635 le->sc_if.if_ipackets++;
636
637 et = (struct ether_header *)buf;
638 et->ether_type = ntohs((u_short)et->ether_type);
639
640 /* adjust input length to account for header and CRC */
641 len = len - sizeof(struct ether_header) - 4;
642
643 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
644 if (et->ether_type >= ETHERTYPE_TRAIL &&
645 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
646 off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
647 if (off >= ETHERMTU)
648 return; /* sanity */
649 et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
650 resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
651 if (off + resid > len)
652 return; /* sanity */
653 len = off + resid;
654 } else
655 off = 0;
656
657 if (len <= 0) {
658 if (ledebug)
659 log(LOG_WARNING,
660 "le%d: ierror(runt packet): from %s: len=%d\n",
661 unit, ether_sprintf(et->ether_shost), len);
662 le->sc_runt++;
663 le->sc_if.if_ierrors++;
664 return;
665 }
666 #if NBPFILTER > 0
667 /*
668 * Check if there's a bpf filter listening on this interface.
669 * If so, hand off the raw packet to bpf, which must deal with
670 * trailers in its own way.
671 */
672 if (le->sc_bpf) {
673 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
674
675 /*
676 * Note that the interface cannot be in promiscuous mode if
677 * there are no bpf listeners. And if we are in promiscuous
678 * mode, we have to check if this packet is really ours.
679 *
680 * XXX This test does not support multicasts.
681 */
682 if ((le->sc_if.if_flags & IFF_PROMISC)
683 && bcmp(et->ether_dhost, le->sc_addr,
684 sizeof(et->ether_dhost)) != 0
685 && bcmp(et->ether_dhost, etherbroadcastaddr,
686 sizeof(et->ether_dhost)) != 0)
687 return;
688 }
689 #endif
690 /*
691 * Pull packet off interface. Off is nonzero if packet
692 * has trailing header; leget will then force this header
693 * information to be at the front, but we still have to drop
694 * the type and length which are at the front of any trailer data.
695 */
696 m = leget(buf, len, off, &le->sc_if);
697 if (m == 0)
698 return;
699
700 ether_input(&le->sc_if, et, m);
701 }
702
703 /*
704 * Routine to copy from mbuf chain to transmit
705 * buffer in board local memory.
706 */
707 leput(lebuf, m)
708 register char *lebuf;
709 register struct mbuf *m;
710 {
711 register struct mbuf *mp;
712 register int len, tlen = 0;
713
714 for (mp = m; mp; mp = mp->m_next) {
715 len = mp->m_len;
716 if (len == 0)
717 continue;
718 tlen += len;
719 bcopy(mtod(mp, char *), lebuf, len);
720 lebuf += len;
721 }
722
723 m_freem(m);
724
725 if (tlen < LEMINSIZE) {
726 bzero(lebuf, LEMINSIZE - tlen);
727 tlen = LEMINSIZE;
728 }
729
730 return(tlen);
731 }
732
733 /*
734 * Routine to copy from board local memory into mbufs.
735 */
736 struct mbuf *
737 leget(lebuf, totlen, off0, ifp)
738 char *lebuf;
739 int totlen, off0;
740 struct ifnet *ifp;
741 {
742 register struct mbuf *m;
743 struct mbuf *top = 0, **mp = ⊤
744 register int off = off0, len;
745 register char *cp;
746 char *epkt;
747
748 lebuf += sizeof (struct ether_header);
749 cp = lebuf;
750 epkt = cp + totlen;
751 if (off) {
752 cp += off + 2 * sizeof(u_short);
753 totlen -= 2 * sizeof(u_short);
754 }
755
756 MGETHDR(m, M_DONTWAIT, MT_DATA);
757
758 if (m == 0)
759 return (0);
760
761 m->m_pkthdr.rcvif = ifp;
762 m->m_pkthdr.len = totlen;
763 m->m_len = MHLEN;
764
765 while (totlen > 0) {
766
767 if (top) {
768 MGET(m, M_DONTWAIT, MT_DATA);
769 if (m == 0) {
770 m_freem(top);
771 return (0);
772 }
773 m->m_len = MLEN;
774 }
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
795 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
796 cp += len;
797 *mp = m;
798 mp = &m->m_next;
799 totlen -= len;
800
801 if (cp == epkt)
802 cp = lebuf;
803
804 }
805
806 return (top);
807 }
808
809 /*
810 * Process an ioctl request.
811 */
812 leioctl(ifp, cmd, data)
813 register struct ifnet *ifp;
814 u_long cmd;
815 caddr_t data;
816 {
817 register struct ifaddr *ifa = (struct ifaddr *)data;
818 struct le_softc *le = &le_softc[ifp->if_unit];
819 struct lereg1 *ler1 = le->sc_r1;
820 int s = splimp(), error = 0;
821
822 switch (cmd) {
823
824 case SIOCSIFADDR:
825 ifp->if_flags |= IFF_UP;
826 switch (ifa->ifa_addr->sa_family) {
827 #ifdef INET
828 case AF_INET:
829 leinit(ifp->if_unit); /* before arpwhohas */
830 ((struct arpcom *)ifp)->ac_ipaddr =
831 IA_SIN(ifa)->sin_addr;
832 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
833 break;
834 #endif
835 #ifdef NS
836 case AF_NS:
837 {
838 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
839
840 if (ns_nullhost(*ina))
841 ina->x_host = *(union ns_host *)(le->sc_addr);
842 else {
843 /*
844 * The manual says we can't change the address
845 * while the receiver is armed,
846 * so reset everything
847 */
848 ifp->if_flags &= ~IFF_RUNNING;
849 bcopy((caddr_t)ina->x_host.c_host,
850 (caddr_t)le->sc_addr, sizeof(le->sc_addr));
851 }
852 leinit(ifp->if_unit); /* does le_setaddr() */
853 break;
854 }
855 #endif
856 default:
857 leinit(ifp->if_unit);
858 break;
859 }
860 break;
861
862 case SIOCSIFFLAGS:
863 if ((ifp->if_flags & IFF_UP) == 0 &&
864 ifp->if_flags & IFF_RUNNING) {
865 ler1->ler1_rdp = LE_STOP;
866 ifp->if_flags &= ~IFF_RUNNING;
867 } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0)
868 leinit(ifp->if_unit);
869
870 /*
871 * If the state of the promiscuous bit changes, the interface
872 * must be reset to effect the change.
873 */
874 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && (ifp->if_flags & IFF_RUNNING)) {
875 le->sc_iflags = ifp->if_flags;
876 lereset(ifp->if_unit);
877 (void)lestart(ifp);
878 }
879 break;
880
881 default:
882 error = EINVAL;
883 }
884
885 splx(s);
886 return (error);
887 }
888
889 leerror(unit, stat)
890 int unit;
891 int stat;
892 {
893 if (!ledebug)
894 return;
895
896 /*
897 * Not all transceivers implement heartbeat
898 * so we only log CERR once.
899 */
900 if ((stat & LE_CERR) && le_softc[unit].sc_cerr)
901 return;
902
903 log(LOG_WARNING,
904 "le%d: error: stat=%b\n", unit,
905 stat,
906 "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
907 }
908
909 lererror(unit, msg)
910 int unit;
911 char *msg;
912 {
913 register struct le_softc *le = &le_softc[unit];
914 register struct lermd *rmd;
915 int len;
916
917 if (!ledebug)
918 return;
919
920 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
921 len = rmd->rmd3;
922
923 log(LOG_WARNING,
924 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
925 unit, msg,
926 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
927 le->sc_rmd, len,
928 rmd->rmd1,
929 "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
930 }
931
932 lexerror(unit)
933 int unit;
934 {
935 register struct le_softc *le = &le_softc[unit];
936 int bix;
937 register struct letmd *tmd;
938 int len;
939
940 if (!ledebug)
941 return;
942
943 bix = (le->sc_tmd - le->sc_no_td + LETBUF) % LETBUF;
944 tmd = &le->sc_r2->ler2_tmd[bix];
945 len = -tmd->tmd2;
946
947 log(LOG_WARNING,
948 "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
949 unit,
950 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
951 0, len,
952 tmd->tmd1,
953 "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
954 tmd->tmd3,
955 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
956 }
957
958 #endif
959
960
961