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