1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if_ec.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "ec.h"
10: #include "enetfilter.h"
11: #if NEC > 0
12:
13: /*
14: * 3Com Ethernet Controller interface
15: */
16: #include "../machine/pte.h"
17:
18: #include "param.h"
19: #include "systm.h"
20: #include "mbuf.h"
21: #include "buf.h"
22: #include "protosw.h"
23: #include "socket.h"
24: #include "syslog.h"
25: #include "vmmac.h"
26: #include "ioctl.h"
27: #include "errno.h"
28:
29: #include "../net/if.h"
30: #include "../net/netisr.h"
31: #include "../net/route.h"
32:
33: #ifdef INET
34: #include "../netinet/in.h"
35: #include "../netinet/in_systm.h"
36: #include "../netinet/in_var.h"
37: #include "../netinet/ip.h"
38: #include "../netinet/if_ether.h"
39: #endif
40:
41: #ifdef NS
42: #include "../netns/ns.h"
43: #include "../netns/ns_if.h"
44: #endif
45:
46: #include "../vax/cpu.h"
47: #include "../vax/mtpr.h"
48: #include "if_ecreg.h"
49: #include "if_uba.h"
50: #if NENETFILTER > 0
51: #include "../net/enet.h"
52: #endif NENETFILTER > 0
53: #include "../vaxuba/ubareg.h"
54: #include "../vaxuba/ubavar.h"
55:
56: #if CLSIZE == 2
57: #define ECBUFSIZE 32 /* on-board memory, clusters */
58: #endif
59:
60: int ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
61: struct uba_device *ecinfo[NEC];
62: u_short ecstd[] = { 0 };
63: struct uba_driver ecdriver =
64: { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, ecubamem };
65:
66: int ecinit(),ecioctl(),ecoutput(),ecreset();
67: struct mbuf *ecget();
68:
69: extern struct ifnet loif;
70:
71: /*
72: * Ethernet software status per interface.
73: *
74: * Each interface is referenced by a network interface structure,
75: * es_if, which the routing code uses to locate the interface.
76: * This structure contains the output queue for the interface, its address, ...
77: * We also have, for each interface, a UBA interface structure, which
78: * contains information about the UNIBUS resources held by the interface:
79: * map registers, buffered data paths, etc. Information is cached in this
80: * structure for use by the if_uba.c routines in running the interface
81: * efficiently.
82: */
83: struct ec_softc {
84: struct arpcom es_ac; /* common Ethernet structures */
85: #define es_if es_ac.ac_if /* network-visible interface */
86: #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */
87: struct ifuba es_ifuba; /* UNIBUS resources */
88: short es_mask; /* mask for current output delay */
89: short es_oactive; /* is output active? */
90: #if NENETFILTER > 0
91: short es_enetunit; /* unit number for enet filtering */
92: #endif NENETFILTER > 0
93: u_char *es_buf[16]; /* virtual addresses of buffers */
94: } ec_softc[NEC];
95:
96: /*
97: * Configure on-board memory for an interface.
98: * Called from autoconfig and after a uba reset.
99: * The address of the memory on the uba is supplied in the device flags.
100: */
101: ecubamem(ui, uban)
102: register struct uba_device *ui;
103: {
104: register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags];
105: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
106:
107: /*
108: * Make sure csr is there (we run before ecprobe).
109: */
110: if (badaddr((caddr_t)addr, 2))
111: return (-1);
112: #if VAX780
113: if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
114: uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
115: return (-1);
116: }
117: #endif
118: /*
119: * Make sure memory is turned on
120: */
121: addr->ec_rcr = EC_AROM;
122: /*
123: * Tell the system that the board has memory here, so it won't
124: * attempt to allocate the addresses later.
125: */
126: if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) {
127: printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit);
128: addr->ec_rcr = EC_MDISAB; /* disable memory */
129: return (-1);
130: }
131: /*
132: * Check for existence of buffers on Unibus.
133: */
134: if (badaddr((caddr_t)ecbuf, 2)) {
135: bad:
136: printf("ec%d: buffer mem not found\n", ui->ui_unit);
137: (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0);
138: addr->ec_rcr = EC_MDISAB; /* disable memory */
139: return (-1);
140: }
141: #if VAX780
142: if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
143: uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
144: goto bad;
145: }
146: #endif
147: if (ui->ui_alive == 0) /* Only printf from autoconfig */
148: printf("ec%d: mem %x-%x\n", ui->ui_unit,
149: ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1);
150: ui->ui_type = 1; /* Memory on, allocated */
151: return (0);
152: }
153:
154: /*
155: * Do output DMA to determine interface presence and
156: * interrupt vector. DMA is too short to disturb other hosts.
157: */
158: ecprobe(reg, ui)
159: caddr_t reg;
160: struct uba_device *ui;
161: {
162: register int br, cvec; /* r11, r10 value-result */
163: register struct ecdevice *addr = (struct ecdevice *)reg;
164: register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags];
165:
166: #ifdef lint
167: br = 0; cvec = br; br = cvec;
168: ecrint(0); ecxint(0); eccollide(0);
169: #endif
170:
171: /*
172: * Check that buffer memory was found and enabled.
173: */
174: if (ui->ui_type == 0)
175: return(0);
176: /*
177: * Make a one byte packet in what should be buffer #0.
178: * Submit it for sending. This should cause an xmit interrupt.
179: * The xmit interrupt vector is 8 bytes after the receive vector,
180: * so adjust for this before returning.
181: */
182: *(u_short *)ecbuf = (u_short) 03777;
183: ecbuf[03777] = '\0';
184: addr->ec_xcr = EC_XINTEN|EC_XWBN;
185: DELAY(100000);
186: addr->ec_xcr = EC_XCLR;
187: if (cvec > 0 && cvec != 0x200) {
188: if (cvec & 04) { /* collision interrupt */
189: cvec -= 04;
190: br += 1; /* rcv is collision + 1 */
191: } else { /* xmit interrupt */
192: cvec -= 010;
193: br += 2; /* rcv is xmit + 2 */
194: }
195: }
196: return (1);
197: }
198:
199: /*
200: * Interface exists: make available by filling in network interface
201: * record. System will initialize the interface when it is ready
202: * to accept packets.
203: */
204: ecattach(ui)
205: struct uba_device *ui;
206: {
207: struct ec_softc *es = &ec_softc[ui->ui_unit];
208: register struct ifnet *ifp = &es->es_if;
209: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
210: int i, j;
211: u_char *cp;
212:
213: ifp->if_unit = ui->ui_unit;
214: ifp->if_name = "ec";
215: ifp->if_mtu = ETHERMTU;
216:
217: /*
218: * Read the ethernet address off the board, one nibble at a time.
219: */
220: addr->ec_xcr = EC_UECLR; /* zero address pointer */
221: addr->ec_rcr = EC_AROM;
222: cp = es->es_addr;
223: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
224: for (i=0; i < sizeof (es->es_addr); i++) {
225: *cp = 0;
226: for (j=0; j<=4; j+=4) {
227: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
228: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
229: }
230: cp++;
231: }
232: printf("ec%d: hardware address %s\n", ui->ui_unit,
233: ether_sprintf(es->es_addr));
234: ifp->if_init = ecinit;
235: ifp->if_ioctl = ecioctl;
236: ifp->if_output = ecoutput;
237: ifp->if_reset = ecreset;
238: ifp->if_flags = IFF_BROADCAST;
239: for (i=0; i<16; i++)
240: es->es_buf[i]
241: = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i];
242: #if NENETFILTER > 0
243: {
244: struct endevp enp;
245:
246: enp.end_dev_type = ENDT_10MB;
247: enp.end_addr_len = sizeof(es->es_addr);
248: enp.end_hdr_len = sizeof(struct ether_header);
249: enp.end_MTU = ETHERMTU;
250: bcopy((caddr_t)es->es_addr,
251: (caddr_t)(enp.end_addr), sizeof(es->es_addr));
252: bcopy((caddr_t)etherbroadcastaddr,
253: (caddr_t)(enp.end_broadaddr), sizeof(es->es_addr));
254:
255: es->es_enetunit = enetattach(&es->es_if, &enp);
256: }
257: #endif NENETFILTER > 0
258: if_attach(ifp);
259: }
260:
261: /*
262: * Reset of interface after UNIBUS reset.
263: * If interface is on specified uba, reset its state.
264: */
265: ecreset(unit, uban)
266: int unit, uban;
267: {
268: register struct uba_device *ui;
269:
270: if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
271: ui->ui_ubanum != uban)
272: return;
273: printf(" ec%d", unit);
274: ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING;
275: ecinit(unit);
276: }
277:
278: /*
279: * Initialization of interface; clear recorded pending
280: * operations, and reinitialize UNIBUS usage.
281: */
282: ecinit(unit)
283: int unit;
284: {
285: struct ec_softc *es = &ec_softc[unit];
286: struct ecdevice *addr;
287: register struct ifnet *ifp = &es->es_if;
288: int i, s;
289:
290: /* not yet, if address still unknown */
291: if (ifp->if_addrlist == (struct ifaddr *)0)
292: return;
293:
294: /*
295: * Hang receive buffers and start any pending writes.
296: * Writing into the rcr also makes sure the memory
297: * is turned on.
298: */
299: if ((ifp->if_flags & IFF_RUNNING) == 0) {
300: addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
301: s = splimp();
302: /*
303: * write our ethernet address into the address recognition ROM
304: * so we can always use the same EC_READ bits (referencing ROM),
305: * in case we change the address sometime.
306: * Note that this is safe here as the receiver is NOT armed.
307: */
308: ec_setaddr(es->es_addr, unit);
309: /*
310: * Arm the receiver
311: */
312: for (i = ECRHBF; i >= ECRLBF; i--)
313: addr->ec_rcr = EC_READ | i;
314: es->es_oactive = 0;
315: es->es_mask = ~0;
316: es->es_if.if_flags |= IFF_RUNNING;
317: if (es->es_if.if_snd.ifq_head)
318: ecstart(unit);
319: splx(s);
320: }
321: }
322:
323: /*
324: * Start output on interface. Get another datagram to send
325: * off of the interface queue, and copy it to the interface
326: * before starting the output.
327: */
328: ecstart(unit)
329: {
330: register struct ec_softc *es = &ec_softc[unit];
331: struct ecdevice *addr;
332: struct mbuf *m;
333:
334: if ((es->es_if.if_flags & IFF_RUNNING) == 0)
335: return;
336: IF_DEQUEUE(&es->es_if.if_snd, m);
337: if (m == 0)
338: return;
339: ecput(es->es_buf[ECTBF], m);
340: addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
341: addr->ec_xcr = EC_WRITE|ECTBF;
342: es->es_oactive = 1;
343: }
344:
345: /*
346: * Ethernet interface transmitter interrupt.
347: * Start another output if more data to send.
348: */
349: ecxint(unit)
350: int unit;
351: {
352: register struct ec_softc *es = &ec_softc[unit];
353: register struct ecdevice *addr =
354: (struct ecdevice *)ecinfo[unit]->ui_addr;
355:
356: if (es->es_oactive == 0)
357: return;
358: if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
359: printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
360: addr->ec_xcr, EC_XBITS);
361: es->es_oactive = 0;
362: addr->ec_xcr = EC_XCLR;
363: return;
364: }
365: es->es_if.if_opackets++;
366: es->es_oactive = 0;
367: es->es_mask = ~0;
368: addr->ec_xcr = EC_XCLR;
369: if (es->es_if.if_snd.ifq_head)
370: ecstart(unit);
371: }
372:
373: /*
374: * Collision on ethernet interface. Do exponential
375: * backoff, and retransmit. If have backed off all
376: * the way print warning diagnostic, and drop packet.
377: */
378: eccollide(unit)
379: int unit;
380: {
381: register struct ec_softc *es = &ec_softc[unit];
382: register struct ecdevice *addr =
383: (struct ecdevice *)ecinfo[unit]->ui_addr;
384: register i;
385: int delay;
386:
387: es->es_if.if_collisions++;
388: if (es->es_oactive == 0)
389: return;
390:
391: /*
392: * Es_mask is a 16 bit number with n low zero bits, with
393: * n the number of backoffs. When es_mask is 0 we have
394: * backed off 16 times, and give up.
395: */
396: if (es->es_mask == 0) {
397: es->es_if.if_oerrors++;
398: log(LOG_ERR, "ec%d: send error\n", unit);
399: /*
400: * Reset interface, then requeue rcv buffers.
401: * Some incoming packets may be lost, but that
402: * can't be helped.
403: */
404: addr->ec_xcr = EC_UECLR;
405: for (i=ECRHBF; i>=ECRLBF; i--)
406: addr->ec_rcr = EC_READ|i;
407: /*
408: * Reset and transmit next packet (if any).
409: */
410: es->es_oactive = 0;
411: es->es_mask = ~0;
412: if (es->es_if.if_snd.ifq_head)
413: ecstart(unit);
414: return;
415: }
416: /*
417: * Do exponential backoff. Compute delay based on low bits
418: * of the interval timer (1 bit for each transmission attempt,
419: * but at most 5 bits). Then delay for that number of
420: * slot times. A slot time is 51.2 microseconds (rounded to 51).
421: * This does not take into account the time already used to
422: * process the interrupt.
423: */
424: es->es_mask <<= 1;
425: delay = mfpr(ICR) & 0x1f &~ es->es_mask;
426: DELAY(delay * 51);
427: /*
428: * Clear the controller's collision flag, thus enabling retransmit.
429: */
430: addr->ec_xcr = EC_CLEAR;
431: }
432:
433: /*
434: * Ethernet interface receiver interrupt.
435: * If input error just drop packet.
436: * Otherwise examine
437: * packet to determine type. If can't determine length
438: * from type, then have to drop packet. Othewise decapsulate
439: * packet based on type and pass to type specific higher-level
440: * input routine.
441: */
442: ecrint(unit)
443: int unit;
444: {
445: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
446:
447: while (addr->ec_rcr & EC_RDONE)
448: ecread(unit);
449: }
450:
451: ecread(unit)
452: int unit;
453: {
454: register struct ec_softc *es = &ec_softc[unit];
455: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
456: register struct ether_header *ec;
457: struct mbuf *m;
458: int len, off, resid, ecoff, rbuf;
459: register struct ifqueue *inq;
460: u_char *ecbuf;
461:
462: es->es_if.if_ipackets++;
463: rbuf = addr->ec_rcr & EC_RBN;
464: if (rbuf < ECRLBF || rbuf > ECRHBF)
465: panic("ecrint");
466: ecbuf = es->es_buf[rbuf];
467: ecoff = *(short *)ecbuf;
468: if (ecoff <= ECRDOFF || ecoff > 2046) {
469: es->es_if.if_ierrors++;
470: #ifdef notdef
471: if (es->es_if.if_ierrors % 100 == 0)
472: printf("ec%d: += 100 input errors\n", unit);
473: #endif
474: goto setup;
475: }
476:
477: /*
478: * Get input data length.
479: * Get pointer to ethernet header (in input buffer).
480: * Deal with trailer protocol: if type is trailer type
481: * get true type from first 16-bit word past data.
482: * Remember that type was trailer by setting off.
483: */
484: len = ecoff - ECRDOFF - sizeof (struct ether_header);
485: ec = (struct ether_header *)(ecbuf + ECRDOFF);
486: ec->ether_type = ntohs((u_short)ec->ether_type);
487: #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off))))
488: if (ec->ether_type >= ETHERTYPE_TRAIL &&
489: ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
490: off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;
491: if (off >= ETHERMTU)
492: goto setup; /* sanity */
493: ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
494: resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
495: if (off + resid > len)
496: goto setup; /* sanity */
497: len = off + resid;
498: } else
499: off = 0;
500: if (len == 0)
501: goto setup;
502:
503: /*
504: * Pull packet off interface. Off is nonzero if packet
505: * has trailing header; ecget will then force this header
506: * information to be at the front, but we still have to drop
507: * the type and length which are at the front of any trailer data.
508: */
509: m = ecget(ecbuf, len, off, &es->es_if);
510: if (m == 0)
511: goto setup;
512: if (off) {
513: struct ifnet *ifp;
514:
515: ifp = *(mtod(m, struct ifnet **));
516: m->m_off += 2 * sizeof (u_short);
517: m->m_len -= 2 * sizeof (u_short);
518: *(mtod(m, struct ifnet **)) = ifp;
519: }
520: switch (ec->ether_type) {
521:
522: #ifdef INET
523: case ETHERTYPE_IP:
524: schednetisr(NETISR_IP);
525: inq = &ipintrq;
526: break;
527:
528: case ETHERTYPE_ARP:
529: arpinput(&es->es_ac, m);
530: goto setup;
531: #endif
532: #ifdef NS
533: case ETHERTYPE_NS:
534: schednetisr(NETISR_NS);
535: inq = &nsintrq;
536: break;
537:
538: #endif
539: #if NENETFILTER > 0
540: default:
541: {
542: register struct mbuf *mtop;
543: register short *sp,*sp2;
544: int i;
545: /*
546: * We need the local net header after all. Oh well,
547: * this could be improved.
548: */
549: MGET(mtop, M_DONTWAIT, MT_DATA);
550: if (mtop == 0) { /* no more mbufs? */
551: m_freem(m); /* wasted effort */
552: goto setup;
553: }
554: ec->ether_type = htons((u_short)ec->ether_type);
555: sp = (short *) ec;
556: sp2 = mtod(mtop, short *);
557: for (i = 0 ; i < (sizeof(struct ether_header)/2) ; i++)
558: *sp2++ = *sp++;
559: mtop->m_len = sizeof(struct ether_header);
560: IF_ADJ(m);
561: mtop->m_next = m;
562: enetFilter(es->es_enetunit, mtop,
563: (len + sizeof(struct ether_header)) );
564: goto setup;
565: }
566: #else
567: default:
568: m_freem(m);
569: goto setup;
570: #endif NENETFILTER > 0
571: }
572:
573: if (IF_QFULL(inq)) {
574: IF_DROP(inq);
575: m_freem(m);
576: goto setup;
577: }
578: IF_ENQUEUE(inq, m);
579:
580: setup:
581: /*
582: * Reset for next packet.
583: */
584: addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
585: }
586:
587: /*
588: * Ethernet output routine.
589: * Encapsulate a packet of type family for the local net.
590: * Use trailer local net encapsulation if enough data in first
591: * packet leaves a multiple of 512 bytes of data in remainder.
592: * If destination is this address or broadcast, send packet to
593: * loop device to kludge around the fact that 3com interfaces can't
594: * talk to themselves.
595: */
596: ecoutput(ifp, m0, dst)
597: struct ifnet *ifp;
598: struct mbuf *m0;
599: struct sockaddr *dst;
600: {
601: int type, s, error;
602: u_char edst[6];
603: struct in_addr idst;
604: register struct ec_softc *es = &ec_softc[ifp->if_unit];
605: register struct mbuf *m = m0;
606: register struct ether_header *ec;
607: register int off;
608: struct mbuf *mcopy = (struct mbuf *)0;
609: #if NENETFILTER > 0
610: struct mbuf *enetcopy = (struct mbuf *)0;
611: #endif NENETFILTER
612: int usetrailers;
613:
614: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
615: error = ENETDOWN;
616: goto bad;
617: }
618: switch (dst->sa_family) {
619:
620: #ifdef INET
621: case AF_INET:
622: idst = ((struct sockaddr_in *)dst)->sin_addr;
623: if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers))
624: return (0); /* if not yet resolved */
625: if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
626: sizeof(edst)))
627: mcopy = m_copy(m, 0, (int)M_COPYALL);
628: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
629: /* need per host negotiation */
630: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
631: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
632: type = ETHERTYPE_TRAIL + (off>>9);
633: m->m_off -= 2 * sizeof (u_short);
634: m->m_len += 2 * sizeof (u_short);
635: *mtod(m, u_short *) = ntohs((u_short)ETHERTYPE_IP);
636: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
637: goto gottrailertype;
638: }
639: type = ETHERTYPE_IP;
640: off = 0;
641: goto gottype;
642: #endif
643: #ifdef NS
644: case AF_NS:
645: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
646: (caddr_t)edst, sizeof (edst));
647:
648: if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,
649: sizeof(edst))) {
650:
651: mcopy = m_copy(m, 0, (int)M_COPYALL);
652: } else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
653: sizeof(edst))) {
654:
655: return(looutput(&loif, m, dst));
656: }
657: type = ETHERTYPE_NS;
658: off = 0;
659: goto gottype;
660: #endif
661: #if NENETFILTER > 0
662: case AF_IMPLINK:
663: ec = mtod(m, struct ether_header *);
664: /* see if we need to fake loopback */
665: if ( /* is packet to us? */
666: (!bcmp((caddr_t)ec->ether_dhost,
667: (caddr_t)es->es_addr,
668: sizeof(ec->ether_dhost)))
669: || /* or is it a broadcast? */
670: (!bcmp((caddr_t)ec->ether_dhost,
671: (caddr_t)etherbroadcastaddr,
672: sizeof(ec->ether_dhost)))
673: ) {
674: enetcopy = m_copy(m, 0, (int)M_COPYALL);
675: }
676: goto gotheader;
677: #endif NENETFILTER
678:
679: case AF_UNSPEC:
680: ec = (struct ether_header *)dst->sa_data;
681: bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst));
682: type = ec->ether_type;
683: goto gottype;
684:
685: default:
686: printf("ec%d: can't handle af%d\n", ifp->if_unit,
687: dst->sa_family);
688: error = EAFNOSUPPORT;
689: goto bad;
690: }
691:
692: gottrailertype:
693: /*
694: * Packet to be sent as trailer: move first packet
695: * (control information) to end of chain.
696: */
697: while (m->m_next)
698: m = m->m_next;
699: m->m_next = m0;
700: m = m0->m_next;
701: m0->m_next = 0;
702: m0 = m;
703:
704: gottype:
705: /*
706: * Add local net header. If no space in first mbuf,
707: * allocate another.
708: */
709: if (m->m_off > MMAXOFF ||
710: MMINOFF + sizeof (struct ether_header) > m->m_off) {
711: m = m_get(M_DONTWAIT, MT_HEADER);
712: if (m == 0) {
713: error = ENOBUFS;
714: goto bad;
715: }
716: m->m_next = m0;
717: m->m_off = MMINOFF;
718: m->m_len = sizeof (struct ether_header);
719: } else {
720: m->m_off -= sizeof (struct ether_header);
721: m->m_len += sizeof (struct ether_header);
722: }
723: ec = mtod(m, struct ether_header *);
724: ec->ether_type = htons((u_short)type);
725: bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst));
726: #if NENETFILTER > 0
727: :
728: #endif NENETFILTER
729: bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost,
730: sizeof(ec->ether_shost));
731:
732: /*
733: * Queue message on interface, and start output if interface
734: * not yet active.
735: */
736: s = splimp();
737: if (IF_QFULL(&ifp->if_snd)) {
738: IF_DROP(&ifp->if_snd);
739: error = ENOBUFS;
740: goto qfull;
741: }
742: IF_ENQUEUE(&ifp->if_snd, m);
743: if (es->es_oactive == 0)
744: ecstart(ifp->if_unit);
745: #if NENETFILTER > 0
746: if (enetcopy) { /* we have a loopback that isn't an IP */
747: register int count = 0;
748: register struct mbuf *mt = enetcopy;
749:
750: /* figure out how long the packet is */
751: do {
752: count += mt->m_len;
753: mt = mt->m_next;
754: } while (mt);
755:
756: /*
757: * should perhaps reject certain packet types here,
758: * but probably less total effort to let enetFilter
759: * reject them.
760: */
761: enetFilter(es->es_enetunit, enetcopy, count);
762: }
763: #endif NENETFILTER
764: splx(s);
765: return (mcopy ? looutput(&loif, mcopy, dst) : 0);
766:
767: qfull:
768: m0 = m;
769: splx(s);
770: bad:
771: m_freem(m0);
772: if (mcopy)
773: m_freem(mcopy);
774: #if NENETFILTER > 0
775: if (enetcopy)
776: m_freem(enetcopy);
777: #endif NENETFILTER
778: return (error);
779: }
780:
781: /*
782: * Routine to copy from mbuf chain to transmit
783: * buffer in UNIBUS memory.
784: * If packet size is less than the minimum legal size,
785: * the buffer is expanded. We probably should zero out the extra
786: * bytes for security, but that would slow things down.
787: */
788: ecput(ecbuf, m)
789: u_char *ecbuf;
790: struct mbuf *m;
791: {
792: register struct mbuf *mp;
793: register int off;
794: u_char *bp;
795:
796: for (off = 2048, mp = m; mp; mp = mp->m_next)
797: off -= mp->m_len;
798: if (2048 - off < ETHERMIN + sizeof (struct ether_header))
799: off = 2048 - ETHERMIN - sizeof (struct ether_header);
800: *(u_short *)ecbuf = off;
801: bp = (u_char *)(ecbuf + off);
802: for (mp = m; mp; mp = mp->m_next) {
803: register unsigned len = mp->m_len;
804: u_char *mcp;
805:
806: if (len == 0)
807: continue;
808: mcp = mtod(mp, u_char *);
809: if ((unsigned)bp & 01) {
810: *bp++ = *mcp++;
811: len--;
812: }
813: if (off = (len >> 1)) {
814: register u_short *to, *from;
815:
816: to = (u_short *)bp;
817: from = (u_short *)mcp;
818: do
819: *to++ = *from++;
820: while (--off > 0);
821: bp = (u_char *)to,
822: mcp = (u_char *)from;
823: }
824: if (len & 01)
825: *bp++ = *mcp++;
826: }
827: m_freem(m);
828: }
829:
830: /*
831: * Routine to copy from UNIBUS memory into mbufs.
832: * Similar in spirit to if_rubaget.
833: *
834: * Warning: This makes the fairly safe assumption that
835: * mbufs have even lengths.
836: */
837: struct mbuf *
838: ecget(ecbuf, totlen, off0, ifp)
839: u_char *ecbuf;
840: int totlen, off0;
841: struct ifnet *ifp;
842: {
843: register struct mbuf *m;
844: struct mbuf *top = 0, **mp = ⊤
845: register int off = off0, len;
846: u_char *cp;
847:
848: cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
849: while (totlen > 0) {
850: register int words;
851: u_char *mcp;
852:
853: MGET(m, M_DONTWAIT, MT_DATA);
854: if (m == 0)
855: goto bad;
856: if (off) {
857: len = totlen - off;
858: cp = ecbuf + ECRDOFF +
859: sizeof (struct ether_header) + off;
860: } else
861: len = totlen;
862: if (ifp)
863: len += sizeof(ifp);
864: if (len >= NBPG) {
865: MCLGET(m);
866: if (m->m_len == CLBYTES)
867: m->m_len = len = MIN(len, CLBYTES);
868: else
869: m->m_len = len = MIN(MLEN, len);
870: } else {
871: m->m_len = len = MIN(MLEN, len);
872: m->m_off = MMINOFF;
873: }
874: mcp = mtod(m, u_char *);
875: if (ifp) {
876: /*
877: * Prepend interface pointer to first mbuf.
878: */
879: *(mtod(m, struct ifnet **)) = ifp;
880: mcp += sizeof(ifp);
881: len -= sizeof(ifp);
882: ifp = (struct ifnet *)0;
883: }
884: if (words = (len >> 1)) {
885: register u_short *to, *from;
886:
887: to = (u_short *)mcp;
888: from = (u_short *)cp;
889: do
890: *to++ = *from++;
891: while (--words > 0);
892: mcp = (u_char *)to;
893: cp = (u_char *)from;
894: }
895: if (len & 01)
896: *mcp++ = *cp++;
897: *mp = m;
898: mp = &m->m_next;
899: if (off == 0) {
900: totlen -= len;
901: continue;
902: }
903: off += len;
904: if (off == totlen) {
905: cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
906: off = 0;
907: totlen = off0;
908: }
909: }
910: return (top);
911: bad:
912: m_freem(top);
913: return (0);
914: }
915:
916: /*
917: * Process an ioctl request.
918: */
919: ecioctl(ifp, cmd, data)
920: register struct ifnet *ifp;
921: int cmd;
922: caddr_t data;
923: {
924: register struct ifaddr *ifa = (struct ifaddr *)data;
925: struct ec_softc *es = &ec_softc[ifp->if_unit];
926: struct ecdevice *addr;
927: int s = splimp(), error = 0;
928:
929: addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr);
930:
931: switch (cmd) {
932:
933: case SIOCSIFADDR:
934: ifp->if_flags |= IFF_UP;
935:
936: switch (ifa->ifa_addr.sa_family) {
937: #ifdef INET
938: case AF_INET:
939: ecinit(ifp->if_unit); /* before arpwhohas */
940: ((struct arpcom *)ifp)->ac_ipaddr =
941: IA_SIN(ifa)->sin_addr;
942: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
943: break;
944: #endif
945: #ifdef NS
946: case AF_NS:
947: {
948: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
949:
950: if (ns_nullhost(*ina))
951: ina->x_host = *(union ns_host *)(es->es_addr);
952: else {
953: /*
954: * The manual says we can't change the address
955: * while the receiver is armed,
956: * so reset everything
957: */
958: ifp->if_flags &= ~IFF_RUNNING;
959: bcopy((caddr_t)ina->x_host.c_host,
960: (caddr_t)es->es_addr, sizeof(es->es_addr));
961: }
962: ecinit(ifp->if_unit); /* does ec_setaddr() */
963: break;
964: }
965: #endif
966: default:
967: ecinit(ifp->if_unit);
968: break;
969: }
970: break;
971:
972: case SIOCSIFFLAGS:
973: if ((ifp->if_flags & IFF_UP) == 0 &&
974: ifp->if_flags & IFF_RUNNING) {
975: addr->ec_xcr = EC_UECLR;
976: ifp->if_flags &= ~IFF_RUNNING;
977: } else if (ifp->if_flags & IFF_UP &&
978: (ifp->if_flags & IFF_RUNNING) == 0)
979: ecinit(ifp->if_unit);
980: break;
981:
982: default:
983: error = EINVAL;
984: }
985: splx(s);
986: return (error);
987: }
988:
989: ec_setaddr(physaddr,unit)
990: u_char *physaddr;
991: int unit;
992: {
993: struct ec_softc *es = &ec_softc[unit];
994: struct uba_device *ui = ecinfo[unit];
995: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
996: register char nibble;
997: register int i, j;
998:
999: /*
1000: * Use the ethernet address supplied
1001: * Note that we do a UECLR here, so the receive buffers
1002: * must be requeued.
1003: */
1004:
1005: #ifdef DEBUG
1006: printf("ec_setaddr: setting address for unit %d = %s",
1007: unit, ether_sprintf(physaddr));
1008: #endif
1009: addr->ec_xcr = EC_UECLR;
1010: addr->ec_rcr = 0;
1011: /* load requested address */
1012: for (i = 0; i < 6; i++) { /* 6 bytes of address */
1013: es->es_addr[i] = physaddr[i];
1014: nibble = physaddr[i] & 0xf; /* lower nibble */
1015: addr->ec_rcr = (nibble << 8);
1016: addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
1017: addr->ec_rcr = (nibble << 8);
1018: for (j=0; j < 4; j++) {
1019: addr->ec_rcr = 0;
1020: addr->ec_rcr = EC_ASTEP; /* step counter */
1021: addr->ec_rcr = 0;
1022: }
1023: nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */
1024: addr->ec_rcr = (nibble << 8);
1025: addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
1026: addr->ec_rcr = (nibble << 8);
1027: for (j=0; j < 4; j++) {
1028: addr->ec_rcr = 0;
1029: addr->ec_rcr = EC_ASTEP; /* step counter */
1030: addr->ec_rcr = 0;
1031: }
1032: }
1033: #ifdef DEBUG
1034: /*
1035: * Read the ethernet address off the board, one nibble at a time.
1036: */
1037: addr->ec_xcr = EC_UECLR;
1038: addr->ec_rcr = 0; /* read RAM */
1039: cp = es->es_addr;
1040: #undef NEXTBIT
1041: #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0
1042: for (i=0; i < sizeof (es->es_addr); i++) {
1043: *cp = 0;
1044: for (j=0; j<=4; j+=4) {
1045: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
1046: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
1047: }
1048: cp++;
1049: }
1050: printf("ec_setaddr: RAM address for unit %d = %s",
1051: unit, ether_sprintf(physaddr));
1052: #endif
1053: }
1054: #endif