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