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