|
|
1.1 root 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: *
1.1.1.2 ! root 33: * from: @(#)if_le.c 7.6 (Berkeley) 5/8/91
! 34: * if_le.c,v 1.2 1993/05/22 07:56:23 cgd Exp
1.1 root 35: */
36:
37: #include "le.h"
38: #if NLE > 0
39:
40: #include "bpfilter.h"
41:
42: /*
43: * AMD 7990 LANCE
44: *
45: * This driver will generate and accept tailer encapsulated packets even
46: * though it buys us nothing. The motivation was to avoid incompatibilities
47: * with VAXen, SUNs, and others that handle and benefit from them.
48: * This reasoning is dubious.
49: */
50: #include "sys/param.h"
51: #include "sys/systm.h"
52: #include "sys/mbuf.h"
53: #include "sys/buf.h"
54: #include "sys/protosw.h"
55: #include "sys/socket.h"
56: #include "sys/syslog.h"
57: #include "sys/ioctl.h"
58: #include "sys/errno.h"
59:
60: #include "net/if.h"
61: #include "net/netisr.h"
62: #include "net/route.h"
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: #ifdef RMP
78: #include "netrmp/rmp.h"
79: #include "netrmp/rmp_var.h"
80: #endif
81:
82: #include "../include/cpu.h"
83: #include "../hp300/isr.h"
84: #include "../include/mtpr.h"
85: #include "device.h"
86: #include "if_lereg.h"
87:
88: #if NBPFILTER > 0
89: #include "../net/bpf.h"
90: #include "../net/bpfdesc.h"
91: #endif
92:
93: /* offsets for: ID, REGS, MEM, NVRAM */
94: int lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
95:
96: int leattach();
97: struct driver ledriver = {
98: leattach, "le",
99: };
100:
101: struct isr le_isr[NLE];
102: int ledebug = 0; /* console error messages */
103:
104: int leintr(), leinit(), leioctl(), lestart(), ether_output();
105: struct mbuf *leget();
106: extern struct ifnet loif;
107:
108: /*
109: * Ethernet software status per interface.
110: *
111: * Each interface is referenced by a network interface structure,
112: * le_if, which the routing code uses to locate the interface.
113: * This structure contains the output queue for the interface, its address, ...
114: */
115: struct le_softc {
116: struct arpcom sc_ac; /* common Ethernet structures */
117: #define sc_if sc_ac.ac_if /* network-visible interface */
118: #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
119: struct lereg0 *sc_r0; /* DIO registers */
120: struct lereg1 *sc_r1; /* LANCE registers */
121: struct lereg2 *sc_r2; /* dual-port RAM */
122: int sc_rmd; /* predicted next rmd to process */
123: int sc_runt;
124: int sc_jab;
125: int sc_merr;
126: int sc_babl;
127: int sc_cerr;
128: int sc_miss;
129: int sc_xint;
130: int sc_xown;
131: int sc_uflo;
132: int sc_rxlen;
133: int sc_rxoff;
134: int sc_txoff;
135: int sc_busy;
136: short sc_iflags;
137: #if NBPFILTER > 0
138: caddr_t sc_bpf;
139: #endif
140: } le_softc[NLE];
141:
142: /* access LANCE registers */
143: #define LERDWR(cntl, src, dst) \
144: do { \
145: (dst) = (src); \
146: } while (((cntl)->ler0_status & LE_ACK) == 0);
147:
148: /*
149: * Interface exists: make available by filling in network interface
150: * record. System will initialize the interface when it is ready
151: * to accept packets.
152: */
153: leattach(hd)
154: struct hp_device *hd;
155: {
156: register struct lereg0 *ler0;
157: register struct lereg2 *ler2;
158: struct lereg2 *lemem = 0;
159: struct le_softc *le = &le_softc[hd->hp_unit];
160: struct ifnet *ifp = &le->sc_if;
161: char *cp;
162: int i;
163:
164: ler0 = le->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
165: le->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
166: ler2 = le->sc_r2 = (struct lereg2 *)(lestd[2] + (int)hd->hp_addr);
167: if (ler0->ler0_id != LEID)
168: return(0);
169: le_isr[hd->hp_unit].isr_intr = leintr;
170: hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status);
171: le_isr[hd->hp_unit].isr_arg = hd->hp_unit;
172: ler0->ler0_id = 0xFF;
173: DELAY(100);
174:
175: /*
176: * Read the ethernet address off the board, one nibble at a time.
177: */
178: cp = (char *)(lestd[3] + (int)hd->hp_addr);
179: for (i = 0; i < sizeof(le->sc_addr); i++) {
180: le->sc_addr[i] = (*++cp & 0xF) << 4;
181: cp++;
182: le->sc_addr[i] |= *++cp & 0xF;
183: cp++;
184: }
185: printf("le%d: hardware address %s\n", hd->hp_unit,
186: ether_sprintf(le->sc_addr));
187:
188: /*
189: * Setup for transmit/receive
190: */
191: ler2->ler2_mode = LE_MODE;
192: ler2->ler2_padr[0] = le->sc_addr[1];
193: ler2->ler2_padr[1] = le->sc_addr[0];
194: ler2->ler2_padr[2] = le->sc_addr[3];
195: ler2->ler2_padr[3] = le->sc_addr[2];
196: ler2->ler2_padr[4] = le->sc_addr[5];
197: ler2->ler2_padr[5] = le->sc_addr[4];
198: #ifdef RMP
199: /*
200: * Set up logical addr filter to accept multicast 9:0:9:0:0:4
201: * This should be an ioctl() to the driver. (XXX)
202: */
203: ler2->ler2_ladrf0 = 0x00100000;
204: ler2->ler2_ladrf1 = 0x0;
205: #else
206: ler2->ler2_ladrf0 = 0;
207: ler2->ler2_ladrf1 = 0;
208: #endif
209: ler2->ler2_rlen = LE_RLEN;
210: ler2->ler2_rdra = (int)lemem->ler2_rmd;
211: ler2->ler2_tlen = LE_TLEN;
212: ler2->ler2_tdra = (int)lemem->ler2_tmd;
213: isrlink(&le_isr[hd->hp_unit]);
214: ler0->ler0_status = LE_IE;
215:
216: ifp->if_unit = hd->hp_unit;
217: ifp->if_name = "le";
218: ifp->if_mtu = ETHERMTU;
219: ifp->if_init = leinit;
220: ifp->if_ioctl = leioctl;
221: ifp->if_output = ether_output;
222: ifp->if_start = lestart;
223: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
224: #if NBPFILTER > 0
225: bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
226: #endif
227: if_attach(ifp);
228: return (1);
229: }
230:
231: ledrinit(ler2)
232: register struct lereg2 *ler2;
233: {
234: register struct lereg2 *lemem = 0;
235: register int i;
236:
237: for (i = 0; i < LERBUF; i++) {
238: ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
239: ler2->ler2_rmd[i].rmd1 = LE_OWN;
240: ler2->ler2_rmd[i].rmd2 = -LEMTU;
241: ler2->ler2_rmd[i].rmd3 = 0;
242: }
243: for (i = 0; i < LETBUF; i++) {
244: ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
245: ler2->ler2_tmd[i].tmd1 = 0;
246: ler2->ler2_tmd[i].tmd2 = 0;
247: ler2->ler2_tmd[i].tmd3 = 0;
248: }
249: }
250:
251: lereset(unit)
252: register int unit;
253: {
254: register struct le_softc *le = &le_softc[unit];
255: register struct lereg0 *ler0 = le->sc_r0;
256: register struct lereg1 *ler1 = le->sc_r1;
257: register struct lereg2 *lemem = 0;
258: register int timo = 100000;
259: register int stat;
260:
261: #ifdef lint
262: stat = unit;
263: #endif
264: #if NBPFILTER > 0
265: if (le->sc_if.if_flags & IFF_PROMISC)
266: /* set the promiscuous bit */
267: le->sc_r2->ler2_mode = LE_MODE|0x8000;
268: else
269: le->sc_r2->ler2_mode = LE_MODE;
270: #endif
271: LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
272: LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
273: ledrinit(le->sc_r2);
274: le->sc_rmd = 0;
275: LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
276: LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
277: LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
278: LERDWR(ler0, 0, ler1->ler1_rdp);
279: LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
280: LERDWR(ler0, LE_INIT, ler1->ler1_rdp);
281: do {
282: if (--timo == 0) {
283: printf("le%d: init timeout, stat = 0x%x\n",
284: unit, stat);
285: break;
286: }
287: LERDWR(ler0, ler1->ler1_rdp, stat);
288: } while ((stat & LE_IDON) == 0);
289: LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
290: LERDWR(ler0, LE_CSR3, ler1->ler1_rap);
291: LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);
292: LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
293: LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
294: le->sc_if.if_flags &= ~IFF_OACTIVE;
295: }
296:
297: /*
298: * Initialization of interface
299: */
300: leinit(unit)
301: int unit;
302: {
303: struct le_softc *le = &le_softc[unit];
304: register struct ifnet *ifp = &le->sc_if;
305: int s;
306:
307: /* not yet, if address still unknown */
308: if (ifp->if_addrlist == (struct ifaddr *)0)
309: return;
310: if ((ifp->if_flags & IFF_RUNNING) == 0) {
311: s = splimp();
312: ifp->if_flags |= IFF_RUNNING;
313: lereset(unit);
314: (void) lestart(ifp);
315: splx(s);
316: }
317: }
318:
319: /*
320: * Start output on interface. Get another datagram to send
321: * off of the interface queue, and copy it to the interface
322: * before starting the output.
323: */
324: lestart(ifp)
325: struct ifnet *ifp;
326: {
327: register struct le_softc *le = &le_softc[ifp->if_unit];
328: register struct letmd *tmd;
329: register struct mbuf *m;
330: int len;
331:
332: if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
333: return (0);
334: IF_DEQUEUE(&le->sc_if.if_snd, m);
335: if (m == 0)
336: return (0);
337: len = leput(le->sc_r2->ler2_tbuf[0], m);
338: #if NBPFILTER > 0
339: /*
340: * If bpf is listening on this interface, let it
341: * see the packet before we commit it to the wire.
342: */
343: if (le->sc_bpf)
344: bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len);
345: #endif
346: tmd = le->sc_r2->ler2_tmd;
347: tmd->tmd3 = 0;
348: tmd->tmd2 = -len;
349: tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
350: le->sc_if.if_flags |= IFF_OACTIVE;
351: return (0);
352: }
353:
354: leintr(unit)
355: register int unit;
356: {
357: register struct le_softc *le = &le_softc[unit];
358: register struct lereg0 *ler0 = le->sc_r0;
359: register struct lereg1 *ler1;
360: register int stat;
361:
362: if ((ler0->ler0_status & LE_IR) == 0)
363: return(0);
364: if (ler0->ler0_status & LE_JAB) {
365: le->sc_jab++;
366: lereset(unit);
367: return(1);
368: }
369: ler1 = le->sc_r1;
370: LERDWR(ler0, ler1->ler1_rdp, stat);
371: if (stat & LE_SERR) {
372: leerror(unit, stat);
373: if (stat & LE_MERR) {
374: le->sc_merr++;
375: lereset(unit);
376: return(1);
377: }
378: if (stat & LE_BABL)
379: le->sc_babl++;
380: if (stat & LE_CERR)
381: le->sc_cerr++;
382: if (stat & LE_MISS)
383: le->sc_miss++;
384: LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
385: }
386: if ((stat & LE_RXON) == 0) {
387: le->sc_rxoff++;
388: lereset(unit);
389: return(1);
390: }
391: if ((stat & LE_TXON) == 0) {
392: le->sc_txoff++;
393: lereset(unit);
394: return(1);
395: }
396: if (stat & LE_RINT) {
397: /* interrupt is cleared in lerint */
398: lerint(unit);
399: }
400: if (stat & LE_TINT) {
401: LERDWR(ler0, LE_TINT|LE_INEA, ler1->ler1_rdp);
402: lexint(unit);
403: }
404: return(1);
405: }
406:
407: /*
408: * Ethernet interface transmitter interrupt.
409: * Start another output if more data to send.
410: */
411: lexint(unit)
412: register int unit;
413: {
414: register struct le_softc *le = &le_softc[unit];
415: register struct letmd *tmd = le->sc_r2->ler2_tmd;
416:
417: if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
418: le->sc_xint++;
419: return;
420: }
421: if (tmd->tmd1 & LE_OWN) {
422: le->sc_xown++;
423: return;
424: }
425: if (tmd->tmd1 & LE_ERR) {
426: err:
427: lexerror(unit);
428: le->sc_if.if_oerrors++;
429: if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
430: le->sc_uflo++;
431: lereset(unit);
432: }
433: else if (tmd->tmd3 & LE_LCOL)
434: le->sc_if.if_collisions++;
435: else if (tmd->tmd3 & LE_RTRY)
436: le->sc_if.if_collisions += 16;
437: }
438: else if (tmd->tmd3 & LE_TBUFF)
439: /* XXX documentation says BUFF not included in ERR */
440: goto err;
441: else if (tmd->tmd1 & LE_ONE)
442: le->sc_if.if_collisions++;
443: else if (tmd->tmd1 & LE_MORE)
444: /* what is the real number? */
445: le->sc_if.if_collisions += 2;
446: else
447: le->sc_if.if_opackets++;
448: le->sc_if.if_flags &= ~IFF_OACTIVE;
449: (void) lestart(&le->sc_if);
450: }
451:
452: #define LENEXTRMP \
453: if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
454:
455: /*
456: * Ethernet interface receiver interrupt.
457: * If input error just drop packet.
458: * Decapsulate packet based on type and pass to type specific
459: * higher-level input routine.
460: */
461: lerint(unit)
462: int unit;
463: {
464: register struct le_softc *le = &le_softc[unit];
465: register int bix = le->sc_rmd;
466: register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
467:
468: /*
469: * Out of sync with hardware, should never happen?
470: */
471: if (rmd->rmd1 & LE_OWN) {
472: LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
473: return;
474: }
475:
476: /*
477: * Process all buffers with valid data
478: */
479: while ((rmd->rmd1 & LE_OWN) == 0) {
480: int len = rmd->rmd3;
481:
482: /* Clear interrupt to avoid race condition */
483: LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
484:
485: if (rmd->rmd1 & LE_ERR) {
486: le->sc_rmd = bix;
487: lererror(unit, "bad packet");
488: le->sc_if.if_ierrors++;
489: } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
490: /*
491: * Find the end of the packet so we can see how long
492: * it was. We still throw it away.
493: */
494: do {
495: LERDWR(le->sc_r0, LE_RINT|LE_INEA,
496: le->sc_r1->ler1_rdp);
497: rmd->rmd3 = 0;
498: rmd->rmd1 = LE_OWN;
499: LENEXTRMP;
500: } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
501: le->sc_rmd = bix;
502: lererror(unit, "chained buffer");
503: le->sc_rxlen++;
504: /*
505: * If search terminated without successful completion
506: * we reset the hardware (conservative).
507: */
508: if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
509: LE_ENP) {
510: lereset(unit);
511: return;
512: }
513: } else
514: leread(unit, le->sc_r2->ler2_rbuf[bix], len);
515: rmd->rmd3 = 0;
516: rmd->rmd1 = LE_OWN;
517: LENEXTRMP;
518: }
519: le->sc_rmd = bix;
520: }
521:
522: leread(unit, buf, len)
523: int unit;
524: char *buf;
525: int len;
526: {
527: register struct le_softc *le = &le_softc[unit];
528: register struct ether_header *et;
529: struct mbuf *m;
530: int off, resid;
531:
532: le->sc_if.if_ipackets++;
533: et = (struct ether_header *)buf;
534: et->ether_type = ntohs((u_short)et->ether_type);
535: /* adjust input length to account for header and CRC */
536: len = len - sizeof(struct ether_header) - 4;
537:
538: #ifdef RMP
539: /* (XXX)
540: *
541: * If Ethernet Type field is < MaxPacketSize, we probably have
542: * a IEEE802 packet here. Make sure that the size is at least
543: * that of the HP LLC. Also do sanity checks on length of LLC
544: * (old Ethernet Type field) and packet length.
545: *
546: * Provided the above checks succeed, change `len' to reflect
547: * the length of the LLC (i.e. et->ether_type) and change the
548: * type field to ETHERTYPE_IEEE so we can switch() on it later.
549: * Yes, this is a hack and will eventually be done "right".
550: */
551: if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) &&
552: len >= et->ether_type && len >= IEEE802LEN_MIN) {
553: len = et->ether_type;
554: et->ether_type = ETHERTYPE_IEEE; /* hack! */
555: }
556: #endif
557:
558: #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
559: if (et->ether_type >= ETHERTYPE_TRAIL &&
560: et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
561: off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
562: if (off >= ETHERMTU)
563: return; /* sanity */
564: et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
565: resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
566: if (off + resid > len)
567: return; /* sanity */
568: len = off + resid;
569: } else
570: off = 0;
571:
572: if (len <= 0) {
573: if (ledebug)
574: log(LOG_WARNING,
575: "le%d: ierror(runt packet): from %s: len=%d\n",
576: unit, ether_sprintf(et->ether_shost), len);
577: le->sc_runt++;
578: le->sc_if.if_ierrors++;
579: return;
580: }
581: #if NBPFILTER > 0
582: /*
583: * Check if there's a bpf filter listening on this interface.
584: * If so, hand off the raw packet to bpf, which must deal with
585: * trailers in its own way.
586: */
587: if (le->sc_bpf) {
588: bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
589:
590: /*
591: * Note that the interface cannot be in promiscuous mode if
592: * there are no bpf listeners. And if we are in promiscuous
593: * mode, we have to check if this packet is really ours.
594: *
595: * XXX This test does not support multicasts.
596: */
597: if ((le->sc_if.if_flags & IFF_PROMISC)
598: && bcmp(et->ether_dhost, le->sc_addr,
599: sizeof(et->ether_dhost)) != 0
600: && bcmp(et->ether_dhost, etherbroadcastaddr,
601: sizeof(et->ether_dhost)) != 0)
602: return;
603: }
604: #endif
605: /*
606: * Pull packet off interface. Off is nonzero if packet
607: * has trailing header; leget will then force this header
608: * information to be at the front, but we still have to drop
609: * the type and length which are at the front of any trailer data.
610: */
611: m = leget(buf, len, off, &le->sc_if);
612: if (m == 0)
613: return;
614: #ifdef RMP
615: /*
616: * (XXX)
617: * This needs to be integrated with the ISO stuff in ether_input()
618: */
619: if (et->ether_type == ETHERTYPE_IEEE) {
620: /*
621: * Snag the Logical Link Control header (IEEE 802.2).
622: */
623: struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc);
624:
625: /*
626: * If the DSAP (and HP's extended DXSAP) indicate this
627: * is an RMP packet, hand it to the raw input routine.
628: */
629: if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) {
630: static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT};
631: static struct sockaddr rmp_src = {AF_RMP};
632: static struct sockaddr rmp_dst = {AF_RMP};
633:
634: bcopy(et->ether_shost, rmp_src.sa_data,
635: sizeof(et->ether_shost));
636: bcopy(et->ether_dhost, rmp_dst.sa_data,
637: sizeof(et->ether_dhost));
638:
639: raw_input(m, &rmp_sp, &rmp_src, &rmp_dst);
640: return;
641: }
642: }
643: #endif
644: ether_input(&le->sc_if, et, m);
645: }
646:
647: /*
648: * Routine to copy from mbuf chain to transmit
649: * buffer in board local memory.
650: */
651: leput(lebuf, m)
652: register char *lebuf;
653: register struct mbuf *m;
654: {
655: register struct mbuf *mp;
656: register int len, tlen = 0;
657:
658: for (mp = m; mp; mp = mp->m_next) {
659: len = mp->m_len;
660: if (len == 0)
661: continue;
662: tlen += len;
663: bcopy(mtod(mp, char *), lebuf, len);
664: lebuf += len;
665: }
666: m_freem(m);
667: if (tlen < LEMINSIZE) {
668: bzero(lebuf, LEMINSIZE - tlen);
669: tlen = LEMINSIZE;
670: }
671: return(tlen);
672: }
673:
674: /*
675: * Routine to copy from board local memory into mbufs.
676: */
677: struct mbuf *
678: leget(lebuf, totlen, off0, ifp)
679: char *lebuf;
680: int totlen, off0;
681: struct ifnet *ifp;
682: {
683: register struct mbuf *m;
684: struct mbuf *top = 0, **mp = ⊤
685: register int off = off0, len;
686: register char *cp;
687: char *epkt;
688:
689: lebuf += sizeof (struct ether_header);
690: cp = lebuf;
691: epkt = cp + totlen;
692: if (off) {
693: cp += off + 2 * sizeof(u_short);
694: totlen -= 2 * sizeof(u_short);
695: }
696:
697: MGETHDR(m, M_DONTWAIT, MT_DATA);
698: if (m == 0)
699: return (0);
700: m->m_pkthdr.rcvif = ifp;
701: m->m_pkthdr.len = totlen;
702: m->m_len = MHLEN;
703:
704: while (totlen > 0) {
705: if (top) {
706: MGET(m, M_DONTWAIT, MT_DATA);
707: if (m == 0) {
708: m_freem(top);
709: return (0);
710: }
711: m->m_len = MLEN;
712: }
713: len = min(totlen, epkt - cp);
714: if (len >= MINCLSIZE) {
715: MCLGET(m, M_DONTWAIT);
716: if (m->m_flags & M_EXT)
717: m->m_len = len = min(len, MCLBYTES);
718: else
719: len = m->m_len;
720: } else {
721: /*
722: * Place initial small packet/header at end of mbuf.
723: */
724: if (len < m->m_len) {
725: if (top == 0 && len + max_linkhdr <= m->m_len)
726: m->m_data += max_linkhdr;
727: m->m_len = len;
728: } else
729: len = m->m_len;
730: }
731: bcopy(cp, mtod(m, caddr_t), (unsigned)len);
732: cp += len;
733: *mp = m;
734: mp = &m->m_next;
735: totlen -= len;
736: if (cp == epkt)
737: cp = lebuf;
738: }
739: return (top);
740: }
741:
742: /*
743: * Process an ioctl request.
744: */
745: leioctl(ifp, cmd, data)
746: register struct ifnet *ifp;
747: int cmd;
748: caddr_t data;
749: {
750: register struct ifaddr *ifa = (struct ifaddr *)data;
751: struct le_softc *le = &le_softc[ifp->if_unit];
752: struct lereg1 *ler1 = le->sc_r1;
753: int s = splimp(), error = 0;
754:
755: switch (cmd) {
756:
757: case SIOCSIFADDR:
758: ifp->if_flags |= IFF_UP;
759: switch (ifa->ifa_addr->sa_family) {
760: #ifdef INET
761: case AF_INET:
762: leinit(ifp->if_unit); /* before arpwhohas */
763: ((struct arpcom *)ifp)->ac_ipaddr =
764: IA_SIN(ifa)->sin_addr;
765: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
766: break;
767: #endif
768: #ifdef NS
769: case AF_NS:
770: {
771: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
772:
773: if (ns_nullhost(*ina))
774: ina->x_host = *(union ns_host *)(le->sc_addr);
775: else {
776: /*
777: * The manual says we can't change the address
778: * while the receiver is armed,
779: * so reset everything
780: */
781: ifp->if_flags &= ~IFF_RUNNING;
782: bcopy((caddr_t)ina->x_host.c_host,
783: (caddr_t)le->sc_addr, sizeof(le->sc_addr));
784: }
785: leinit(ifp->if_unit); /* does le_setaddr() */
786: break;
787: }
788: #endif
789: default:
790: leinit(ifp->if_unit);
791: break;
792: }
793: break;
794:
795: case SIOCSIFFLAGS:
796: if ((ifp->if_flags & IFF_UP) == 0 &&
797: ifp->if_flags & IFF_RUNNING) {
798: LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
799: ifp->if_flags &= ~IFF_RUNNING;
800: } else if (ifp->if_flags & IFF_UP &&
801: (ifp->if_flags & IFF_RUNNING) == 0)
802: leinit(ifp->if_unit);
803: /*
804: * If the state of the promiscuous bit changes, the interface
805: * must be reset to effect the change.
806: */
807: if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
808: (ifp->if_flags & IFF_RUNNING)) {
809: le->sc_iflags = ifp->if_flags;
810: lereset(ifp->if_unit);
811: lestart(ifp);
812: }
813: break;
814:
815: default:
816: error = EINVAL;
817: }
818: splx(s);
819: return (error);
820: }
821:
822: leerror(unit, stat)
823: int unit;
824: int stat;
825: {
826: if (!ledebug)
827: return;
828:
829: /*
830: * Not all transceivers implement heartbeat
831: * so we only log CERR once.
832: */
833: if ((stat & LE_CERR) && le_softc[unit].sc_cerr)
834: return;
835: log(LOG_WARNING,
836: "le%d: error: stat=%b\n", unit,
837: stat,
838: "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
839: }
840:
841: lererror(unit, msg)
842: int unit;
843: char *msg;
844: {
845: register struct le_softc *le = &le_softc[unit];
846: register struct lermd *rmd;
847: int len;
848:
849: if (!ledebug)
850: return;
851:
852: rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
853: len = rmd->rmd3;
854: log(LOG_WARNING,
855: "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
856: unit, msg,
857: len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
858: le->sc_rmd, len,
859: rmd->rmd1,
860: "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
861: }
862:
863: lexerror(unit)
864: int unit;
865: {
866: register struct le_softc *le = &le_softc[unit];
867: register struct letmd *tmd;
868: int len;
869:
870: if (!ledebug)
871: return;
872:
873: tmd = le->sc_r2->ler2_tmd;
874: len = -tmd->tmd2;
875: log(LOG_WARNING,
876: "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
877: unit,
878: len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
879: 0, len,
880: tmd->tmd1,
881: "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
882: tmd->tmd3,
883: "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
884: }
885: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.