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