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