xref: /csrg-svn/sys/vax/if/if_ec.c (revision 7235)
1 /*	if_ec.c	4.19	82/06/20	*/
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 	/*
284 	 * There shouldn't ever be any mbuf's to free, but just in case...
285 	 */
286 	if (es->es_ifuba.ifu_xtofree) {
287 		m_freem(es->es_ifuba.ifu_xtofree);
288 		es->es_ifuba.ifu_xtofree = 0;
289 	}
290 	if (es->es_if.if_snd.ifq_head)
291 		ecstart(unit);
292 }
293 
294 /*
295  * Collision on ethernet interface.  Do exponential
296  * backoff, and retransmit.  If have backed off all
297  * the way print warning diagnostic, and drop packet.
298  */
299 eccollide(unit)
300 	int unit;
301 {
302 	struct ec_softc *es = &ec_softc[unit];
303 
304 	printf("ec%d: collision\n", unit);
305 	es->es_if.if_collisions++;
306 	if (es->es_oactive)
307 		ecdocoll(unit);
308 }
309 
310 ecdocoll(unit)
311 	int unit;
312 {
313 	register struct ec_softc *es = &ec_softc[unit];
314 	register struct ecdevice *addr =
315 	    (struct ecdevice *)ecinfo[unit]->ui_addr;
316 	register i;
317 	int delay;
318 
319 	/*
320 	 * Es_mask is a 16 bit number with n low zero bits, with
321 	 * n the number of backoffs.  When es_mask is 0 we have
322 	 * backed off 16 times, and give up.
323 	 */
324 	if (es->es_mask == 0) {
325 		es->es_if.if_oerrors++;
326 		printf("ec%d: send error\n", unit);
327 		/*
328 		 * Reset interface, then requeue rcv buffers.
329 		 * Some incoming packets may be lost, but that
330 		 * can't be helped.
331 		 */
332 		addr->ec_xcr = EC_UECLR;
333 		for (i=ECRHBF; i>=ECRLBF; i--)
334 			addr->ec_rcr = EC_READ|i;
335 		/*
336 		 * Reset and transmit next packet (if any).
337 		 */
338 		es->es_oactive = 0;
339 		es->es_mask = ~0;
340 		if (es->es_if.if_snd.ifq_head)
341 			ecstart(unit);
342 		return;
343 	}
344 	/*
345 	 * Do exponential backoff.  Compute delay based on low bits
346 	 * of the interval timer.  Then delay for that number of
347 	 * slot times.  A slot time is 51.2 microseconds (rounded to 51).
348 	 * This does not take into account the time already used to
349 	 * process the interrupt.
350 	 */
351 	es->es_mask <<= 1;
352 	delay = mfpr(ICR) &~ es->es_mask;
353 	DELAY(delay * 51);
354 	/*
355 	 * Clear the controller's collision flag, thus enabling retransmit.
356 	 */
357 	addr->ec_xcr = EC_JINTEN|EC_XINTEN|EC_JCLR;
358 }
359 
360 /*
361  * Ethernet interface receiver interrupt.
362  * If input error just drop packet.
363  * Otherwise purge input buffered data path and examine
364  * packet to determine type.  If can't determine length
365  * from type, then have to drop packet.  Othewise decapsulate
366  * packet based on type and pass to type specific higher-level
367  * input routine.
368  */
369 ecrint(unit)
370 	int unit;
371 {
372 	struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
373 
374 	while (addr->ec_rcr & EC_RDONE)
375 		ecread(unit);
376 }
377 
378 ecread(unit)
379 	int unit;
380 {
381 	register struct ec_softc *es = &ec_softc[unit];
382 	struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
383 	register struct ec_header *ec;
384     	struct mbuf *m;
385 	int len, off, resid, ecoff, buf;
386 	register struct ifqueue *inq;
387 	caddr_t ecbuf;
388 
389 	es->es_if.if_ipackets++;
390 	buf = addr->ec_rcr & EC_RBN;
391 	if (buf < ECRLBF || buf > ECRHBF)
392 		panic("ecrint");
393 	ecbuf = es->es_buf[buf];
394 	ecoff = *(short *)ecbuf;
395 	if (ecoff <= ECRDOFF || ecoff > 2046) {
396 		es->es_if.if_ierrors++;
397 #ifdef notdef
398 		if (es->es_if.if_ierrors % 100 == 0)
399 			printf("ec%d: += 100 input errors\n", unit);
400 #endif
401 		printf("ec%d: input error (offset=%d)\n", unit, ecoff);
402 		goto setup;
403 	}
404 
405 	/*
406 	 * Get input data length.
407 	 * Get pointer to ethernet header (in input buffer).
408 	 * Deal with trailer protocol: if type is PUP trailer
409 	 * get true type from first 16-bit word past data.
410 	 * Remember that type was trailer by setting off.
411 	 */
412 	len = ecoff - ECRDOFF - sizeof (struct ec_header);
413 	ec = (struct ec_header *)(ecbuf + ECRDOFF);
414 #define	ecdataaddr(ec, off, type)	((type)(((caddr_t)((ec)+1)+(off))))
415 	if (ec->ec_type >= ECPUP_TRAIL &&
416 	    ec->ec_type < ECPUP_TRAIL+ECPUP_NTRAILER) {
417 		off = (ec->ec_type - ECPUP_TRAIL) * 512;
418 		if (off >= ECMTU)
419 			goto setup;		/* sanity */
420 		ec->ec_type = *ecdataaddr(ec, off, u_short *);
421 		resid = *(ecdataaddr(ec, off+2, u_short *));
422 		if (off + resid > len)
423 			goto setup;		/* sanity */
424 		len = off + resid;
425 	} else
426 		off = 0;
427 	if (len == 0)
428 		goto setup;
429 
430 	/*
431 	 * Pull packet off interface.  Off is nonzero if packet
432 	 * has trailing header; ecget will then force this header
433 	 * information to be at the front, but we still have to drop
434 	 * the type and length which are at the front of any trailer data.
435 	 */
436 	m = ecget(ecbuf, len, off);
437 	if (m == 0)
438 		goto setup;
439 	if (off) {
440 		m->m_off += 2 * sizeof (u_short);
441 		m->m_len -= 2 * sizeof (u_short);
442 	}
443 	switch (ec->ec_type) {
444 
445 #ifdef INET
446 	case ECPUP_IPTYPE:
447 		schednetisr(NETISR_IP);
448 		inq = &ipintrq;
449 		break;
450 #endif
451 	default:
452 		m_freem(m);
453 		goto setup;
454 	}
455 
456 	if (IF_QFULL(inq)) {
457 		IF_DROP(inq);
458 		m_freem(m);
459 		goto setup;
460 	}
461 	IF_ENQUEUE(inq, m);
462 
463 setup:
464 	/*
465 	 * Reset for next packet.
466 	 */
467 	addr->ec_rcr = EC_READ|EC_RCLR|buf;
468 }
469 
470 /*
471  * Ethernet output routine.
472  * Encapsulate a packet of type family for the local net.
473  * Use trailer local net encapsulation if enough data in first
474  * packet leaves a multiple of 512 bytes of data in remainder.
475  * If destination is this address or broadcast, send packet to
476  * loop device to kludge around the fact that 3com interfaces can't
477  * talk to themselves.
478  */
479 ecoutput(ifp, m0, dst)
480 	struct ifnet *ifp;
481 	struct mbuf *m0;
482 	struct sockaddr *dst;
483 {
484 	int type, dest, s, error;
485 	register struct ec_softc *es = &ec_softc[ifp->if_unit];
486 	register struct mbuf *m = m0;
487 	register struct ec_header *ec;
488 	register int off, i;
489 	struct mbuf *mcopy = (struct mbuf *) 0;		/* Null */
490 
491 	switch (dst->sa_family) {
492 
493 #ifdef INET
494 	case AF_INET:
495 		dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
496 		if ((dest &~ 0xff) == 0)
497 			mcopy = m_copy(m, 0, M_COPYALL);
498 		else if (dest == ((struct sockaddr_in *)&es->es_if.if_addr)->
499 		    sin_addr.s_addr) {
500 			mcopy = m;
501 			goto gotlocal;
502 		}
503 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
504 		if (off > 0 && (off & 0x1ff) == 0 &&
505 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
506 			type = ECPUP_TRAIL + (off>>9);
507 			m->m_off -= 2 * sizeof (u_short);
508 			m->m_len += 2 * sizeof (u_short);
509 			*mtod(m, u_short *) = ECPUP_IPTYPE;
510 			*(mtod(m, u_short *) + 1) = m->m_len;
511 			goto gottrailertype;
512 		}
513 		type = ECPUP_IPTYPE;
514 		off = 0;
515 		goto gottype;
516 #endif
517 
518 	default:
519 		printf("ec%d: can't handle af%d\n", ifp->if_unit,
520 			dst->sa_family);
521 		error = EAFNOSUPPORT;
522 		goto bad;
523 	}
524 
525 gottrailertype:
526 	/*
527 	 * Packet to be sent as trailer: move first packet
528 	 * (control information) to end of chain.
529 	 */
530 	while (m->m_next)
531 		m = m->m_next;
532 	m->m_next = m0;
533 	m = m0->m_next;
534 	m0->m_next = 0;
535 	m0 = m;
536 
537 gottype:
538 	/*
539 	 * Add local net header.  If no space in first mbuf,
540 	 * allocate another.
541 	 */
542 	if (m->m_off > MMAXOFF ||
543 	    MMINOFF + sizeof (struct ec_header) > m->m_off) {
544 		m = m_get(M_DONTWAIT);
545 		if (m == 0) {
546 			error = ENOBUFS;
547 			goto bad;
548 		}
549 		m->m_next = m0;
550 		m->m_off = MMINOFF;
551 		m->m_len = sizeof (struct ec_header);
552 	} else {
553 		m->m_off -= sizeof (struct ec_header);
554 		m->m_len += sizeof (struct ec_header);
555 	}
556 	ec = mtod(m, struct ec_header *);
557 	for (i=0; i<6; i++)
558 		ec->ec_shost[i] = es->es_enaddr[i];
559 	if ((dest &~ 0xff) == 0)
560 		/* broadcast address */
561 		for (i=0; i<6; i++)
562 			ec->ec_dhost[i] = 0xff;
563 	else {
564 		if (dest & 0x8000) {
565 			ec->ec_dhost[0] = ec_iltop[0];
566 			ec->ec_dhost[1] = ec_iltop[1];
567 			ec->ec_dhost[2] = ec_iltop[2];
568 		} else {
569 			ec->ec_dhost[0] = es->es_enaddr[0];
570 			ec->ec_dhost[1] = es->es_enaddr[1];
571 			ec->ec_dhost[2] = es->es_enaddr[2];
572 		}
573 		ec->ec_dhost[3] = (dest>>8) & 0x7f;
574 		ec->ec_dhost[4] = (dest>>16) & 0xff;
575 		ec->ec_dhost[5] = (dest>>24) & 0xff;
576 	}
577 	ec->ec_type = type;
578 
579 	/*
580 	 * Queue message on interface, and start output if interface
581 	 * not yet active.
582 	 */
583 	s = splimp();
584 	if (IF_QFULL(&ifp->if_snd)) {
585 		IF_DROP(&ifp->if_snd);
586 		error = ENOBUFS;
587 		goto qfull;
588 	}
589 	IF_ENQUEUE(&ifp->if_snd, m);
590 	if (es->es_oactive == 0)
591 		ecstart(ifp->if_unit);
592 	splx(s);
593 
594 gotlocal:
595 	return(mcopy ? looutput(&loif, mcopy, dst) : 0);
596 
597 qfull:
598 	m0 = m;
599 	splx(s);
600 bad:
601 	m_freem(m0);
602 	return(error);
603 }
604 
605 /*
606  * Routine to copy from mbuf chain to transmitter
607  * buffer in UNIBUS memory.
608  */
609 ecput(ecbuf, m)
610 	u_char *ecbuf;
611 	struct mbuf *m;
612 {
613 	register struct mbuf *mp;
614 	register u_char *bp;
615 	register int off;
616 
617 	for (off = 2048, mp = m; mp; mp = mp->m_next)
618 		off -= mp->m_len;
619 	*(u_short *)ecbuf = off;
620 	bp = (u_char *)(ecbuf + off);
621 	for (mp = m; mp; mp = m_free(mp)) {
622 		register unsigned len;
623 		register u_char *mcp;
624 
625 		len = mp->m_len;
626 		if (len == 0)
627 			continue;
628 		mcp = mtod(mp, u_char *);
629 		if ((unsigned)bp & 01) {
630 			*bp++ = *mcp++;
631 			len--;
632 		}
633 		for (; len > 1; len -= sizeof (u_short)) {
634 			*(u_short *)bp = *(u_short *)mcp;
635 			bp += sizeof (u_short);
636 			mcp += sizeof (u_short);
637 		}
638 		if (len)
639 			*bp++ = *mcp++;
640 	}
641 #ifdef notdef
642 	if (bp - ecbuf != 2048)
643 		printf("ec: bad ecput, diff=%d\n", bp-ecbuf);
644 #endif
645 }
646 
647 /*
648  * Routine to copy from UNIBUS memory into mbufs.
649  * Similar in spirit to if_rubaget.
650  *
651  * Warning: This makes the fairly safe assumption that
652  * mbufs have even lengths.
653  */
654 struct mbuf *
655 ecget(ecbuf, totlen, off0)
656 	char *ecbuf;
657 	int totlen, off0;
658 {
659 	struct mbuf *top, **mp, *m;
660 	int off = off0, len;
661 	register char *cp, *mcp;
662 	register int i;
663 
664 	top = 0;
665 	mp = &top;
666 	cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
667 	while (totlen > 0) {
668 		MGET(m, 0);
669 		if (m == 0)
670 			goto bad;
671 		if (off) {
672 			len = totlen - off;
673 			cp = ecbuf + ECRDOFF + sizeof (struct ec_header) + off;
674 		} else
675 			len = totlen;
676 		if (len >= CLBYTES) {
677 			struct mbuf *p;
678 
679 			MCLGET(p, 1);
680 			if (p != 0) {
681 				m->m_len = len = CLBYTES;
682 				m->m_off = (int)p - (int)m;
683 			} else {
684 				m->m_len = len = MIN(MLEN, len);
685 				m->m_off = MMINOFF;
686 			}
687 		} else {
688 			m->m_len = len = MIN(MLEN, len);
689 			m->m_off = MMINOFF;
690 		}
691 		mcp = mtod(m, char *);
692 		for (i = 0; i < len; i += sizeof (short)) {
693 			*(short *)mcp = *(short *)cp;
694 			mcp += sizeof (short);
695 			cp += sizeof (short);
696 		}
697 		if (len & 01)
698 			*mcp++ = *cp++;
699 		*mp = m;
700 		mp = &m->m_next;
701 		if (off) {
702 			off += len;
703 			if (off == totlen) {
704 				cp = ecbuf + ECRDOFF +
705 				    sizeof (struct ec_header);
706 				off = 0;
707 				totlen = off0;
708 			}
709 		} else
710 			totlen -= len;
711 	}
712 	return (top);
713 bad:
714 	m_freem(top);
715 	return (0);
716 }
717