xref: /csrg-svn/sys/tahoe/if/if_ace.c (revision 29563)
1 /*	if_ace.c	1.10	86/07/16	*/
2 
3 /*
4  * ACC VERSAbus Ethernet controller
5  */
6 #include "ace.h"
7 #if NACE > 0
8 
9 #include "../machine/pte.h"
10 
11 #include "param.h"
12 #include "systm.h"
13 #include "mbuf.h"
14 #include "buf.h"
15 #include "protosw.h"
16 #include "socket.h"
17 #include "vmmac.h"
18 #include "ioctl.h"
19 #include "errno.h"
20 #include "vmparam.h"
21 #include "syslog.h"
22 
23 #include "../net/if.h"
24 #include "../net/netisr.h"
25 #include "../net/route.h"
26 #ifdef INET
27 #include "../netinet/in.h"
28 #include "../netinet/in_systm.h"
29 #include "../netinet/in_var.h"
30 #include "../netinet/ip.h"
31 #include "../netinet/ip_var.h"
32 #include "../netinet/if_ether.h"
33 #endif
34 #ifdef NS
35 #include "../netns/ns.h"
36 #include "../netns/ns_if.h"
37 #endif
38 
39 #include "../tahoe/mtpr.h"
40 #include "../tahoeif/if_acereg.h"
41 #include "../tahoevba/vbavar.h"
42 
43 int	aceprobe(), aceattach(), acerint(), acecint();
44 struct	vba_device *aceinfo[NACE];
45 long	acestd[] = { 0 };
46 struct	vba_driver acedriver =
47     { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
48 
49 int	aceinit(), aceoutput(), aceioctl(), acereset();
50 struct	mbuf *aceget();
51 
52 /*
53  * Ethernet software status per interface.
54  *
55  * Each interface is referenced by a network interface structure,
56  * is_if, which the routing code uses to locate the interface.
57  * This structure contains the output queue for the interface, its address, ...
58  */
59 struct	ace_softc {
60 	struct	arpcom is_ac;		/* Ethernet common part	*/
61 #define	is_if	is_ac.ac_if		/* network-visible interface */
62 #define	is_addr	is_ac.ac_enaddr		/* hardware Ethernet address */
63 	short	is_flags;
64 #define	ACEF_OACTIVE	0x1		/* output is active */
65 #define	ACEF_RCVPENDING	0x2		/* start rcv in acecint	*/
66 	short	is_promiscuous;		/* true is enabled */
67 	short	is_segboundry;		/* first TX Seg in dpm */
68 	short	is_eictr;		/* Rx segment tracking ctr */
69 	short	is_eoctr;		/* Tx segment tracking ctr */
70 	short	is_txnext;		/* Next available Tx segment */
71 	short	is_currnd;		/* current random backoff */
72 	struct	ace_stats is_stats;	/* holds board statistics */
73 	short	is_xcnt;		/* count xmitted segments to be acked
74 					   by the controller */
75 	long	is_ivec;		/* autoconfig interrupt vector base */
76 	struct	pte *is_map;		/* pte map for dual ported memory */
77 	caddr_t	is_dpm;			/* address of mapped memory */
78 } ace_softc[NACE];
79 extern	struct ifnet loif;
80 
81 aceprobe(reg, vi)
82 	caddr_t reg;
83 	struct vba_device *vi;
84 {
85 	register br, cvec;		/* must be r12, r11 */
86 	struct acedevice *ap = (struct acedevice *)reg;
87 	struct ace_softc *is = &ace_softc[vi->ui_unit];
88 
89 #ifdef lint
90 	acerint(0); acecint(0);
91 #endif
92 	if (badaddr(reg, 2))
93 		return (0);
94 	movow(&ap->csr, CSR_RESET);
95 	DELAY(10000);
96 #ifdef notdef
97 	/*
98 	 * Select two spaces for the interrupts aligned to an
99 	 * eight vector boundary and fitting in 8 bits (as
100 	 * required by the controller) -- YECH.  The controller
101 	 * will be notified later at initialization time.
102 	 */
103 	if ((vi->ui_hd->vh_lastiv -= 2) > 0xff)
104 		vi->ui_hd->vh_lastiv  = 0x200;
105 	is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;
106 #else
107 	is->is_ivec = 0x90+vi->ui_unit*8;
108 #endif
109 	br = 0x14, cvec = is->is_ivec;		/* XXX */
110 	return (sizeof (*ap));
111 }
112 
113 /*
114  * Interface exists: make available by filling in network interface
115  * record.  System will initialize the interface when it is ready
116  * to accept packets.
117  */
118 aceattach(ui)
119 	struct vba_device *ui;
120 {
121 	register short unit = ui->ui_unit;
122 	register struct ace_softc *is = &ace_softc[unit];
123 	register struct ifnet *ifp = &is->is_if;
124 	register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
125 	register short *wp, i;
126 	char *cp;
127 
128 	ifp->if_unit = unit;
129 	ifp->if_name = "ace";
130 	ifp->if_mtu = ETHERMTU;
131 	/*
132 	 * Get station's addresses and set multicast hash table.
133 	 */
134 	for (wp = (short *)addr->station, i = 0; i < 6; i++)
135 		is->is_addr[i] = ~*wp++;
136 	printf("ace%d: hardware address %s\n", unit,
137 	    ether_sprintf(is->is_addr));
138 	is->is_promiscuous = 0;
139 	for (wp = (short *)addr->hash, i =  0; i < 8; i++)
140 		movow(wp++, ~0xf);
141 	movow(&addr->bcastena[0], ~0xffff);
142 	movow(&addr->bcastena[1], ~0xffff);
143 	/*
144 	 * Allocate and map dual ported VERSAbus memory.
145 	 */
146 	vbmemalloc(32, (caddr_t)ui->ui_flags, &is->is_map, &is->is_dpm);
147 
148 	ifp->if_init = aceinit;
149 	ifp->if_output = aceoutput;
150 	ifp->if_ioctl = aceioctl;
151 	ifp->if_reset = acereset;
152 	ifp->if_flags = IFF_BROADCAST;
153 	if_attach(ifp);
154 }
155 
156 /*
157  * Reset of interface after "system" reset.
158  */
159 acereset(unit, vban)
160 	int unit, vban;
161 {
162 	register struct vba_device *ui;
163 
164 	if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
165 	    ui->ui_vbanum != vban)
166 		return;
167 	printf(" ace%d", unit);
168 	aceinit(unit);
169 }
170 
171 /*
172  * Initialization of interface; clear recorded pending operations
173  */
174 aceinit(unit)
175 	int unit;
176 {
177 	register struct ace_softc *is = &ace_softc[unit];
178 	register struct vba_device *ui = aceinfo[unit];
179 	register struct acedevice *addr;
180 	register struct ifnet *ifp = &is->is_if;
181 	register short Csr;
182 	register int s;
183 
184 	if (ifp->if_addrlist == (struct ifaddr *)0)
185 		return;
186 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
187 		/*
188 		 * Reset the controller, initialize the recieve buffers,
189 		 * and turn the controller on again and set board online.
190 		 */
191 		addr = (struct acedevice *)ui->ui_addr;
192 		s = splimp();
193 		movow(&addr->csr, CSR_RESET);
194 		DELAY(10000);
195 
196 		/*
197 		 * Clean up dpm since the controller might
198 		 * jumble dpm after reset.
199 		 */
200 		acesetup(unit);
201 		movow(&addr->csr, CSR_GO);
202 		Csr = addr->csr;
203 		if (Csr & CSR_ACTIVE) {
204 			movow(&addr->ivct, is->is_ivec);
205 			Csr |= CSR_IENA | is->is_promiscuous;
206 			movow(&addr->csr, Csr);
207 			is->is_flags = 0;
208 			is->is_xcnt = 0;
209 			is->is_if.if_flags |= IFF_RUNNING;
210 		}
211 		splx(s);
212 	}
213 	if (is->is_if.if_snd.ifq_head)
214 		acestart(unit);
215 }
216 
217 /*
218  * Start output on interface.
219  * Get another datagram to send off of the interface queue,
220  * and map it to the interface before starting the output.
221  */
222 acestart(unit)
223 	int unit;
224 {
225 	register struct tx_segment *txs;
226 	register long len;
227 	register int s;
228 	register struct ace_softc *is = &ace_softc[unit];
229 	struct mbuf *m;
230 	short retries;
231 
232 	if (is->is_flags & ACEF_OACTIVE)
233 		return;
234 	is->is_flags |= ACEF_OACTIVE;
235 again:
236 	txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
237 	if (txs->tx_csr & TCS_TBFULL) {
238 		is->is_stats.tx_busy++;
239 		is->is_flags &= ~ACEF_OACTIVE;
240 		return;
241 	}
242 	s = splimp();
243 	IF_DEQUEUE(&is->is_if.if_snd, m);
244 	splx(s);
245 	if (m == 0) {
246 		is->is_flags &= ~ACEF_OACTIVE;
247 		return;
248 	}
249 	len = aceput(unit, txs->tx_data, m);
250 	retries = txs->tx_csr & TCS_RTC;
251 	if (retries > 0)
252 		acebakoff(is, txs, retries);
253 
254 	/*
255 	 * Ensure minimum packet length.
256 	 * This makes the safe assumtion that there are no virtual holes
257 	 * after the data.
258 	 * For security, it might be wise to zero out the added bytes,
259 	 * but we're mainly interested in speed at the moment.
260 	 */
261 	if (len - sizeof (struct ether_header) < ETHERMIN)
262 		len = ETHERMIN + sizeof (struct ether_header);
263 	if (++is->is_txnext > SEG_MAX)
264 		is->is_txnext = is->is_segboundry;
265 	is->is_if.if_opackets++;
266 	is->is_xcnt++;
267 	len = (len & 0x7fff) | TCS_TBFULL;
268 	movow(txs, len);
269 	goto again;
270 }
271 
272 /*
273  * Transmit done interrupt.
274  */
275 acecint(unit)
276 	int unit;
277 {
278 	register struct ace_softc *is = &ace_softc[unit];
279 	register struct tx_segment *txseg;
280 	short eostat;
281 
282 	if (is->is_xcnt <= 0)  {
283 		log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n",
284 		    unit, is->is_xcnt);
285 		is->is_xcnt = 0;
286 		if (is->is_if.if_snd.ifq_head)
287 			acestart(unit);
288 		return;
289 	}
290 	is->is_xcnt--;
291 	txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
292 	eostat = txseg->tx_csr;
293 	if ((eostat & TCS_TBFULL) == 0) {
294 		is->is_stats.tx_retries += eostat & TCS_RTC;
295 		if (eostat & TCS_RTFAIL)  {
296 			is->is_stats.tx_discarded++;
297 			is->is_if.if_oerrors++;
298 		} else
299 			is->is_stats.tx_datagrams++;
300 		if (++is->is_eoctr >= 16)
301 			is->is_eoctr = is->is_segboundry;
302 	}
303 	if (is->is_if.if_snd.ifq_head)
304 		acestart(unit);
305 }
306 
307 /*
308  * Ethernet interface receiver interrupt.
309  * If input error just drop packet.
310  * Otherwise purge input buffered data path and examine
311  * packet to determine type.  If can't determine length
312  * from type, then have to drop packet.  Othewise decapsulate
313  * packet based on type and pass to type specific higher-level
314  * input routine.
315  */
316 acerint(unit)
317 	int unit;
318 {
319 	register struct ace_softc *is = &ace_softc[unit];
320 	register struct ifqueue *inq;
321 	register struct ether_header *ace;
322 	register struct rx_segment *rxseg;
323 	int len, s, off, resid;
324 	struct mbuf *m;
325 	short eistat;
326 
327 	if ((is->is_if.if_flags&IFF_RUNNING) == 0)
328 		return;
329 again:
330 	rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
331 	eistat = rxseg->rx_csr;
332 	if ((eistat & RCS_RBFULL) == 0)
333 		return;
334 	is->is_if.if_ipackets++;
335 	if (++is->is_eictr >= is->is_segboundry)
336 		is->is_eictr = 0;
337 	len = eistat & RCS_RBC;
338 	if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
339 	    len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) {
340 		if (eistat & RCS_ROVRN)
341 			is->is_stats.rx_overruns++;
342 		if (eistat & RCS_RCRC)
343 			is->is_stats.rx_crc_errors++;
344 		if (eistat & RCS_RODD)
345 			is->is_stats.rx_align_errors++;
346 		if (len < ET_MINLEN)
347 			is->is_stats.rx_underruns++;
348 		if (len > ET_MAXLEN+CRC_SIZE)
349 			is->is_stats.rx_overruns++;
350 		is->is_if.if_ierrors++;
351 		rxseg->rx_csr = 0;
352 		return;
353 	} else
354 		is->is_stats.rx_datagrams++;
355 	ace = (struct ether_header *)rxseg->rx_data;
356 	len -= sizeof (struct ether_header);
357 	/*
358 	 * Deal with trailer protocol: if type is trailer
359 	 * get true type from first 16-bit word past data.
360 	 * Remember that type was trailer by setting off.
361 	 */
362 	ace->ether_type = ntohs((u_short)ace->ether_type);
363 #define	acedataaddr(ace, off, type) \
364     ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
365 	if (ace->ether_type >= ETHERTYPE_TRAIL &&
366 	    ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
367 		off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
368 		if (off >= ETHERMTU)
369 			goto setup;		/* sanity */
370 		ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
371 		resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
372 		if (off + resid > len)
373 			goto setup;		/* sanity */
374 		len = off + resid;
375 	} else
376 		off = 0;
377 	if (len == 0)
378 		goto setup;
379 
380 	/*
381 	 * Pull packet off interface.  Off is nonzero if packet
382 	 * has trailing header; aceget will then force this header
383 	 * information to be at the front, but we still have to drop
384 	 * the type and length which are at the front of any trailer data.
385 	 */
386 	m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
387 	if (m == 0)
388 		goto setup;
389 	if (off) {
390 		struct ifnet *ifp;
391 
392 		ifp = *(mtod(m, struct ifnet **));
393 		m->m_off += 2 * sizeof (u_short);
394 		m->m_len -= 2 * sizeof (u_short);
395 		*(mtod(m, struct ifnet **)) = ifp;
396 	}
397 	switch (ace->ether_type) {
398 
399 #ifdef INET
400 	case ETHERTYPE_IP:
401 		schednetisr(NETISR_IP);
402 		inq = &ipintrq;
403 		break;
404 #endif
405 
406 	case ETHERTYPE_ARP:
407 		arpinput(&is->is_ac, m);
408 		goto setup;
409 #ifdef NS
410 	case ETHERTYPE_NS:
411 		schednetisr(NETISR_NS);
412 		inq = &nsintrq;
413 		break;
414 
415 #endif
416 	default:
417 		m_freem(m);
418 		goto setup;
419 	}
420 	if (IF_QFULL(inq)) {
421 		IF_DROP(inq);
422 		m_freem(m);
423 		goto setup;
424 	}
425 	s = splimp();
426 	IF_ENQUEUE(inq, m);
427 	splx(s);
428 setup:
429 	rxseg->rx_csr = 0;
430 	goto again;
431 }
432 
433 /*
434  * Ethernet output routine.
435  * Encapsulate a packet of type family for the local net.
436  * Use trailer local net encapsulation if enough data in first
437  * packet leaves a multiple of 512 bytes of data in remainder.
438  */
439 aceoutput(ifp, m0, dst)
440 	struct ifnet *ifp;
441 	struct mbuf *m0;
442 	struct sockaddr *dst;
443 {
444 	register struct ace_softc *is = &ace_softc[ifp->if_unit];
445 	register struct mbuf *m = m0;
446 	register struct ether_header *ace;
447 	register int off;
448 	struct mbuf *mcopy = (struct mbuf *)0;
449 	int type, s, error, usetrailers;
450 	u_char edst[6];
451 	struct in_addr idst;
452 
453 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
454 		error = ENETDOWN;
455 		goto bad;
456 	}
457 	switch (dst->sa_family) {
458 
459 #ifdef INET
460 	case AF_INET:
461 		idst = ((struct sockaddr_in *)dst)->sin_addr;
462 		if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers))
463 			return (0);	/* if not yet resolved */
464 		if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
465 		    sizeof (edst)))
466 			mcopy = m_copy(m, 0, (int)M_COPYALL);
467 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
468 		if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
469 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
470 			type = ETHERTYPE_TRAIL + (off>>9);
471 			m->m_off -= 2 * sizeof (u_short);
472 			m->m_len += 2 * sizeof (u_short);
473 			*mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
474 			*(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
475 			goto gottrailertype;
476 		}
477 		type = ETHERTYPE_IP;
478 		off = 0;
479 		goto gottype;
480 #endif
481 #ifdef NS
482 	case AF_NS:
483  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
484 		    (caddr_t)edst, sizeof (edst));
485 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst)))
486 			mcopy = m_copy(m, 0, (int)M_COPYALL);
487 		else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
488 		    sizeof(edst)))
489 			return(looutput(&loif, m, dst));
490 		type = ETHERTYPE_NS;
491 		off = 0;
492 		goto gottype;
493 #endif
494 	case AF_UNSPEC:
495 		ace = (struct ether_header *)dst->sa_data;
496 		bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
497 		type = ace->ether_type;
498 		goto gottype;
499 
500 	default:
501 		log(LOG_ERR, "ace%d: can't handle af%d\n",
502 		    ifp->if_unit, dst->sa_family);
503 		error = EAFNOSUPPORT;
504 		goto bad;
505 	}
506 
507 gottrailertype:
508 	/*
509 	 * Packet to be sent as trailer: move first packet
510 	 * (control information) to end of chain.
511 	 */
512 	while (m->m_next)
513 		m = m->m_next;
514 	m->m_next = m0;
515 	m = m0->m_next;
516 	m0->m_next = 0;
517 	m0 = m;
518 
519 gottype:
520 	/*
521 	 * Add local net header.  If no space in first mbuf,
522 	 * allocate another.
523 	 */
524 	if (m->m_off > MMAXOFF ||
525 	    MMINOFF + sizeof (struct ether_header) > m->m_off) {
526 		m = m_get(M_DONTWAIT, MT_HEADER);
527 		if (m == 0) {
528 			error = ENOBUFS;
529 			goto bad;
530 		}
531 		m->m_next = m0;
532 		m->m_off = MMINOFF;
533 		m->m_len = sizeof (struct ether_header);
534 	} else {
535 		m->m_off -= sizeof (struct ether_header);
536 		m->m_len += sizeof (struct ether_header);
537 	}
538 	ace = mtod(m, struct ether_header *);
539 	bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
540 	bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost,
541 	    sizeof (is->is_addr));
542 	ace->ether_type = htons((u_short)type);
543 
544 	/*
545 	 * Queue message on interface, and start output if interface
546 	 * not yet active.
547 	 */
548 	s = splimp();
549 	if (IF_QFULL(&ifp->if_snd)) {
550 		IF_DROP(&ifp->if_snd);
551 		error = ENOBUFS;
552 		goto qfull;
553 	}
554 	IF_ENQUEUE(&ifp->if_snd, m);
555 	splx(s);
556 	acestart(ifp->if_unit);
557 	return (mcopy ? looutput(&loif, mcopy, dst) : 0);
558 qfull:
559 	m0 = m;
560 	splx(s);
561 bad:
562 	m_freem(m0);
563 	if (mcopy)
564 		m_freem(mcopy);
565 	return (error);
566 }
567 
568 /*
569  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
570  * If packet size is less than the minimum legal size,
571  * the buffer is expanded.  We probably should zero out the extra
572  * bytes for security, but that would slow things down.
573  */
574 /*ARGSUSED*/
575 aceput(unit, txbuf, m)
576 	int unit;
577 	char *txbuf;
578 	struct mbuf *m;
579 {
580 	register u_char *bp, *mcp;
581 	register short *s1, *s2;
582 	register u_int len;
583 	register struct mbuf *mp;
584 	int total;
585 
586 	total = 0;
587 	bp = (u_char *)txbuf;
588 	for (mp = m; (mp); mp = mp->m_next) {
589 		len = mp->m_len;
590 		if (len == 0)
591 			continue;
592 		total += len;
593 		mcp = mtod(mp, u_char *);
594 		if (((int)mcp & 01) && ((int)bp & 01)) {
595 			/* source & destination at odd addresses */
596 			movob(bp++, *mcp++);
597 			--len;
598 		}
599 		if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
600 			register u_int l;
601 
602 			s1 = (short *)bp;
603 			s2 = (short *)mcp;
604 			l = len >> 1;		/* count # of shorts */
605 			while (l-- != 0)
606 				movow(s1++, *s2++);
607 			len &= 1;		/* # remaining bytes */
608 			bp = (u_char *)s1;
609 			mcp = (u_char *)s2;
610 		}
611 		while (len-- != 0)
612 			movob(bp++, *mcp++);
613 	}
614 	m_freem(m);
615 	return (total);
616 }
617 
618 /*
619  * Routine to copy from VERSAbus memory into mbufs.
620  *
621  * Warning: This makes the fairly safe assumption that
622  * mbufs have even lengths.
623  */
624 /*ARGSUSED*/
625 struct mbuf *
626 aceget(rxbuf, totlen, off0, ifp)
627 	u_char *rxbuf;
628 	int totlen, off0;
629 	struct ifnet *ifp;
630 {
631 	register u_char *cp, *mcp;
632 	register int tlen;
633 	register struct mbuf *m;
634 	struct mbuf *top = 0, **mp = &top;
635 	int len, off = off0;
636 
637 	cp = rxbuf + sizeof (struct ether_header);
638 	while (totlen > 0) {
639 		MGET(m, M_DONTWAIT, MT_DATA);
640 		if (m == 0)
641 			goto bad;
642 		if (off) {
643 			len = totlen - off;
644 			cp = rxbuf + sizeof (struct ether_header) + off;
645 		} else
646 			len = totlen;
647 		if (ifp)
648 			len += sizeof(ifp);
649 		if (len >= NBPG) {
650 			MCLGET(m);
651 			if (m->m_len == CLBYTES)
652 				m->m_len = len = MIN(len, CLBYTES);
653 			else
654 				m->m_len = len = MIN(MLEN, len);
655 		} else {
656 			m->m_len = len = MIN(MLEN, len);
657 			m->m_off = MMINOFF;
658 		}
659 		mcp = mtod(m, u_char *);
660 		if (ifp) {
661 			/*
662 			 * Prepend interface pointer to first mbuf.
663 			 */
664 			*(mtod(m, struct ifnet **)) = ifp;
665 			mcp += sizeof(ifp);
666 			len -= sizeof(ifp);
667 			ifp = (struct ifnet *)0;
668 		}
669 		/*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
670 		/*cp += len; mcp += len;*/
671 		tlen = len;
672 		if (((int)mcp & 01) && ((int)cp & 01)) {
673 			/* source & destination at odd addresses */
674 			*mcp++ = *cp++;
675 			--tlen;
676 		}
677 		if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) {
678 			register short *s1, *s2;
679 			register int l;
680 
681 			s1 = (short *)mcp;
682 			s2 = (short *)cp;
683 			l = tlen >> 1;		/* count # of shorts */
684 			while (l-- > 0)		/* copy shorts */
685 				*s1++ = *s2++;
686 			tlen &= 1;		/* # remaining bytes */
687 			mcp = (u_char *)s1;
688 			cp = (u_char *)s2;
689 		}
690 		while (tlen-- > 0)
691 			*mcp++ = *cp++;
692 		*mp = m;
693 		mp = &m->m_next;
694 		if (off == 0) {
695 			totlen -= len;
696 			continue;
697 		}
698 		off += len;
699 		if (off == totlen) {
700 			cp = rxbuf + sizeof (struct ether_header);
701 			off = 0;
702 			totlen = off0;
703 		}
704 	}
705 	return (top);
706 bad:
707 	m_freem(top);
708 	return (0);
709 }
710 
711 /* backoff table masks */
712 short	random_mask_tbl[16] = {
713 	0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0,
714 	0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0
715 };
716 
717 acebakoff(is, txseg, retries)
718 	struct ace_softc *is;
719 	struct tx_segment *txseg;
720 	register int retries;
721 {
722 	register short *pBakNum, random_num;
723 	short *pMask;
724 
725 	pMask = &random_mask_tbl[0];
726 	pBakNum = &txseg->tx_backoff[0];
727 	while (--retries >= 0) {
728 		random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
729 		random_num &= *pMask++;
730 		*pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc);
731 	}
732 }
733 
734 /*
735  * Process an ioctl request.
736  */
737 aceioctl(ifp, cmd, data)
738 	register struct ifnet *ifp;
739 	int cmd;
740 	caddr_t data;
741 {
742 	register struct ifaddr *ifa = (struct ifaddr *)data;
743 	struct acedevice *addr;
744 	int s = splimp(), error = 0;
745 
746 	switch (cmd) {
747 
748 	case SIOCSIFADDR:
749 		ifp->if_flags |= IFF_UP;
750 		switch (ifa->ifa_addr.sa_family) {
751 #ifdef INET
752 		case AF_INET:
753 			aceinit(ifp->if_unit);	/* before arpwhohas */
754 			((struct arpcom *)ifp)->ac_ipaddr =
755 				IA_SIN(ifa)->sin_addr;
756 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
757 			break;
758 #endif
759 #ifdef NS
760 		case AF_NS: {
761 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
762 			struct ace_softc *is = &ace_softc[ifp->if_unit];
763 
764 			if (!ns_nullhost(*ina)) {
765 				ifp->if_flags &= ~IFF_RUNNING;
766 				addr = (struct acedevice *)
767 				    aceinfo[ifp->if_unit]->ui_addr;
768 				movow(&addr->csr, CSR_RESET);
769 				DELAY(10000);
770 				/* set station address & copy addr to arp */
771 				acesetaddr(ifp->if_unit, addr,
772 				    ina->x_host.c_host);
773 			} else
774 				ina->x_host = *(union ns_host *)is->is_addr;
775 			aceinit(ifp->if_unit);
776 			break;
777 		}
778 #endif
779 		default:
780 			aceinit(ifp->if_unit);
781 			break;
782 		}
783 		break;
784 
785 	case SIOCSIFFLAGS:
786 		if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
787 			addr = (struct acedevice *)
788 			    (aceinfo[ifp->if_unit]->ui_addr);
789 			movow(&addr->csr, CSR_RESET);
790 			ifp->if_flags &= ~IFF_RUNNING;
791 		} else if (ifp->if_flags&IFF_UP &&
792 		    (ifp->if_flags&IFF_RUNNING) == 0)
793 			aceinit(ifp->if_unit);
794 		break;
795 
796 	default:
797 		error = EINVAL;
798 	}
799 	splx(s);
800 	return (error);
801 }
802 
803 /*
804  * Set the on-board station address, then read it back
805  * to initialize the address used by ARP (among others).
806  */
807 acesetaddr(unit, addr, station)
808 	short unit;
809 	struct acedevice *addr;
810 	char *station;
811 {
812 	struct ace_softc *is = &ace_softc[unit];
813 	register short *wp, i;
814 
815 	for (wp = (short *)addr->station, i = 0; i < 6; i++)
816 		movow(wp++, ~*station++);
817 	for (wp = (short *)addr->station, i = 0; i < 6; i++)
818 		is->is_addr[i] = ~*wp++;
819 	printf("ace%d: hardware address %s\n", unit,
820 	    ether_sprintf(is->is_addr));
821 }
822 
823 /*
824  * Setup the device for use.  Initialize dual-ported memory,
825  * backoff parameters, and various other software state.
826  */
827 acesetup(unit)
828 	int unit;
829 {
830 	register struct ace_softc *is = &ace_softc[unit];
831 	register char *pData1;
832 	register short i;
833 	struct acedevice *addr;
834 
835 	bzero(is->is_dpm, 16384*2);
836 	is->is_currnd = 49123;
837 	addr = (struct acedevice *)aceinfo[unit]->ui_addr;
838 	is->is_segboundry = (addr->segb >> 11) & 0xf;
839 	pData1 = is->is_dpm + (is->is_segboundry << 11);
840 	for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) {
841 		acebakoff(is, (struct tx_segment *)pData1, 15);
842 		pData1 += sizeof (struct tx_segment);
843 	}
844 	is->is_eictr = 0;
845 	is->is_eoctr = is->is_txnext = is->is_segboundry;
846 	bzero((char *)&is->is_stats, sizeof (is->is_stats));
847 }
848 #endif
849