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