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