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