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