|
|
1.1 root 1: /* if_ec.c 6.1 83/07/29 */
2:
3: #include "ec.h"
4:
5: /*
6: * 3Com Ethernet Controller interface
7: */
8: #include "../machine/pte.h"
9:
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/mbuf.h"
13: #include "../h/buf.h"
14: #include "../h/protosw.h"
15: #include "../h/socket.h"
16: #include "../h/vmmac.h"
17: #include "../h/ioctl.h"
18: #include "../h/errno.h"
19:
20: #include "../net/if.h"
21: #include "../net/netisr.h"
22: #include "../net/route.h"
23: #include "../netinet/in.h"
24: #include "../netinet/in_systm.h"
25: #include "../netinet/ip.h"
26: #include "../netinet/ip_var.h"
27: #include "../netinet/if_ether.h"
28: #include "../netpup/pup.h"
29:
30: #include "../vax/cpu.h"
31: #include "../vax/mtpr.h"
32: #include "../vaxif/if_ecreg.h"
33: #include "../vaxif/if_uba.h"
34: #include "../vaxuba/ubareg.h"
35: #include "../vaxuba/ubavar.h"
36:
37: #define ECMEM 0000000
38:
39: int ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
40: struct uba_device *ecinfo[NEC];
41: u_short ecstd[] = { 0 };
42: struct uba_driver ecdriver =
43: { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo };
44: #define ECUNIT(x) minor(x)
45:
46: int ecinit(),ecioctl(),ecoutput(),ecreset();
47: struct mbuf *ecget();
48:
49: extern struct ifnet loif;
50:
51: /*
52: * Ethernet software status per interface.
53: *
54: * Each interface is referenced by a network interface structure,
55: * es_if, which the routing code uses to locate the interface.
56: * This structure contains the output queue for the interface, its address, ...
57: * We also have, for each interface, a UBA interface structure, which
58: * contains information about the UNIBUS resources held by the interface:
59: * map registers, buffered data paths, etc. Information is cached in this
60: * structure for use by the if_uba.c routines in running the interface
61: * efficiently.
62: */
63: struct ec_softc {
64: struct arpcom es_ac; /* common Ethernet structures */
65: #define es_if es_ac.ac_if /* network-visible interface */
66: #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */
67: struct ifuba es_ifuba; /* UNIBUS resources */
68: short es_mask; /* mask for current output delay */
69: short es_oactive; /* is output active? */
70: u_char *es_buf[16]; /* virtual addresses of buffers */
71: } ec_softc[NEC];
72:
73: /*
74: * Do output DMA to determine interface presence and
75: * interrupt vector. DMA is too short to disturb other hosts.
76: */
77: ecprobe(reg)
78: caddr_t reg;
79: {
80: register int br, cvec; /* r11, r10 value-result */
81: register struct ecdevice *addr = (struct ecdevice *)reg;
82: register caddr_t ecbuf = (caddr_t) &umem[numuba][ECMEM];
83:
84: #ifdef lint
85: br = 0; cvec = br; br = cvec;
86: ecrint(0); ecxint(0); eccollide(0);
87: #endif
88: /*
89: * Make sure memory is turned on
90: */
91: addr->ec_rcr = EC_AROM;
92: /*
93: * Disable map registers for ec unibus space,
94: * but don't allocate yet.
95: */
96: (void) ubamem(numuba, ECMEM, 32*2, 0);
97: /*
98: * Check for existence of buffers on Unibus.
99: */
100: if (badaddr((caddr_t)ecbuf, 2)) {
101: bad1:
102: printf("ec: buffer mem not found\n");
103: bad2:
104: (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */
105: addr->ec_rcr = EC_MDISAB; /* disable memory */
106: return (0);
107: }
108: #if VAX780
109: if (cpu == VAX_780 && uba_hd[numuba].uh_uba->uba_sr) {
110: uba_hd[numuba].uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr;
111: goto bad1;
112: }
113: #endif
114:
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(numuba, ECMEM, 32*2, 1) == 0) {
120: printf("ecprobe: cannot reserve uba addresses\n");
121: goto bad2;
122: }
123:
124: /*
125: * Make a one byte packet in what should be buffer #0.
126: * Submit it for sending. This whould cause an xmit interrupt.
127: * The xmit interrupt vector is 8 bytes after the receive vector,
128: * so adjust for this before returning.
129: */
130: *(u_short *)ecbuf = (u_short) 03777;
131: ecbuf[03777] = '\0';
132: addr->ec_xcr = EC_XINTEN|EC_XWBN;
133: DELAY(100000);
134: addr->ec_xcr = EC_XCLR;
135: if (cvec > 0 && cvec != 0x200) {
136: if (cvec & 04) { /* collision interrupt */
137: cvec -= 04;
138: br += 1; /* rcv is collision + 1 */
139: } else { /* xmit interrupt */
140: cvec -= 010;
141: br += 2; /* rcv is xmit + 2 */
142: }
143: }
144: return (1);
145: }
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: ecattach(ui)
153: struct uba_device *ui;
154: {
155: struct ec_softc *es = &ec_softc[ui->ui_unit];
156: register struct ifnet *ifp = &es->es_if;
157: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
158: struct sockaddr_in *sin;
159: int i, j;
160: u_char *cp;
161:
162: ifp->if_unit = ui->ui_unit;
163: ifp->if_name = "ec";
164: ifp->if_mtu = ETHERMTU;
165:
166: /*
167: * Read the ethernet address off the board, one nibble at a time.
168: */
169: addr->ec_xcr = EC_UECLR;
170: addr->ec_rcr = EC_AROM;
171: cp = es->es_addr;
172: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
173: for (i=0; i<6; i++) {
174: *cp = 0;
175: for (j=0; j<=4; j+=4) {
176: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
177: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
178: }
179: cp++;
180: }
181: sin = (struct sockaddr_in *)&es->es_if.if_addr;
182: sin->sin_family = AF_INET;
183: sin->sin_addr = arpmyaddr((struct arpcom *)0);
184: ifp->if_init = ecinit;
185: ifp->if_ioctl = ecioctl;
186: ifp->if_output = ecoutput;
187: ifp->if_reset = ecreset;
188: for (i=0; i<16; i++)
189: es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ECMEM+2048*i];
190: if_attach(ifp);
191: }
192:
193: /*
194: * Reset of interface after UNIBUS reset.
195: * If interface is on specified uba, reset its state.
196: */
197: ecreset(unit, uban)
198: int unit, uban;
199: {
200: register struct uba_device *ui;
201:
202: if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
203: ui->ui_ubanum != uban)
204: return;
205: printf(" ec%d", unit);
206: (void) ubamem(uban, ECMEM, 32*2, 0); /* mr disable (no alloc) */
207: ecinit(unit);
208: }
209:
210: /*
211: * Initialization of interface; clear recorded pending
212: * operations, and reinitialize UNIBUS usage.
213: */
214: ecinit(unit)
215: int unit;
216: {
217: struct ec_softc *es = &ec_softc[unit];
218: struct ecdevice *addr;
219: register struct ifnet *ifp = &es->es_if;
220: register struct sockaddr_in *sin;
221: int i, s;
222:
223: sin = (struct sockaddr_in *)&ifp->if_addr;
224: if (sin->sin_addr.s_addr == 0) /* address still unknown */
225: return;
226:
227: /*
228: * Hang receive buffers and start any pending writes.
229: * Writing into the rcr also makes sure the memory
230: * is turned on.
231: */
232: if ((es->es_if.if_flags & IFF_RUNNING) == 0) {
233: addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
234: s = splimp();
235: for (i = ECRHBF; i >= ECRLBF; i--)
236: addr->ec_rcr = EC_READ | i;
237: es->es_oactive = 0;
238: es->es_mask = ~0;
239: es->es_if.if_flags |= IFF_UP|IFF_RUNNING;
240: if (es->es_if.if_snd.ifq_head)
241: ecstart(unit);
242: splx(s);
243: }
244: if_rtinit(&es->es_if, RTF_UP);
245: arpattach(&es->es_ac);
246: arpwhohas(&es->es_ac, &sin->sin_addr);
247: }
248:
249: /*
250: * Start or restart output on interface.
251: * If interface is already active, then this is a retransmit
252: * after a collision, and just restuff registers.
253: * If interface is not already active, get another datagram
254: * to send off of the interface queue, and map it to the interface
255: * before starting the output.
256: */
257: ecstart(dev)
258: dev_t dev;
259: {
260: int unit = ECUNIT(dev);
261: struct ec_softc *es = &ec_softc[unit];
262: struct ecdevice *addr;
263: struct mbuf *m;
264:
265: if (es->es_oactive)
266: goto restart;
267:
268: IF_DEQUEUE(&es->es_if.if_snd, m);
269: if (m == 0) {
270: es->es_oactive = 0;
271: return;
272: }
273: ecput(es->es_buf[ECTBF], m);
274:
275: restart:
276: addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
277: addr->ec_xcr = EC_WRITE|ECTBF;
278: es->es_oactive = 1;
279: }
280:
281: /*
282: * Ethernet interface transmitter interrupt.
283: * Start another output if more data to send.
284: */
285: ecxint(unit)
286: int unit;
287: {
288: register struct ec_softc *es = &ec_softc[unit];
289: register struct ecdevice *addr =
290: (struct ecdevice *)ecinfo[unit]->ui_addr;
291:
292: if (es->es_oactive == 0)
293: return;
294: if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
295: printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
296: addr->ec_xcr, EC_XBITS);
297: es->es_oactive = 0;
298: addr->ec_xcr = EC_XCLR;
299: return;
300: }
301: es->es_if.if_opackets++;
302: es->es_oactive = 0;
303: es->es_mask = ~0;
304: addr->ec_xcr = EC_XCLR;
305: if (es->es_if.if_snd.ifq_head)
306: ecstart(unit);
307: }
308:
309: /*
310: * Collision on ethernet interface. Do exponential
311: * backoff, and retransmit. If have backed off all
312: * the way print warning diagnostic, and drop packet.
313: */
314: eccollide(unit)
315: int unit;
316: {
317: struct ec_softc *es = &ec_softc[unit];
318:
319: es->es_if.if_collisions++;
320: if (es->es_oactive)
321: ecdocoll(unit);
322: }
323:
324: ecdocoll(unit)
325: int unit;
326: {
327: register struct ec_softc *es = &ec_softc[unit];
328: register struct ecdevice *addr =
329: (struct ecdevice *)ecinfo[unit]->ui_addr;
330: register i;
331: int delay;
332:
333: /*
334: * Es_mask is a 16 bit number with n low zero bits, with
335: * n the number of backoffs. When es_mask is 0 we have
336: * backed off 16 times, and give up.
337: */
338: if (es->es_mask == 0) {
339: es->es_if.if_oerrors++;
340: printf("ec%d: send error\n", unit);
341: /*
342: * Reset interface, then requeue rcv buffers.
343: * Some incoming packets may be lost, but that
344: * can't be helped.
345: */
346: addr->ec_xcr = EC_UECLR;
347: for (i=ECRHBF; i>=ECRLBF; i--)
348: addr->ec_rcr = EC_READ|i;
349: /*
350: * Reset and transmit next packet (if any).
351: */
352: es->es_oactive = 0;
353: es->es_mask = ~0;
354: if (es->es_if.if_snd.ifq_head)
355: ecstart(unit);
356: return;
357: }
358: /*
359: * Do exponential backoff. Compute delay based on low bits
360: * of the interval timer. Then delay for that number of
361: * slot times. A slot time is 51.2 microseconds (rounded to 51).
362: * This does not take into account the time already used to
363: * process the interrupt.
364: */
365: es->es_mask <<= 1;
366: delay = mfpr(ICR) &~ es->es_mask;
367: DELAY(delay * 51);
368: /*
369: * Clear the controller's collision flag, thus enabling retransmit.
370: */
371: addr->ec_xcr = EC_CLEAR;
372: }
373:
374: /*
375: * Ethernet interface receiver interrupt.
376: * If input error just drop packet.
377: * Otherwise purge input buffered data path and examine
378: * packet to determine type. If can't determine length
379: * from type, then have to drop packet. Othewise decapsulate
380: * packet based on type and pass to type specific higher-level
381: * input routine.
382: */
383: ecrint(unit)
384: int unit;
385: {
386: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
387:
388: while (addr->ec_rcr & EC_RDONE)
389: ecread(unit);
390: }
391:
392: ecread(unit)
393: int unit;
394: {
395: register struct ec_softc *es = &ec_softc[unit];
396: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
397: register struct ether_header *ec;
398: struct mbuf *m;
399: int len, off, resid, ecoff, rbuf;
400: register struct ifqueue *inq;
401: u_char *ecbuf;
402:
403: es->es_if.if_ipackets++;
404: rbuf = addr->ec_rcr & EC_RBN;
405: if (rbuf < ECRLBF || rbuf > ECRHBF)
406: panic("ecrint");
407: ecbuf = es->es_buf[rbuf];
408: ecoff = *(short *)ecbuf;
409: if (ecoff <= ECRDOFF || ecoff > 2046) {
410: es->es_if.if_ierrors++;
411: #ifdef notdef
412: if (es->es_if.if_ierrors % 100 == 0)
413: printf("ec%d: += 100 input errors\n", unit);
414: #endif
415: goto setup;
416: }
417:
418: /*
419: * Get input data length.
420: * Get pointer to ethernet header (in input buffer).
421: * Deal with trailer protocol: if type is PUP trailer
422: * get true type from first 16-bit word past data.
423: * Remember that type was trailer by setting off.
424: */
425: len = ecoff - ECRDOFF - sizeof (struct ether_header);
426: ec = (struct ether_header *)(ecbuf + ECRDOFF);
427: ec->ether_type = ntohs((u_short)ec->ether_type);
428: #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off))))
429: if (ec->ether_type >= ETHERPUP_TRAIL &&
430: ec->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
431: off = (ec->ether_type - ETHERPUP_TRAIL) * 512;
432: if (off >= ETHERMTU)
433: goto setup; /* sanity */
434: ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
435: resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
436: if (off + resid > len)
437: goto setup; /* sanity */
438: len = off + resid;
439: } else
440: off = 0;
441: if (len == 0)
442: goto setup;
443:
444: /*
445: * Pull packet off interface. Off is nonzero if packet
446: * has trailing header; ecget will then force this header
447: * information to be at the front, but we still have to drop
448: * the type and length which are at the front of any trailer data.
449: */
450: m = ecget(ecbuf, len, off);
451: if (m == 0)
452: goto setup;
453: if (off) {
454: m->m_off += 2 * sizeof (u_short);
455: m->m_len -= 2 * sizeof (u_short);
456: }
457: switch (ec->ether_type) {
458:
459: #ifdef INET
460: case ETHERPUP_IPTYPE:
461: schednetisr(NETISR_IP);
462: inq = &ipintrq;
463: break;
464:
465: case ETHERPUP_ARPTYPE:
466: arpinput(&es->es_ac, m);
467: goto setup;
468: #endif
469: default:
470: m_freem(m);
471: goto setup;
472: }
473:
474: if (IF_QFULL(inq)) {
475: IF_DROP(inq);
476: m_freem(m);
477: goto setup;
478: }
479: IF_ENQUEUE(inq, m);
480:
481: setup:
482: /*
483: * Reset for next packet.
484: */
485: addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
486: }
487:
488: /*
489: * Ethernet output routine.
490: * Encapsulate a packet of type family for the local net.
491: * Use trailer local net encapsulation if enough data in first
492: * packet leaves a multiple of 512 bytes of data in remainder.
493: * If destination is this address or broadcast, send packet to
494: * loop device to kludge around the fact that 3com interfaces can't
495: * talk to themselves.
496: */
497: ecoutput(ifp, m0, dst)
498: struct ifnet *ifp;
499: struct mbuf *m0;
500: struct sockaddr *dst;
501: {
502: int type, s, error;
503: u_char edst[6];
504: struct in_addr idst;
505: register struct ec_softc *es = &ec_softc[ifp->if_unit];
506: register struct mbuf *m = m0;
507: register struct ether_header *ec;
508: register int off;
509: struct mbuf *mcopy = (struct mbuf *)0;
510:
511: switch (dst->sa_family) {
512:
513: #ifdef INET
514: case AF_INET:
515: idst = ((struct sockaddr_in *)dst)->sin_addr;
516: if (!arpresolve(&es->es_ac, m, &idst, edst))
517: return (0); /* if not yet resolved */
518: if (in_lnaof(idst) == INADDR_ANY)
519: mcopy = m_copy(m, 0, (int)M_COPYALL);
520: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
521: /* need per host negotiation */
522: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
523: if (off > 0 && (off & 0x1ff) == 0 &&
524: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
525: type = ETHERPUP_TRAIL + (off>>9);
526: m->m_off -= 2 * sizeof (u_short);
527: m->m_len += 2 * sizeof (u_short);
528: *mtod(m, u_short *) = ntohs((u_short)ETHERPUP_IPTYPE);
529: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
530: goto gottrailertype;
531: }
532: type = ETHERPUP_IPTYPE;
533: off = 0;
534: goto gottype;
535: #endif
536:
537: case AF_UNSPEC:
538: ec = (struct ether_header *)dst->sa_data;
539: bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst));
540: type = ec->ether_type;
541: goto gottype;
542:
543: default:
544: printf("ec%d: can't handle af%d\n", ifp->if_unit,
545: dst->sa_family);
546: error = EAFNOSUPPORT;
547: goto bad;
548: }
549:
550: gottrailertype:
551: /*
552: * Packet to be sent as trailer: move first packet
553: * (control information) to end of chain.
554: */
555: while (m->m_next)
556: m = m->m_next;
557: m->m_next = m0;
558: m = m0->m_next;
559: m0->m_next = 0;
560: m0 = m;
561:
562: gottype:
563: /*
564: * Add local net header. If no space in first mbuf,
565: * allocate another.
566: */
567: if (m->m_off > MMAXOFF ||
568: MMINOFF + sizeof (struct ether_header) > m->m_off) {
569: m = m_get(M_DONTWAIT, MT_HEADER);
570: if (m == 0) {
571: error = ENOBUFS;
572: goto bad;
573: }
574: m->m_next = m0;
575: m->m_off = MMINOFF;
576: m->m_len = sizeof (struct ether_header);
577: } else {
578: m->m_off -= sizeof (struct ether_header);
579: m->m_len += sizeof (struct ether_header);
580: }
581: ec = mtod(m, struct ether_header *);
582: bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst));
583: ec->ether_type = htons((u_short)type);
584: bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost, 6);
585:
586: /*
587: * Queue message on interface, and start output if interface
588: * not yet active.
589: */
590: s = splimp();
591: if (IF_QFULL(&ifp->if_snd)) {
592: IF_DROP(&ifp->if_snd);
593: error = ENOBUFS;
594: goto qfull;
595: }
596: IF_ENQUEUE(&ifp->if_snd, m);
597: if (es->es_oactive == 0)
598: ecstart(ifp->if_unit);
599: splx(s);
600: return (mcopy ? looutput(&loif, mcopy, dst) : 0);
601:
602: qfull:
603: m0 = m;
604: splx(s);
605: bad:
606: m_freem(m0);
607: return (error);
608: }
609:
610: /*
611: * Routine to copy from mbuf chain to transmit
612: * buffer in UNIBUS memory.
613: * If packet size is less than the minimum legal size,
614: * the buffer is expanded. We probably should zero out the extra
615: * bytes for security, but that would slow things down.
616: */
617: ecput(ecbuf, m)
618: u_char *ecbuf;
619: struct mbuf *m;
620: {
621: register struct mbuf *mp;
622: register int off;
623: u_char *bp;
624:
625: for (off = 2048, mp = m; mp; mp = mp->m_next)
626: off -= mp->m_len;
627: if (2048 - off < ETHERMIN + sizeof (struct ether_header))
628: off = 2048 - ETHERMIN - sizeof (struct ether_header);
629: *(u_short *)ecbuf = off;
630: bp = (u_char *)(ecbuf + off);
631: for (mp = m; mp; mp = mp->m_next) {
632: register unsigned len = mp->m_len;
633: u_char *mcp;
634:
635: if (len == 0)
636: continue;
637: mcp = mtod(mp, u_char *);
638: if ((unsigned)bp & 01) {
639: *bp++ = *mcp++;
640: len--;
641: }
642: if (off = (len >> 1)) {
643: register u_short *to, *from;
644:
645: to = (u_short *)bp;
646: from = (u_short *)mcp;
647: do
648: *to++ = *from++;
649: while (--off > 0);
650: bp = (u_char *)to,
651: mcp = (u_char *)from;
652: }
653: if (len & 01)
654: *bp++ = *mcp++;
655: }
656: m_freem(m);
657: }
658:
659: /*
660: * Routine to copy from UNIBUS memory into mbufs.
661: * Similar in spirit to if_rubaget.
662: *
663: * Warning: This makes the fairly safe assumption that
664: * mbufs have even lengths.
665: */
666: struct mbuf *
667: ecget(ecbuf, totlen, off0)
668: u_char *ecbuf;
669: int totlen, off0;
670: {
671: register struct mbuf *m;
672: struct mbuf *top = 0, **mp = ⊤
673: register int off = off0, len;
674: u_char *cp;
675:
676: cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
677: while (totlen > 0) {
678: register int words;
679: u_char *mcp;
680:
681: MGET(m, M_DONTWAIT, MT_DATA);
682: if (m == 0)
683: goto bad;
684: if (off) {
685: len = totlen - off;
686: cp = ecbuf + ECRDOFF +
687: sizeof (struct ether_header) + off;
688: } else
689: len = totlen;
690: if (len >= CLBYTES) {
691: struct mbuf *p;
692:
693: MCLGET(p, 1);
694: if (p != 0) {
695: m->m_len = len = CLBYTES;
696: m->m_off = (int)p - (int)m;
697: } else {
698: m->m_len = len = MIN(MLEN, len);
699: m->m_off = MMINOFF;
700: }
701: } else {
702: m->m_len = len = MIN(MLEN, len);
703: m->m_off = MMINOFF;
704: }
705: mcp = mtod(m, u_char *);
706: if (words = (len >> 1)) {
707: register u_short *to, *from;
708:
709: to = (u_short *)mcp;
710: from = (u_short *)cp;
711: do
712: *to++ = *from++;
713: while (--words > 0);
714: mcp = (u_char *)to;
715: cp = (u_char *)from;
716: }
717: if (len & 01)
718: *mcp++ = *cp++;
719: *mp = m;
720: mp = &m->m_next;
721: if (off == 0) {
722: totlen -= len;
723: continue;
724: }
725: off += len;
726: if (off == totlen) {
727: cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
728: off = 0;
729: totlen = off0;
730: }
731: }
732: return (top);
733: bad:
734: m_freem(top);
735: return (0);
736: }
737:
738: /*
739: * Process an ioctl request.
740: */
741: ecioctl(ifp, cmd, data)
742: register struct ifnet *ifp;
743: int cmd;
744: caddr_t data;
745: {
746: register struct ifreq *ifr = (struct ifreq *)data;
747: int s = splimp(), error = 0;
748:
749: switch (cmd) {
750:
751: case SIOCSIFADDR:
752: if (ifp->if_flags & IFF_RUNNING)
753: if_rtinit(ifp, -1); /* delete previous route */
754: ecsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
755: ecinit(ifp->if_unit);
756: break;
757:
758: default:
759: error = EINVAL;
760: }
761: splx(s);
762: return (error);
763: }
764:
765: ecsetaddr(ifp, sin)
766: register struct ifnet *ifp;
767: register struct sockaddr_in *sin;
768: {
769:
770: ifp->if_addr = *(struct sockaddr *)sin;
771: ifp->if_net = in_netof(sin->sin_addr);
772: ifp->if_host[0] = in_lnaof(sin->sin_addr);
773: sin = (struct sockaddr_in *)&ifp->if_broadaddr;
774: sin->sin_family = AF_INET;
775: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
776: ifp->if_flags |= IFF_BROADCAST;
777: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.