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