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