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