xref: /csrg-svn/sys/tahoe/if/if_enp.c (revision 29649)
1*29649Ssam /*	if_enp.c	1.1	86/07/20	*/
2*29649Ssam 
3*29649Ssam #include "enp.h"
4*29649Ssam #define ENPBPTE 128
5*29649Ssam #if NENP > 0
6*29649Ssam 
7*29649Ssam /*
8*29649Ssam  * Modified 3 Com Ethernet Controller interface
9*29649Ssam  * enp modifications added S. F. Holmgren
10*29649Ssam  */
11*29649Ssam 
12*29649Ssam #include "param.h"
13*29649Ssam #include "systm.h"
14*29649Ssam #include "mbuf.h"
15*29649Ssam #include "buf.h"
16*29649Ssam #include "protosw.h"
17*29649Ssam #include "socket.h"
18*29649Ssam #include "vmmac.h"
19*29649Ssam #include "errno.h"
20*29649Ssam #include "time.h"
21*29649Ssam #include "kernel.h"
22*29649Ssam #include "uio.h"
23*29649Ssam 
24*29649Ssam #include "../net/if.h"
25*29649Ssam #include "../net/netisr.h"
26*29649Ssam #include "../net/route.h"
27*29649Ssam #include "../netinet/in.h"
28*29649Ssam #include "../h/ioctl.h"
29*29649Ssam 
30*29649Ssam #include "../netinet/in_systm.h"
31*29649Ssam #include "../netinet/ip.h"
32*29649Ssam #include "../netinet/ip_var.h"
33*29649Ssam #include "../netinet/if_ether.h"
34*29649Ssam 
35*29649Ssam #include "../tahoevba/vbavar.h"
36*29649Ssam #include "../tahoeif/if_enp.h"
37*29649Ssam #include "../machine/mtpr.h"
38*29649Ssam #include "../tahoeif/if_debug.h"
39*29649Ssam 
40*29649Ssam #define ENP0_PHYSADDR	0xf40000	/* board # 0 physical base addr */
41*29649Ssam #define ENP1_PHYSADDR	0xf60000	/* board # 1 physical base addr */
42*29649Ssam #define ENPSTART	0xf02000	/* standard enp start addr 	*/
43*29649Ssam 
44*29649Ssam int	enpprobe(), enpattach(), enpintr();
45*29649Ssam extern	nulldev();
46*29649Ssam caddr_t	vtoph();
47*29649Ssam struct  mbuf *m_tofree();
48*29649Ssam struct  vba_device *enpinfo[ NENP ];
49*29649Ssam 
50*29649Ssam /*	Maximun 2 controllers per system supported			*/
51*29649Ssam 
52*29649Ssam long  enpstd[] = { ENP0_PHYSADDR+0x1000,ENP1_PHYSADDR+0x1000, 0 };
53*29649Ssam extern	char	enp0utl[], enp1utl[];	/* enp accessible ram map	*/
54*29649Ssam char	*enpmap[]= { enp0utl, enp1utl };
55*29649Ssam extern	long	ENP0map[], ENP1map[];
56*29649Ssam long	*ENPmap[] = {ENP0map, ENP1map};
57*29649Ssam long	ENPmapa[] = {0xfff41000, 0xfff61000};
58*29649Ssam long	enpismapped[NENP];
59*29649Ssam 
60*29649Ssam unsigned short intvec[4] =
61*29649Ssam 	{ 0xc1, 0xc2, 0xc3, 0xc4 };	/* intrvec of upto 4 enps	*/
62*29649Ssam 
63*29649Ssam struct  vba_driver enpdriver =
64*29649Ssam {
65*29649Ssam /* use of prom based version
66*29649Ssam 	enpprobe, 0, enpattach, 0, 0,	enpintr,
67*29649Ssam */
68*29649Ssam 	enpprobe, 0, nulldev, 0,
69*29649Ssam 	enpstd,   "enp", enpinfo, "ENP 20", 0
70*29649Ssam };
71*29649Ssam 
72*29649Ssam int     enpinit(),
73*29649Ssam 	enpioctl(),
74*29649Ssam 	enpoutput(),
75*29649Ssam 	enpreset(),
76*29649Ssam 	enpbroadcast(),
77*29649Ssam 	enptimeout();
78*29649Ssam 
79*29649Ssam int	enpcopy();
80*29649Ssam 
81*29649Ssam struct  mbuf *enpget();
82*29649Ssam 
83*29649Ssam extern  struct ifnet loif;
84*29649Ssam 
85*29649Ssam /*
86*29649Ssam  * Ethernet software status per interface.
87*29649Ssam  *
88*29649Ssam  * Each interface is referenced by a network interface structure,
89*29649Ssam  * es_if, which the routing code uses to locate the interface.
90*29649Ssam  * This structure contains the output queue for the interface, its address, ...
91*29649Ssam  */
92*29649Ssam 
93*29649Ssam struct 	enp_softc	enp_softc[NENP];
94*29649Ssam long	stat_addr[NENP];	/* enp statistic addr (for nstat use) */
95*29649Ssam long	ring_addr[NENP];	/* enp dev ring addresses (for nstat use) */
96*29649Ssam int 	numenp = NENP;
97*29649Ssam int	enp_intr = 0, 		/* no. of enp_to_host interrupts */
98*29649Ssam 	host_intr = 0;		/* no. of host_to_enp interrupts */
99*29649Ssam short	enpram[NENP];		/* open/close flags for enp devices */
100*29649Ssam /*	Debugging tools, used to trace input packets */
101*29649Ssam extern 	int	printerror;	/* error print flag, from if_ace.c */
102*29649Ssam int	save_enp_inpkt = 0;
103*29649Ssam #define	ENPTRACE(X)	if (save_enp_inpkt) X;
104*29649Ssam 
105*29649Ssam struct 	inp_err 	enperr[NENP];
106*29649Ssam 
107*29649Ssam /*
108*29649Ssam  * Probe for device.
109*29649Ssam  */
110*29649Ssam 
111*29649Ssam enpprobe(reg)
112*29649Ssam caddr_t reg;
113*29649Ssam {
114*29649Ssam 	static	int 	unit=0;
115*29649Ssam 	register ENPDEVICE	*addr = (ENPDEVICE *)reg;
116*29649Ssam 
117*29649Ssam 	if( (badaddr( addr, 2 ) ) || (badaddr( &addr->enp_ram[0], 2 ) ) )
118*29649Ssam 		return( 0 );
119*29649Ssam 	addr->enp_state = S_ENPRESET; /* controller is reset by vbus reset */
120*29649Ssam 	/* save address of statistic area for nstat uses	*/
121*29649Ssam 
122*29649Ssam 	stat_addr[unit] = (long) &(addr->enp_stat);
123*29649Ssam 	ring_addr[unit++] = (long) &(addr->enp_toenp);
124*29649Ssam 
125*29649Ssam 	return( ENPSIZE );
126*29649Ssam }
127*29649Ssam 
128*29649Ssam /*
129*29649Ssam  * Interface exists: make available by filling in network interface
130*29649Ssam  * record.  System will initialize the interface when it is ready
131*29649Ssam  * to accept packets.
132*29649Ssam  */
133*29649Ssam 
134*29649Ssam enpattach( md )
135*29649Ssam register struct vba_device *md;
136*29649Ssam {
137*29649Ssam 	struct enp_softc 	*es = &enp_softc[md->ui_unit];
138*29649Ssam 	register struct ifnet 	*ifp = &es->es_if;
139*29649Ssam 	register ENPDEVICE 	*addr = (ENPDEVICE *)md->ui_addr;
140*29649Ssam 	struct sockaddr_in 	*sin;
141*29649Ssam 
142*29649Ssam 	enpgetaddr( md->ui_unit );
143*29649Ssam 
144*29649Ssam 	ifp->if_unit = md->ui_unit;
145*29649Ssam 	ifp->if_name = "enp";
146*29649Ssam 	ifp->if_mtu = ETHERMTU;
147*29649Ssam 
148*29649Ssam /*	bcopy(&es->es_boardaddr, es->es_enaddr, sizeof(es->es_enaddr)); */
149*29649Ssam 
150*29649Ssam 	sin = (struct sockaddr_in *)&es->es_if.if_addr;
151*29649Ssam 	sin->sin_family = AF_INET;
152*29649Ssam 
153*29649Ssam 	ifp->if_init = enpinit;
154*29649Ssam 	ifp->if_ioctl = enpioctl;
155*29649Ssam 	ifp->if_output = enpoutput;
156*29649Ssam 	ifp->if_reset = enpreset;
157*29649Ssam 	if_attach(ifp);
158*29649Ssam }
159*29649Ssam 
160*29649Ssam 
161*29649Ssam /*
162*29649Ssam  * Reset of interface after UNIBUS reset.
163*29649Ssam  */
164*29649Ssam enpreset(unit)
165*29649Ssam int unit;
166*29649Ssam {
167*29649Ssam 	register struct vba_device *md;
168*29649Ssam 
169*29649Ssam 	if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
170*29649Ssam 		return(ENODEV);
171*29649Ssam 
172*29649Ssam 	enpinit(unit);
173*29649Ssam }
174*29649Ssam 
175*29649Ssam /*
176*29649Ssam  * Initialization of interface; clear recorded pending
177*29649Ssam  * operations.
178*29649Ssam  */
179*29649Ssam 
180*29649Ssam enpinit( unit )
181*29649Ssam int unit;
182*29649Ssam {
183*29649Ssam 	struct enp_softc 	*es = &enp_softc[unit];
184*29649Ssam 	ENPDEVICE 		*addr;
185*29649Ssam 	int i, s;
186*29649Ssam 	u_char *cp, *ap;
187*29649Ssam 	register struct ifnet 	*ifp = &es->es_if;
188*29649Ssam 	register struct sockaddr_in *sin, *sinb;
189*29649Ssam 
190*29649Ssam 	sin = (struct sockaddr_in *)&ifp->if_addr;
191*29649Ssam 
192*29649Ssam 	if ( !enpismapped[unit] ) {
193*29649Ssam 		ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
194*29649Ssam 		++enpismapped[unit];
195*29649Ssam 	}
196*29649Ssam 	if ((addr = (ENPDEVICE *)enpinfo[unit]->ui_addr) == (ENPDEVICE *)0)
197*29649Ssam 		return(ENODEV);
198*29649Ssam 	s = splimp();
199*29649Ssam 	RESET_ENP( addr );
200*29649Ssam 	DELAY( 200000 );
201*29649Ssam 
202*29649Ssam #ifdef notdef
203*29649Ssam /* only needed if not downloading ( ie, ROM-resident ENP code) */
204*29649Ssam 	addr->enp_intrvec = intvec[unit];
205*29649Ssam 	ENP_GO( addr,ENPSTART );
206*29649Ssam 	DELAY( 200000 );
207*29649Ssam /* end of ROM-resident */
208*29649Ssam #endif notdef
209*29649Ssam 
210*29649Ssam 	es->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/
211*29649Ssam 	splx(s);
212*29649Ssam 
213*29649Ssam 	if_rtinit( &es->es_if,RTF_UP );
214*29649Ssam 	arpwhohas(&es->es_ac, &sin->sin_addr);
215*29649Ssam }
216*29649Ssam 
217*29649Ssam 
218*29649Ssam /*
219*29649Ssam  * Ethernet interface interrupt.
220*29649Ssam  */
221*29649Ssam 
222*29649Ssam enpintr( unit )
223*29649Ssam {
224*29649Ssam 	register ENPDEVICE 		*addr;
225*29649Ssam 	register BCB			*bcbp;
226*29649Ssam 	register struct vba_device	 *md;
227*29649Ssam 
228*29649Ssam 	enp_intr++;
229*29649Ssam 
230*29649Ssam 	if (unit >= NENP || (md = enpinfo[unit]) == 0)
231*29649Ssam 		return;
232*29649Ssam 
233*29649Ssam 	addr = (ENPDEVICE *)md->ui_addr;
234*29649Ssam 
235*29649Ssam 	if( IS_ENP_INTR(addr) == 0 )
236*29649Ssam 		return;
237*29649Ssam 
238*29649Ssam 	ACK_ENP_INTR( addr );
239*29649Ssam 
240*29649Ssam 	while( (bcbp = (BCB *)ringget( &addr->enp_tohost )) != 0 )
241*29649Ssam 	{
242*29649Ssam 		enpread( &enp_softc[ unit ],bcbp, unit );
243*29649Ssam 		ringput( &addr->enp_enpfree,bcbp );
244*29649Ssam 	}
245*29649Ssam 	return(0);
246*29649Ssam }
247*29649Ssam 
248*29649Ssam #define	MAXBLEN	1500
249*29649Ssam char	errpkt[MAXBLEN];
250*29649Ssam int	bufptr = 0;
251*29649Ssam int	maxl_tosave = 200;		/* save only the first 200 bytes */
252*29649Ssam 
253*29649Ssam saverrpkt(errbuf, errtype, len)
254*29649Ssam register u_char *errbuf;
255*29649Ssam int errtype, len;
256*29649Ssam {
257*29649Ssam 	int remain, newptr;
258*29649Ssam 
259*29649Ssam 	remain = MAXBLEN - bufptr;
260*29649Ssam 	if (remain < 50)		/* if too small			*/
261*29649Ssam 		return;			/* no space avail		*/
262*29649Ssam 	len = (len > maxl_tosave || len <= 0) ? maxl_tosave : len;
263*29649Ssam 	len = len > remain ? (remain - 2*sizeof(len)): len;
264*29649Ssam 	newptr = bufptr + len + 2*sizeof(len);
265*29649Ssam 	if (newptr <= MAXBLEN) {
266*29649Ssam 		enpcopy((char *)&len, &errpkt[bufptr], sizeof(len));
267*29649Ssam 		enpcopy((char *)&errtype, &errpkt[bufptr+sizeof(len)],
268*29649Ssam 			sizeof(errtype));
269*29649Ssam 		enpcopy(errbuf, &errpkt[bufptr+(2*sizeof(len))], len);
270*29649Ssam 	}
271*29649Ssam 	bufptr = newptr;
272*29649Ssam }
273*29649Ssam 
274*29649Ssam /*
275*29649Ssam  * Read input packet, examine its packet type, and enqueue it.
276*29649Ssam  */
277*29649Ssam 
278*29649Ssam enpread( es, bcbp, unit )
279*29649Ssam struct	enp_softc *es;
280*29649Ssam register BCB *bcbp;
281*29649Ssam int	unit;
282*29649Ssam {
283*29649Ssam 	register struct ether_header *enp;
284*29649Ssam 	struct mbuf *m;
285*29649Ssam 	long int  s, v;
286*29649Ssam 	register short *vp = (short *)&v,
287*29649Ssam 			*sp;
288*29649Ssam 	int len, off, resid, enptype;
289*29649Ssam 	register struct ifqueue *inq;
290*29649Ssam 
291*29649Ssam 	es->es_if.if_ipackets++;
292*29649Ssam 
293*29649Ssam 	/*
294*29649Ssam 	 * Get input data length.
295*29649Ssam 	 * Get pointer to ethernet header (in input buffer).
296*29649Ssam 	 * Deal with trailer protocol: if type is PUP trailer
297*29649Ssam 	 * get true type from first 16-bit word past data.
298*29649Ssam 	 * Remember that type was trailer by setting off.
299*29649Ssam 	 */
300*29649Ssam 
301*29649Ssam 	len = bcbp->b_msglen - SIZEOF_ETHEADER;
302*29649Ssam #ifdef TAHOE
303*29649Ssam 	sp = (short *)&bcbp->b_addr;
304*29649Ssam 	*vp = *sp; vp[1] = sp[1];
305*29649Ssam 	enp = (struct ether_header *) v;
306*29649Ssam #else
307*29649Ssam 	enp = (struct ether_header *)bcbp->b_addr;
308*29649Ssam #endif TAHOE
309*29649Ssam 
310*29649Ssam #define enpdataaddr(enp, off, type) ((type)(((caddr_t)(((char *)enp)+SIZEOF_ETHEADER)+(off))))
311*29649Ssam 
312*29649Ssam 	enptype = enp->ether_type;
313*29649Ssam 	if (enptype >= ETHERPUP_TRAIL && enptype < ETHERPUP_TRAIL+ETHERPUP_NTRAILER)
314*29649Ssam 	{
315*29649Ssam 		off = (enptype - ETHERPUP_TRAIL) * 512;
316*29649Ssam 		if (off >= ETHERMTU) {
317*29649Ssam 			enperr[unit].bad_offset++;
318*29649Ssam 			ENPTRACE(saverrpkt((char *)enp, B_OFFSET, bcbp->b_msglen));
319*29649Ssam 
320*29649Ssam 			goto badinput;
321*29649Ssam 		}
322*29649Ssam 		enptype = *enpdataaddr(enp, off, u_short *);
323*29649Ssam 		resid = *(enpdataaddr(enp, off+2, u_short *));
324*29649Ssam 
325*29649Ssam 		if (off + resid > len) {
326*29649Ssam 			enperr[unit].bad_length++;
327*29649Ssam 			ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen));
328*29649Ssam 			goto badinput;
329*29649Ssam 		}
330*29649Ssam 		len = off + resid;
331*29649Ssam 	}
332*29649Ssam 	else
333*29649Ssam 		off = 0;
334*29649Ssam 
335*29649Ssam 	if( len == 0 ) {
336*29649Ssam 		enperr[unit].bad_length++;
337*29649Ssam 		ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen));
338*29649Ssam 		goto badinput;
339*29649Ssam 	}
340*29649Ssam 	/*
341*29649Ssam 	 * Pull packet off interface.  Off is nonzero if packet
342*29649Ssam 	 * has trailing header; enpget will then force this header
343*29649Ssam 	 * information to be at the front, but we still have to drop
344*29649Ssam 	 * the type and length which are at the front of any trailer data.
345*29649Ssam 	 */
346*29649Ssam 
347*29649Ssam 	m = enpget(bcbp, len, off);
348*29649Ssam 	if( m == 0 )  {
349*29649Ssam 		enperr[unit].h_nobuffer++; /* host runs out of buf */
350*29649Ssam 		goto badinput;
351*29649Ssam 	}
352*29649Ssam 	if( off )
353*29649Ssam 	{
354*29649Ssam 		m->m_off += 2 * sizeof (u_short);
355*29649Ssam 		m->m_len -= 2 * sizeof (u_short);
356*29649Ssam 	}
357*29649Ssam 
358*29649Ssam 	switch (enptype)
359*29649Ssam 	{
360*29649Ssam #ifdef INET
361*29649Ssam 	case ETHERPUP_IPTYPE:
362*29649Ssam #ifdef notdef
363*29649Ssam 		arpipin(enp, m);
364*29649Ssam #endif notdef
365*29649Ssam 		schednetisr(NETISR_IP);
366*29649Ssam 		inq = &ipintrq;
367*29649Ssam 		break;
368*29649Ssam 
369*29649Ssam 	case ETHERPUP_ARPTYPE:
370*29649Ssam 		arpinput(&es->es_ac, m);
371*29649Ssam 		return(0);
372*29649Ssam #endif
373*29649Ssam 	default:	/* unrecognized ethernet header */
374*29649Ssam 		enperr[unit].bad_packetype++;
375*29649Ssam 		if (printerror) {
376*29649Ssam 			printf("\nenp%d: Undefined packet type 0x%x ", unit,
377*29649Ssam 				enp->ether_type);
378*29649Ssam 			printf("from host: %x.%x.%x.%x.%x.%x\n",
379*29649Ssam 				enp->ether_shost[0], enp->ether_shost[1],
380*29649Ssam 				enp->ether_shost[2], enp->ether_shost[3],
381*29649Ssam 				enp->ether_shost[4], enp->ether_shost[5]);
382*29649Ssam 		}	/* end debugging aid	*/
383*29649Ssam 		ENPTRACE(saverrpkt((char *)enp, B_PACKETYPE, bcbp->b_msglen));
384*29649Ssam 		m_freem(m);
385*29649Ssam 		goto badinput;
386*29649Ssam 	}
387*29649Ssam 
388*29649Ssam 	if (IF_QFULL(inq))
389*29649Ssam 	{
390*29649Ssam 		enperr[unit].inq_full++;
391*29649Ssam 		IF_DROP(inq);
392*29649Ssam 		m_freem(m);
393*29649Ssam 		return(0);
394*29649Ssam 	}
395*29649Ssam 	s = splimp();
396*29649Ssam 	IF_ENQUEUE(inq, m);
397*29649Ssam 	splx(s);
398*29649Ssam badinput:
399*29649Ssam 	return(0);         /* sanity */
400*29649Ssam }
401*29649Ssam 
402*29649Ssam /*
403*29649Ssam  * Ethernet output routine. (called by user)
404*29649Ssam  * Encapsulate a packet of type family for the local net.
405*29649Ssam  * Use trailer local net encapsulation if enough data in first
406*29649Ssam  * packet leaves a multiple of 512 bytes of data in remainder.
407*29649Ssam  * If destination is this address or broadcast, send packet to
408*29649Ssam  * loop device to kludge around the fact that 3com interfaces can't
409*29649Ssam  * talk to themselves.
410*29649Ssam  */
411*29649Ssam 
412*29649Ssam enpoutput(ifp, m0, dst)
413*29649Ssam struct ifnet *ifp;
414*29649Ssam struct mbuf *m0;
415*29649Ssam struct sockaddr *dst;
416*29649Ssam {
417*29649Ssam 	int type, s, error;
418*29649Ssam 	struct ether_addr edst;
419*29649Ssam 	struct in_addr idst;
420*29649Ssam 
421*29649Ssam 	register struct enp_softc *es = &enp_softc[ifp->if_unit];
422*29649Ssam 	register struct mbuf *m = m0;
423*29649Ssam 	register struct ether_header *enp;
424*29649Ssam 	register int off, i;
425*29649Ssam 
426*29649Ssam 	struct mbuf *mcopy = (struct mbuf *) 0;         /* Null */
427*29649Ssam 	int unit = ifp->if_unit;
428*29649Ssam 
429*29649Ssam 	switch( dst->sa_family )
430*29649Ssam 	{
431*29649Ssam #ifdef INET
432*29649Ssam 	case AF_INET:
433*29649Ssam 		idst = ((struct sockaddr_in *)dst)->sin_addr;
434*29649Ssam 
435*29649Ssam 		/* translate internet to ethernet address */
436*29649Ssam 
437*29649Ssam 		switch(arpresolve(&es->es_ac, m, &idst, &edst)) {
438*29649Ssam 
439*29649Ssam 		   	case ARPRESOLVE_WILLSEND:
440*29649Ssam 				return (0);	/* if not yet resolved */
441*29649Ssam 		   	case ARPRESOLVE_BROADCAST:
442*29649Ssam 				mcopy = m_copy(m, 0, (int)M_COPYALL);
443*29649Ssam 				if (mcopy)
444*29649Ssam 					looutput(&loif, mcopy, dst);
445*29649Ssam 
446*29649Ssam 				/* falls through ... */
447*29649Ssam 		   	case ARPRESOLVE_OK:
448*29649Ssam 				break;
449*29649Ssam 		}
450*29649Ssam 		off = ((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
451*29649Ssam 		if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
452*29649Ssam 			if (off > 0 && (off & 0x1ff) == 0 &&
453*29649Ssam 			    m->m_off >= MMINOFF + 2 * sizeof (u_short))
454*29649Ssam 			{
455*29649Ssam 				type = ETHERPUP_TRAIL + (off>>9);
456*29649Ssam 				m->m_off -= 2 * sizeof (u_short);
457*29649Ssam 				m->m_len += 2 * sizeof (u_short);
458*29649Ssam 				*mtod(m, u_short *) = ETHERPUP_IPTYPE;
459*29649Ssam 				*(mtod(m, u_short *) + 1) = m->m_len;
460*29649Ssam 				goto gottrailertype;
461*29649Ssam 			}
462*29649Ssam 
463*29649Ssam 		type = ETHERPUP_IPTYPE;
464*29649Ssam 		off = 0;
465*29649Ssam 		goto gottype;
466*29649Ssam #endif
467*29649Ssam 
468*29649Ssam #ifdef notdef
469*29649Ssam 	case AF_RAW:
470*29649Ssam 		enp = mtod(m, struct ether_header *);
471*29649Ssam 		if (m->m_len < sizeof *enp)
472*29649Ssam 		{
473*29649Ssam 			error = EMSGSIZE;
474*29649Ssam 			goto bad;
475*29649Ssam 		}
476*29649Ssam 		goto gotheader;
477*29649Ssam #endif
478*29649Ssam 
479*29649Ssam 	case AF_UNSPEC:
480*29649Ssam 		enp = (struct ether_header *)dst->sa_data;
481*29649Ssam 		bcopy( enp->ether_dhost, &edst, sizeof(edst));
482*29649Ssam 		type = enp->ether_type;
483*29649Ssam 		goto gottype;
484*29649Ssam 
485*29649Ssam 	default:
486*29649Ssam 		if (printerror)
487*29649Ssam 		    printf("enp%d: can't handle af%d\n", unit,dst->sa_family);
488*29649Ssam 		error = EAFNOSUPPORT;
489*29649Ssam 		goto bad;
490*29649Ssam 	}
491*29649Ssam 
492*29649Ssam gottrailertype:
493*29649Ssam 	/*
494*29649Ssam 	 * Packet to be sent as trailer: move first packet
495*29649Ssam 	 * (control information) to end of chain.
496*29649Ssam 	 */
497*29649Ssam 	while (m->m_next)
498*29649Ssam 		m = m->m_next;
499*29649Ssam 	m->m_next = m0;
500*29649Ssam 	m = m0->m_next;
501*29649Ssam 	m0->m_next = 0;
502*29649Ssam 	m0 = m;
503*29649Ssam 
504*29649Ssam gottype:
505*29649Ssam 	/*
506*29649Ssam          * Add local net header.  If no space in first mbuf,
507*29649Ssam          * allocate another.
508*29649Ssam          */
509*29649Ssam 	if (m->m_off > MMAXOFF ||
510*29649Ssam 	    MMINOFF + SIZEOF_ETHEADER > m->m_off)
511*29649Ssam 	{
512*29649Ssam 		m = m_get(M_DONTWAIT, MT_HEADER);
513*29649Ssam 		if (m == 0)
514*29649Ssam 		{
515*29649Ssam 			enperr[unit].h_nobuffer++; /* host runs out of buf */
516*29649Ssam 			error = ENOBUFS;
517*29649Ssam 			goto bad;
518*29649Ssam 		}
519*29649Ssam 		m->m_next = m0;
520*29649Ssam 		m->m_off = MMINOFF;
521*29649Ssam 		m->m_len = SIZEOF_ETHEADER;
522*29649Ssam 	}
523*29649Ssam 	else
524*29649Ssam 	{
525*29649Ssam 		m->m_off -= SIZEOF_ETHEADER;
526*29649Ssam 		m->m_len += SIZEOF_ETHEADER;
527*29649Ssam 	}
528*29649Ssam 	enp = mtod(m, struct ether_header *);
529*29649Ssam 	bcopy( &edst, enp->ether_dhost, sizeof(enp->ether_dhost) );
530*29649Ssam 	enp->ether_type = type;
531*29649Ssam gotheader:
532*29649Ssam 	bcopy( es->es_enaddr, enp->ether_shost, sizeof(enp->ether_shost));
533*29649Ssam 
534*29649Ssam 	/*
535*29649Ssam 	 * Queue message on interface if possible
536*29649Ssam 	 */
537*29649Ssam 
538*29649Ssam 	s = splimp();
539*29649Ssam 	if( enpput( unit,m ) )
540*29649Ssam 	{
541*29649Ssam 		error = ENOBUFS;
542*29649Ssam 		enperr[unit].c_nobuffer++; /* controller runs out of buf */
543*29649Ssam 		goto qfull;
544*29649Ssam 	}
545*29649Ssam 	splx( s );
546*29649Ssam 	es->es_if.if_opackets++;
547*29649Ssam 	return(0);
548*29649Ssam qfull:
549*29649Ssam 	splx( s );
550*29649Ssam 	m0 = m;
551*29649Ssam bad:
552*29649Ssam 	m_freem(m0);
553*29649Ssam 	return(error);
554*29649Ssam }
555*29649Ssam 
556*29649Ssam /*
557*29649Ssam  * Routine to copy from mbuf chain to transmitter
558*29649Ssam  * buffer in Multibus memory.
559*29649Ssam  */
560*29649Ssam 
561*29649Ssam enpput( unit,m )
562*29649Ssam int unit;
563*29649Ssam struct mbuf *m;
564*29649Ssam {
565*29649Ssam 	register BCB *bcbp;
566*29649Ssam 	register ENPDEVICE *addr;
567*29649Ssam 	register struct mbuf *mp;
568*29649Ssam 	register u_char *bp;
569*29649Ssam 	int	 ctr = 0;
570*29649Ssam 	long int	v;
571*29649Ssam 	register short *vp = (short *)&v,
572*29649Ssam 			*sp;
573*29649Ssam 
574*29649Ssam 	addr = (ENPDEVICE *)enpinfo[ unit ]->ui_addr;
575*29649Ssam 
576*29649Ssam 	if ( ringempty( &addr->enp_hostfree ) )
577*29649Ssam 			return( 1 );
578*29649Ssam 
579*29649Ssam 	bcbp = (BCB *)ringget( &addr->enp_hostfree );
580*29649Ssam 	bcbp->b_len = 0;
581*29649Ssam #ifdef TAHOE
582*29649Ssam 	sp = (short *)&bcbp->b_addr;
583*29649Ssam 	*vp = *sp; vp[1] = sp[1];
584*29649Ssam 	bp = (u_char *)v;
585*29649Ssam #else
586*29649Ssam 	bp = (u_char *)bcbp->b_addr;
587*29649Ssam #endif TAHOE
588*29649Ssam 	for (mp = m; mp; mp = mp->m_next)
589*29649Ssam 	{
590*29649Ssam 		register unsigned len;
591*29649Ssam 		u_char *mcp;
592*29649Ssam 
593*29649Ssam 		len = mp->m_len;
594*29649Ssam 		if( len == 0 )
595*29649Ssam 			continue;
596*29649Ssam 		mcp = mtod( mp,u_char * );
597*29649Ssam 		enpcopy( mcp,bp,len );
598*29649Ssam 		bp += len;
599*29649Ssam 		bcbp->b_len += len;
600*29649Ssam 	}
601*29649Ssam 	bcbp->b_len = max( MINPKTSIZE,bcbp->b_len );
602*29649Ssam 	bcbp->b_reserved = 0;
603*29649Ssam 	if ( ringput( &addr->enp_toenp,bcbp ) == 1 ) {
604*29649Ssam 		host_intr++;
605*29649Ssam 		INTR_ENP( addr );
606*29649Ssam 	}
607*29649Ssam 	m_freem(m);
608*29649Ssam 	return( 0 );
609*29649Ssam }
610*29649Ssam 
611*29649Ssam /*
612*29649Ssam  * Routine to copy from Multibus memory into mbufs.
613*29649Ssam  *
614*29649Ssam  * Warning: This makes the fairly safe assumption that
615*29649Ssam  * mbufs have even lengths.
616*29649Ssam  */
617*29649Ssam struct mbuf *
618*29649Ssam enpget( bcbp, totlen, off0 )
619*29649Ssam register BCB *bcbp;
620*29649Ssam int totlen, off0;
621*29649Ssam {
622*29649Ssam 	register struct mbuf *m;
623*29649Ssam 	register int off = off0;
624*29649Ssam 	register unsigned char *cp;
625*29649Ssam 	long int	v;
626*29649Ssam 	register short *vp = (short *)&v,
627*29649Ssam 			*sp;
628*29649Ssam 
629*29649Ssam 	int len;
630*29649Ssam 	struct mbuf *top = 0;
631*29649Ssam 	struct mbuf **mp = &top;
632*29649Ssam 
633*29649Ssam #ifdef TAHOE
634*29649Ssam 	sp = (short *)&bcbp->b_addr;
635*29649Ssam 	*vp = *sp; vp[1] = sp[1];
636*29649Ssam 	cp = (unsigned char *)v + SIZEOF_ETHEADER;
637*29649Ssam #else
638*29649Ssam 	cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
639*29649Ssam #endif TAHOE
640*29649Ssam 
641*29649Ssam 	while( totlen > 0 )
642*29649Ssam 	{
643*29649Ssam 		u_char *mcp;
644*29649Ssam 
645*29649Ssam 		MGET(m, M_DONTWAIT, MT_DATA);
646*29649Ssam 		if (m == 0)
647*29649Ssam 			goto bad;
648*29649Ssam 		if( off )
649*29649Ssam 		{
650*29649Ssam 			len = totlen - off;
651*29649Ssam #ifdef TAHOE
652*29649Ssam 			sp = (short *)&bcbp->b_addr;
653*29649Ssam 			*vp = *sp; vp[1] = sp[1];
654*29649Ssam 			cp = (unsigned char *)v + SIZEOF_ETHEADER
655*29649Ssam 				+ off;
656*29649Ssam #else
657*29649Ssam 			cp = (unsigned char *)bcbp->b_addr +
658*29649Ssam 				SIZEOF_ETHEADER + off;
659*29649Ssam #endif TAHOE
660*29649Ssam 		}
661*29649Ssam 		else
662*29649Ssam 			len = totlen;
663*29649Ssam 
664*29649Ssam 
665*29649Ssam 		if (len >= CLBYTES) {
666*29649Ssam 			struct mbuf *p;
667*29649Ssam 
668*29649Ssam 			MCLGET(p, 1);
669*29649Ssam 			if (p != 0) {
670*29649Ssam 				m->m_len = len = CLBYTES;
671*29649Ssam 				m->m_off = (int)p - (int)m;
672*29649Ssam 			} else  {
673*29649Ssam 				m->m_len = len = MIN(MLEN, len);
674*29649Ssam 				m->m_off = MMINOFF;
675*29649Ssam 				}
676*29649Ssam 		} else  {
677*29649Ssam 			m->m_len = len = MIN(MLEN, len);
678*29649Ssam 			m->m_off = MMINOFF;
679*29649Ssam 		}
680*29649Ssam 
681*29649Ssam 		mcp = mtod(m, u_char *);
682*29649Ssam 		enpcopy(cp, mcp, len);
683*29649Ssam 		cp += len;
684*29649Ssam 		*mp = m;
685*29649Ssam 		mp = &m->m_next;
686*29649Ssam 		if (off == 0)
687*29649Ssam 		{
688*29649Ssam 			totlen -= len;
689*29649Ssam 			continue;
690*29649Ssam 		}
691*29649Ssam 		off += len;
692*29649Ssam 		if (off == totlen)
693*29649Ssam 		{
694*29649Ssam #ifdef TAHOE
695*29649Ssam 			sp = (short *)&bcbp->b_addr;
696*29649Ssam 			*vp = *sp; vp[1] = sp[1];
697*29649Ssam 			cp = (unsigned char *)v + SIZEOF_ETHEADER;
698*29649Ssam #else
699*29649Ssam 			cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER;
700*29649Ssam #endif TAHOE
701*29649Ssam 			off = 0;
702*29649Ssam 			totlen = off0;
703*29649Ssam 		}
704*29649Ssam 	}
705*29649Ssam 	return (top);
706*29649Ssam bad:
707*29649Ssam 	m_freem(top);
708*29649Ssam 	return (0);
709*29649Ssam }
710*29649Ssam 
711*29649Ssam /*
712*29649Ssam  * Process an ioctl request.
713*29649Ssam  *    this can be called via the "socket" route for SIOCSIFADDR or
714*29649Ssam  *	by the cdev/inode route for SIOCSIFCCFWR/RD
715*29649Ssam  *
716*29649Ssam  */
717*29649Ssam 
718*29649Ssam enpioctl(ifp, cmd, data)
719*29649Ssam register struct ifnet *ifp;
720*29649Ssam int cmd;
721*29649Ssam caddr_t data;
722*29649Ssam {
723*29649Ssam 	register int	unit = ifp->if_unit;
724*29649Ssam 	register struct vba_device *md;
725*29649Ssam 	int s, error = 0;
726*29649Ssam 	struct sockaddr_in	*sin;
727*29649Ssam 	struct sockaddr		*sa;
728*29649Ssam 	struct enp_softc	*es = &enp_softc[ifp->if_unit];
729*29649Ssam 	ENPDEVICE		*addr;
730*29649Ssam 	struct config_entry	*cf;
731*29649Ssam 	struct ifreq *ifr	= (struct ifreq *)data;
732*29649Ssam 	struct sockaddr_in	*et_addr;
733*29649Ssam 	int code, i;
734*29649Ssam 
735*29649Ssam 
736*29649Ssam 	if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0)
737*29649Ssam 		return(ENODEV);
738*29649Ssam 
739*29649Ssam 	switch (cmd) {
740*29649Ssam 
741*29649Ssam 	case SIOCSIFADDR:
742*29649Ssam 		s = splimp();
743*29649Ssam 		sa = (struct sockaddr *)&ifr->ifr_addr;
744*29649Ssam 		if (sa->sa_family == AF_UNSPEC ) {
745*29649Ssam 			if (sa->sa_data[0] & 1){ /*broad or multi-cast*/
746*29649Ssam 				splx( s );
747*29649Ssam 				return( EINVAL );
748*29649Ssam 			}
749*29649Ssam 			bcopy(sa->sa_data,es->es_enaddr,sizeof(es->es_enaddr));
750*29649Ssam 			enpinit( ifp->if_unit);
751*29649Ssam 			break;
752*29649Ssam 		}
753*29649Ssam 		sin = (struct sockaddr_in *)&ifr->ifr_addr;
754*29649Ssam 		if (sin->sin_family != AF_INET){
755*29649Ssam 			splx( s );
756*29649Ssam 			return( EINVAL );
757*29649Ssam 		}
758*29649Ssam 		if (ifp->if_flags & IFF_RUNNING)
759*29649Ssam 			if_rtinit(ifp, -1);     /* delete previous route */
760*29649Ssam 		enpsetaddr(ifp, sin);
761*29649Ssam 		enpinit(ifp->if_unit);
762*29649Ssam 		enpgetaddr( ifp->if_unit );
763*29649Ssam 		splx(s);
764*29649Ssam 		break;
765*29649Ssam 
766*29649Ssam 
767*29649Ssam 	case SIOCSETETADDR:	/* Set Ethernet station address */
768*29649Ssam 		s = splimp();
769*29649Ssam 		ifp->if_flags &= (~IFF_RUNNING | IFF_UP);
770*29649Ssam 		et_addr = (struct sockaddr_in *)&ifr->ifr_addr;
771*29649Ssam 		addr = (ENPDEVICE *)enpinfo[ifp->if_unit]->ui_addr;
772*29649Ssam 
773*29649Ssam 		/* Set station address and reset controller board */
774*29649Ssam 		{
775*29649Ssam 		u_char	*to = &addr->enp_addr.e_baseaddr.ea_addr[0];
776*29649Ssam 		char	*from = &et_addr->sin_zero[2];
777*29649Ssam 		int	i;
778*29649Ssam 
779*29649Ssam 		for (i = 0 ; i < ETHADDR_SIZE; i++)
780*29649Ssam 			*to++ = (u_char) (~(*from++ & 0xff));
781*29649Ssam 		}
782*29649Ssam 		enpcopy(&addr->enp_addr.e_listsize, &code, sizeof(code));
783*29649Ssam 		code |= E_ADDR_SUPP;
784*29649Ssam 		enpcopy(&code, &addr->enp_addr.e_listsize, sizeof(code));
785*29649Ssam 		enpreset(ifp->if_unit);		/* Re-initialize */
786*29649Ssam 		enpgetaddr(ifp->if_unit);
787*29649Ssam 		splx(s);
788*29649Ssam 		break;
789*29649Ssam 
790*29649Ssam 	case SIOCGETETADDR:	/* Get Foreign Hosts' Ethernet addresses */
791*29649Ssam 		arpwhohas(&es->es_ac, (struct in_addr *)ifr->ifr_data);
792*29649Ssam 		break;
793*29649Ssam 
794*29649Ssam 	default:
795*29649Ssam 		error = EINVAL;
796*29649Ssam 	}
797*29649Ssam 	return(error);
798*29649Ssam }
799*29649Ssam 
800*29649Ssam enpsetaddr(ifp, sin)
801*29649Ssam register struct ifnet *ifp;
802*29649Ssam register struct sockaddr_in *sin;
803*29649Ssam {
804*29649Ssam 
805*29649Ssam 	ifp->if_addr = *(struct sockaddr *)sin;
806*29649Ssam 	ifp->if_net = in_netof(sin->sin_addr);
807*29649Ssam 	ifp->if_host[0] = in_lnaof(sin->sin_addr);
808*29649Ssam 	sin = (struct sockaddr_in *)&ifp->if_broadaddr;
809*29649Ssam 	sin->sin_family = AF_INET;
810*29649Ssam 	sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
811*29649Ssam 	ifp->if_flags |= IFF_BROADCAST;
812*29649Ssam }
813*29649Ssam 
814*29649Ssam 
815*29649Ssam /*
816*29649Ssam  * Get the ethernet addr, store it and print it
817*29649Ssam  * Read the ethernet address off the board, one byte at a time.
818*29649Ssam  *	put it in enp_softc
819*29649Ssam  */
820*29649Ssam 
821*29649Ssam 
822*29649Ssam enpgetaddr( unit )
823*29649Ssam int unit;
824*29649Ssam {
825*29649Ssam 	register struct enp_softc	*es = &enp_softc[unit];
826*29649Ssam 	register ENPDEVICE *addr =(ENPDEVICE *)enpinfo[unit]->ui_addr;
827*29649Ssam 	int i;
828*29649Ssam 
829*29649Ssam #ifdef TAHOE
830*29649Ssam 	enpcopy(&addr->enp_addr.e_baseaddr, &es->es_boardaddr, sizeof(es->es_boardaddr));
831*29649Ssam #else
832*29649Ssam 	es->es_boardaddr = addr->enp_addr.e_baseaddr;
833*29649Ssam #endif TAHOE
834*29649Ssam 	bcopy(&es->es_boardaddr, es->es_enaddr, ETHADDR_SIZE);
835*29649Ssam 	return( 1 );
836*29649Ssam }
837*29649Ssam 
838*29649Ssam /*
839*29649Ssam  * enpram device
840*29649Ssam  *
841*29649Ssam  */
842*29649Ssam 
843*29649Ssam enpr_open( dev )
844*29649Ssam {
845*29649Ssam 	register int	unit = minor(dev);
846*29649Ssam 	register struct vba_device *md;
847*29649Ssam 	register ENPDEVICE	*addr;
848*29649Ssam 
849*29649Ssam 	if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
850*29649Ssam 	    (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
851*29649Ssam 		return(ENODEV);
852*29649Ssam 	if (addr->enp_state != S_ENPRESET)
853*29649Ssam 		return(EACCES);  /* enp is not in reset state, don't open  */
854*29649Ssam 	if ( !enpismapped[unit] ) {
855*29649Ssam 		ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE);
856*29649Ssam 		++enpismapped[unit];
857*29649Ssam 	}
858*29649Ssam 	enpram[unit] = ENP_OPEN;
859*29649Ssam 	return( 0 );
860*29649Ssam }
861*29649Ssam 
862*29649Ssam enpr_close(dev)
863*29649Ssam {
864*29649Ssam 	enpram[minor(dev)] = ENP_CLOSE;
865*29649Ssam 	return( 0 );
866*29649Ssam }
867*29649Ssam 
868*29649Ssam enpr_read( dev,uio )
869*29649Ssam int dev;
870*29649Ssam register struct uio *uio;
871*29649Ssam {
872*29649Ssam 	register ENPDEVICE *addr;
873*29649Ssam 	register struct iovec *iov;
874*29649Ssam 	register r=0;
875*29649Ssam 
876*29649Ssam 	if (enpram[minor(dev)] != ENP_OPEN)
877*29649Ssam 		return(EACCES);
878*29649Ssam 	if ( uio->uio_offset > RAM_SIZE )
879*29649Ssam 		return( ENODEV );
880*29649Ssam 	if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
881*29649Ssam 		iov->iov_len = RAM_SIZE - uio->uio_offset;
882*29649Ssam 	addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
883*29649Ssam 	iov  = uio->uio_iov;
884*29649Ssam 
885*29649Ssam 	if( r = enpcopyout( &addr->enp_ram[ uio->uio_offset ], iov->iov_base,
886*29649Ssam 			 iov->iov_len ) )
887*29649Ssam 		 return( r );
888*29649Ssam 
889*29649Ssam 	uio->uio_resid -= iov->iov_len;
890*29649Ssam 	iov->iov_len = 0;
891*29649Ssam 
892*29649Ssam 	return( 0 );
893*29649Ssam }
894*29649Ssam 
895*29649Ssam enpr_write( dev,uio )
896*29649Ssam int dev;
897*29649Ssam register struct uio *uio;
898*29649Ssam {
899*29649Ssam 	register ENPDEVICE *addr;
900*29649Ssam 	register struct iovec *iov;
901*29649Ssam 	register r=0;
902*29649Ssam 
903*29649Ssam 	if (enpram[minor(dev)] != ENP_OPEN)
904*29649Ssam 		return(EACCES);
905*29649Ssam 	addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr;
906*29649Ssam 	iov  = uio->uio_iov;
907*29649Ssam 
908*29649Ssam 	if ( uio->uio_offset > RAM_SIZE )
909*29649Ssam 		return( ENODEV );
910*29649Ssam 	if ( uio->uio_offset + iov->iov_len > RAM_SIZE )
911*29649Ssam 		iov->iov_len = RAM_SIZE - uio->uio_offset;
912*29649Ssam 	if( r = enpcopyin( iov->iov_base, &addr->enp_ram[ uio->uio_offset ],
913*29649Ssam 			iov->iov_len ) )
914*29649Ssam 		return( r );
915*29649Ssam 
916*29649Ssam 	uio->uio_resid -= iov->iov_len;
917*29649Ssam 	iov->iov_len = 0;
918*29649Ssam 
919*29649Ssam 	return( 0 );
920*29649Ssam }
921*29649Ssam 
922*29649Ssam enpr_ioctl( dev,cmd,arg,fflag )
923*29649Ssam dev_t dev;
924*29649Ssam caddr_t *arg;
925*29649Ssam {
926*29649Ssam 	register ENPDEVICE *addr;
927*29649Ssam 	long int	v;
928*29649Ssam 	register short	*vp = (short *)&v, *sp;
929*29649Ssam 	register unit = minor(dev);
930*29649Ssam 	register struct vba_device *md;
931*29649Ssam 
932*29649Ssam 	if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 ||
933*29649Ssam 	    (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0)
934*29649Ssam 		return(ENODEV);
935*29649Ssam 	switch( cmd )
936*29649Ssam 	{
937*29649Ssam 		case ENPIOGO:
938*29649Ssam /* not needed if prom based version */
939*29649Ssam #ifdef TAHOE
940*29649Ssam 			sp = (short *)&addr->enp_base;
941*29649Ssam 			v = (int)addr;
942*29649Ssam 			*sp = *vp; sp[1] = vp[1];
943*29649Ssam #else
944*29649Ssam 			addr->enp_base = (int)addr;
945*29649Ssam #endif TAHOE
946*29649Ssam 			addr->enp_intrvec = intvec[ unit ];
947*29649Ssam 			ENP_GO( addr, ENPSTART );
948*29649Ssam 			DELAY( 200000 );
949*29649Ssam 			enpattach( enpinfo[ unit ] );
950*29649Ssam 			enpinit( unit );
951*29649Ssam 			addr->enp_state = S_ENPRUN;  /* it is running now */
952*29649Ssam /* end of not needed */
953*29649Ssam 
954*29649Ssam 			break;
955*29649Ssam 
956*29649Ssam 		case ENPIORESET:
957*29649Ssam 			RESET_ENP( addr );
958*29649Ssam 			addr->enp_state = S_ENPRESET;  /* it is reset now */
959*29649Ssam 			DELAY( 100000 );
960*29649Ssam 			break;
961*29649Ssam 	}
962*29649Ssam 	return( 0 );
963*29649Ssam }
964*29649Ssam 
965*29649Ssam /*
966*29649Ssam  * routines to synchronize enp and host
967*29649Ssam  */
968*29649Ssam 
969*29649Ssam static
970*29649Ssam ringinit( rp,size )
971*29649Ssam register RING *rp;
972*29649Ssam {
973*29649Ssam 	register int	i;
974*29649Ssam 	register short *sp;
975*29649Ssam 
976*29649Ssam 	rp->r_rdidx = rp->r_wrtidx = 0;
977*29649Ssam 	rp->r_size = size;
978*29649Ssam }
979*29649Ssam 
980*29649Ssam static
981*29649Ssam ringempty( rp )
982*29649Ssam register RING *rp;
983*29649Ssam {
984*29649Ssam 	return( rp->r_rdidx == rp->r_wrtidx );
985*29649Ssam }
986*29649Ssam 
987*29649Ssam static
988*29649Ssam ringfull( rp )
989*29649Ssam register RING *rp;
990*29649Ssam {
991*29649Ssam 	register short idx;
992*29649Ssam 
993*29649Ssam 	idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
994*29649Ssam 	return( idx == rp->r_rdidx );
995*29649Ssam }
996*29649Ssam 
997*29649Ssam static
998*29649Ssam ringput( rp,v )
999*29649Ssam register RING *rp;
1000*29649Ssam {
1001*29649Ssam 	register int idx;
1002*29649Ssam 	register short *vp = (short *)&v,
1003*29649Ssam 		       *sp;
1004*29649Ssam 
1005*29649Ssam 	idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
1006*29649Ssam 	if( idx != rp->r_rdidx )
1007*29649Ssam 	{
1008*29649Ssam #ifdef TAHOE
1009*29649Ssam 		sp = (short *)&rp->r_slot[ rp->r_wrtidx ];
1010*29649Ssam 		*sp = *vp; sp[1] = vp[1];
1011*29649Ssam #else
1012*29649Ssam 		rp->r_slot[ rp->r_wrtidx ] = v;
1013*29649Ssam #endif TAHOE
1014*29649Ssam 		rp->r_wrtidx = idx;
1015*29649Ssam 		if( (idx -= rp->r_rdidx) < 0 )
1016*29649Ssam 			idx += rp->r_size;
1017*29649Ssam 		return( idx );			/* num ring entries */
1018*29649Ssam 	}
1019*29649Ssam 	return( 0 );
1020*29649Ssam }
1021*29649Ssam 
1022*29649Ssam static
1023*29649Ssam ringget( rp )
1024*29649Ssam register RING *rp;
1025*29649Ssam {
1026*29649Ssam 	register int i = 0;
1027*29649Ssam 	long int v;
1028*29649Ssam 	register short *vp = (short *)&v,
1029*29649Ssam 		       *sp;
1030*29649Ssam 
1031*29649Ssam 	if( rp->r_rdidx != rp->r_wrtidx )
1032*29649Ssam 	{
1033*29649Ssam #ifdef TAHOE
1034*29649Ssam 		sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1035*29649Ssam 		*vp = *sp; vp[1] = sp[1];
1036*29649Ssam 		i = v;
1037*29649Ssam #else
1038*29649Ssam 		i = rp->r_slot[ rp->r_rdidx ];
1039*29649Ssam #endif TAHOE
1040*29649Ssam 		rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
1041*29649Ssam 	}
1042*29649Ssam 	return( i );
1043*29649Ssam }
1044*29649Ssam 
1045*29649Ssam #ifdef notdef
1046*29649Ssam struct mbuf *
1047*29649Ssam m_tofree( rp )
1048*29649Ssam register RING *rp;
1049*29649Ssam {
1050*29649Ssam 	long int v = 0;
1051*29649Ssam 	register short *vp = (short *)&v,
1052*29649Ssam 		       *sp;
1053*29649Ssam 
1054*29649Ssam 	if( rp->r_rdidx != rp->r_wrtidx )
1055*29649Ssam 	{
1056*29649Ssam #ifdef TAHOE
1057*29649Ssam 		sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1058*29649Ssam 		*vp = *sp; vp[1] = sp[1];
1059*29649Ssam 		/* *sp = 0xffff; sp[1] = 0xffff; */
1060*29649Ssam #else
1061*29649Ssam 		v = rp->r_slot[ rp->r_rdidx ];
1062*29649Ssam #endif TAHOE
1063*29649Ssam 	  	rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
1064*29649Ssam 	}
1065*29649Ssam 	return( (struct mbuf *)v );
1066*29649Ssam }
1067*29649Ssam #endif
1068*29649Ssam static
1069*29649Ssam fir( rp )
1070*29649Ssam register RING *rp;
1071*29649Ssam {
1072*29649Ssam 	long int v;
1073*29649Ssam 	register short *vp = (short *)&v,
1074*29649Ssam 		       *sp;
1075*29649Ssam 
1076*29649Ssam 	if( rp->r_rdidx != rp->r_wrtidx )
1077*29649Ssam #ifdef TAHOE
1078*29649Ssam 	{
1079*29649Ssam 		sp = (short *)&rp->r_slot[ rp->r_rdidx ];
1080*29649Ssam 		*vp = *sp; vp[1] = sp[1];
1081*29649Ssam 		return( v );
1082*29649Ssam 	}
1083*29649Ssam #else
1084*29649Ssam 		return( rp->r_slot[ rp->r_rdidx ] );
1085*29649Ssam #endif TAHOE
1086*29649Ssam 	else
1087*29649Ssam 		return( 0 );
1088*29649Ssam }
1089*29649Ssam 
1090*29649Ssam 
1091*29649Ssam static
1092*29649Ssam prtbytes( addr )
1093*29649Ssam register char *addr;
1094*29649Ssam {
1095*29649Ssam 	register int i;
1096*29649Ssam 
1097*29649Ssam 	for( i = 0; i < 12; i++ )
1098*29649Ssam 	{
1099*29649Ssam 		printf("%X ",*addr&0377);
1100*29649Ssam 		addr++;
1101*29649Ssam 	}
1102*29649Ssam 	printf("\n");
1103*29649Ssam }
1104*29649Ssam 
1105*29649Ssam static
1106*29649Ssam enpcopy(from, to, cnt)
1107*29649Ssam register char *from, *to;
1108*29649Ssam register cnt;
1109*29649Ssam {
1110*29649Ssam 	register c;
1111*29649Ssam 	register short *f, *t;
1112*29649Ssam 
1113*29649Ssam 	if (((int)from & 01) && ((int)to & 01)) {
1114*29649Ssam 					/* source & dest at odd addresses */
1115*29649Ssam 		*to++ = *from++;
1116*29649Ssam 		--cnt;
1117*29649Ssam 	}
1118*29649Ssam 	if (cnt > 1 && (((int)to & 01)==0) && (((int)from & 01)==0)) {
1119*29649Ssam 		t = (short *) to;
1120*29649Ssam 		f = (short *) from;
1121*29649Ssam 		for( c = cnt>>1; c; --c)	/* even address copy */
1122*29649Ssam 			*t++ = *f++;
1123*29649Ssam 		cnt &= 1;
1124*29649Ssam 		if ( cnt ) {			/* odd len */
1125*29649Ssam 			from = (char *) f;
1126*29649Ssam 			to   = (char *) t;
1127*29649Ssam 			*to = *from;
1128*29649Ssam 		}
1129*29649Ssam 	}
1130*29649Ssam 	while (cnt-- > 0)	/* one of the address(es) must be odd */
1131*29649Ssam 		*to++ = *from++;
1132*29649Ssam 
1133*29649Ssam }
1134*29649Ssam 
1135*29649Ssam static
1136*29649Ssam enpcopyin(userv, kernv, cnt)
1137*29649Ssam {
1138*29649Ssam 
1139*29649Ssam 	if (useracc(userv, cnt, 1)) {
1140*29649Ssam 		enpcopy( userv, kernv, cnt );
1141*29649Ssam 		return( 0 );
1142*29649Ssam 	}
1143*29649Ssam 	else	return( EFAULT );
1144*29649Ssam }
1145*29649Ssam 
1146*29649Ssam 
1147*29649Ssam static
1148*29649Ssam enpcopyout(kernv, userv, cnt)
1149*29649Ssam {
1150*29649Ssam 
1151*29649Ssam 	if (useracc(userv, cnt, 0)) {
1152*29649Ssam 		enpcopy( kernv, userv, cnt );
1153*29649Ssam 		return( 0 );
1154*29649Ssam 	}
1155*29649Ssam 	else	return( EFAULT );
1156*29649Ssam }
1157*29649Ssam #endif
1158