xref: /csrg-svn/sys/tahoe/if/if_enp.c (revision 35383)
134508Skarels /*
234508Skarels  * Copyright (c) 1988 Regents of the University of California.
334508Skarels  * All rights reserved.
434508Skarels  *
5*35383Skarels  * This code is derived from software contributed to Berkeley by
6*35383Skarels  * Computer Consoles Inc.
7*35383Skarels  *
834508Skarels  * Redistribution and use in source and binary forms are permitted
934864Sbostic  * provided that the above copyright notice and this paragraph are
1034864Sbostic  * duplicated in all such forms and that any documentation,
1134864Sbostic  * advertising materials, and other materials related to such
1234864Sbostic  * distribution and use acknowledge that the software was developed
1334864Sbostic  * by the University of California, Berkeley.  The name of the
1434864Sbostic  * University may not be used to endorse or promote products derived
1534864Sbostic  * from this software without specific prior written permission.
1634864Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1734864Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1834864Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1934508Skarels  *
20*35383Skarels  *	@(#)if_enp.c	7.3 (Berkeley) 08/19/88
2134508Skarels  */
2229649Ssam 
2329649Ssam #include "enp.h"
2429649Ssam #if NENP > 0
2529649Ssam /*
2630986Ssam  * CMC ENP-20 Ethernet Controller.
2729649Ssam  */
2829649Ssam #include "param.h"
2929649Ssam #include "systm.h"
3029649Ssam #include "mbuf.h"
3129649Ssam #include "buf.h"
3229649Ssam #include "protosw.h"
3329649Ssam #include "socket.h"
3429649Ssam #include "vmmac.h"
3530230Ssam #include "ioctl.h"
3629649Ssam #include "errno.h"
3730230Ssam #include "vmparam.h"
3830230Ssam #include "syslog.h"
3929649Ssam #include "uio.h"
4029649Ssam 
4129649Ssam #include "../net/if.h"
4229649Ssam #include "../net/netisr.h"
4329649Ssam #include "../net/route.h"
4430230Ssam #ifdef INET
4529649Ssam #include "../netinet/in.h"
4629649Ssam #include "../netinet/in_systm.h"
4730230Ssam #include "../netinet/in_var.h"
4829649Ssam #include "../netinet/ip.h"
4929649Ssam #include "../netinet/ip_var.h"
5029649Ssam #include "../netinet/if_ether.h"
5130230Ssam #endif
5230230Ssam #ifdef NS
5330230Ssam #include "../netns/ns.h"
5430230Ssam #include "../netns/ns_if.h"
5530230Ssam #endif
5629649Ssam 
5730230Ssam #include "../tahoe/cpu.h"
5830230Ssam #include "../tahoe/pte.h"
5930230Ssam #include "../tahoe/mtpr.h"
6030230Ssam 
6129649Ssam #include "../tahoevba/vbavar.h"
6230230Ssam #include "../tahoeif/if_enpreg.h"
6329649Ssam 
6430230Ssam #define ENPSTART	0xf02000	/* standard enp start addr */
6530230Ssam #define	ENPUNIT(dev)	(minor(dev))	/* for enp ram devices */
6630986Ssam /* macros for dealing with longs in i/o space */
6730986Ssam #define	ENPGETLONG(a)	((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1]))
6830986Ssam #define	ENPSETLONG(a,v) \
6930986Ssam    { register u_short *wp = (u_short *)(a); \
7030986Ssam      wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];}
7129649Ssam 
7229649Ssam int	enpprobe(), enpattach(), enpintr();
7330298Ssam long	enpstd[] = { 0xfff41000, 0xfff61000, 0 };
7430230Ssam struct  vba_device *enpinfo[NENP];
7529649Ssam struct  vba_driver enpdriver =
7630230Ssam     { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 };
7729649Ssam 
78*35383Skarels int	enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart();
7929649Ssam struct  mbuf *enpget();
8029649Ssam 
8129649Ssam /*
8229649Ssam  * Ethernet software status per interface.
8329649Ssam  *
8429649Ssam  * Each interface is referenced by a network interface structure,
8529649Ssam  * es_if, which the routing code uses to locate the interface.
8629649Ssam  * This structure contains the output queue for the interface, its address, ...
8729649Ssam  */
8830230Ssam struct  enp_softc {
8930230Ssam 	struct  arpcom es_ac;           /* common ethernet structures */
9030230Ssam #define es_if		es_ac.ac_if
9130986Ssam #define es_addr	es_ac.ac_enaddr
9230230Ssam 	short	es_ivec;		/* interrupt vector */
9330230Ssam } enp_softc[NENP];
9430230Ssam extern	struct ifnet loif;
9529649Ssam 
9630230Ssam enpprobe(reg, vi)
9730230Ssam 	caddr_t reg;
9830230Ssam 	struct vba_device *vi;
9929649Ssam {
10030230Ssam 	register br, cvec;		/* must be r12, r11 */
10130230Ssam 	register struct enpdevice *addr = (struct enpdevice *)reg;
10230230Ssam 	struct enp_softc *es = &enp_softc[vi->ui_unit];
10329649Ssam 
10430230Ssam #ifdef lint
10530295Ssam 	br = 0; cvec = br; br = cvec;
10630230Ssam 	enpintr(0);
10730230Ssam #endif
10830295Ssam 	if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2))
10930230Ssam 		return (0);
11030230Ssam 	es->es_ivec = --vi->ui_hd->vh_lastiv;
11130230Ssam 	addr->enp_state = S_ENPRESET;		/* reset by VERSAbus reset */
11230230Ssam 	br = 0x14, cvec = es->es_ivec;		/* XXX */
11330230Ssam 	return (sizeof (struct enpdevice));
11429649Ssam }
11529649Ssam 
11629649Ssam /*
11729649Ssam  * Interface exists: make available by filling in network interface
11829649Ssam  * record.  System will initialize the interface when it is ready
11929649Ssam  * to accept packets.
12029649Ssam  */
12130230Ssam enpattach(ui)
12230230Ssam 	register struct vba_device *ui;
12329649Ssam {
12430230Ssam 	struct enp_softc *es = &enp_softc[ui->ui_unit];
12530230Ssam 	register struct ifnet *ifp = &es->es_if;
12629649Ssam 
12730230Ssam 	ifp->if_unit = ui->ui_unit;
12829649Ssam 	ifp->if_name = "enp";
12929649Ssam 	ifp->if_mtu = ETHERMTU;
13029649Ssam 	ifp->if_init = enpinit;
13129649Ssam 	ifp->if_ioctl = enpioctl;
132*35383Skarels 	ifp->if_output = enoutput;
13329649Ssam 	ifp->if_reset = enpreset;
134*35383Skarels 	ifp->if_start = enpstart;
13530230Ssam 	ifp->if_flags = IFF_BROADCAST;
13629649Ssam 	if_attach(ifp);
13729649Ssam }
13829649Ssam 
13929649Ssam /*
14030230Ssam  * Reset of interface after "system" reset.
14129649Ssam  */
14230230Ssam enpreset(unit, vban)
14330230Ssam 	int unit, vban;
14429649Ssam {
14530230Ssam 	register struct vba_device *ui;
14629649Ssam 
14730230Ssam 	if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
14830230Ssam 	    ui->ui_vbanum != vban)
14930230Ssam 		return;
15030230Ssam 	printf(" enp%d", unit);
15129649Ssam 	enpinit(unit);
15229649Ssam }
15329649Ssam 
15429649Ssam /*
15530230Ssam  * Initialization of interface; clear recorded pending operations.
15629649Ssam  */
15730230Ssam enpinit(unit)
15830230Ssam 	int unit;
15929649Ssam {
16030230Ssam 	struct enp_softc *es = &enp_softc[unit];
16130230Ssam 	register struct vba_device *ui = enpinfo[unit];
16230230Ssam 	struct enpdevice *addr;
16330230Ssam 	register struct ifnet *ifp = &es->es_if;
16430230Ssam 	int s;
16529649Ssam 
16630230Ssam 	if (ifp->if_addrlist == (struct ifaddr *)0)
16730230Ssam 		return;
16830230Ssam 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
16930230Ssam 		addr = (struct enpdevice *)ui->ui_addr;
17030230Ssam 		s = splimp();
17130230Ssam 		RESET_ENP(addr);
17230230Ssam 		DELAY(200000);
17330230Ssam 		es->es_if.if_flags |= IFF_RUNNING;
17430230Ssam 		splx(s);
17529649Ssam 	}
17629649Ssam }
17729649Ssam 
17829649Ssam /*
17929649Ssam  * Ethernet interface interrupt.
18029649Ssam  */
18130230Ssam enpintr(unit)
18230230Ssam 	int unit;
18329649Ssam {
18430230Ssam 	register struct enpdevice *addr;
18530230Ssam 	register BCB *bcbp;
18629649Ssam 
18730230Ssam 	addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
18830295Ssam #if ENP == 30
18930230Ssam 	if (!IS_ENP_INTR(addr))
19029649Ssam 		return;
19130230Ssam 	ACK_ENP_INTR(addr);
19230295Ssam #endif
19330295Ssam 	while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) {
194*35383Skarels 		enpread(&enp_softc[unit], bcbp);
19530295Ssam 		(void) ringput((RING *)&addr->enp_enpfree, bcbp);
19629649Ssam 	}
19729649Ssam }
19829649Ssam 
19929649Ssam /*
20029649Ssam  * Read input packet, examine its packet type, and enqueue it.
20129649Ssam  */
20230295Ssam enpread(es, bcbp)
20330230Ssam 	struct enp_softc *es;
20430230Ssam 	register BCB *bcbp;
20529649Ssam {
20629649Ssam 	register struct ether_header *enp;
20729649Ssam 	struct mbuf *m;
20830295Ssam 	int s, len, off, resid;
20929649Ssam 
21029649Ssam 	es->es_if.if_ipackets++;
21129649Ssam 	/*
21229649Ssam 	 * Get input data length.
21329649Ssam 	 * Get pointer to ethernet header (in input buffer).
21429649Ssam 	 * Deal with trailer protocol: if type is PUP trailer
21529649Ssam 	 * get true type from first 16-bit word past data.
21629649Ssam 	 * Remember that type was trailer by setting off.
21729649Ssam 	 */
21830230Ssam 	len = bcbp->b_msglen - sizeof (struct ether_header);
21930986Ssam 	enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr);
22030230Ssam #define enpdataaddr(enp, off, type) \
22130230Ssam     ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off))))
22230230Ssam 	enp->ether_type = ntohs((u_short)enp->ether_type);
22330230Ssam 	if (enp->ether_type >= ETHERTYPE_TRAIL &&
22430230Ssam 	    enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
22530230Ssam 		off = (enp->ether_type - ETHERTYPE_TRAIL) * 512;
22630230Ssam 		if (off >= ETHERMTU)
227*35383Skarels 			return;
22830230Ssam 		enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *));
22930230Ssam 		resid = ntohs(*(enpdataaddr(enp, off+2, u_short *)));
23030230Ssam 		if (off + resid > len)
231*35383Skarels 			return;
23229649Ssam 		len = off + resid;
23330230Ssam 	} else
23429649Ssam 		off = 0;
23530230Ssam 	if (len == 0)
236*35383Skarels 		return;
23729649Ssam 
23829649Ssam 	/*
23929649Ssam 	 * Pull packet off interface.  Off is nonzero if packet
24029649Ssam 	 * has trailing header; enpget will then force this header
241*35383Skarels 	 * information to be at the front.
24229649Ssam 	 */
24330986Ssam 	m = enpget((u_char *)enp, len, off, &es->es_if);
24430230Ssam 	if (m == 0)
245*35383Skarels 		return;
246*35383Skarels 	en_doproto(&es->es_if, enp, m);
24729649Ssam }
24829649Ssam 
249*35383Skarels enpstart(ifp)
25030230Ssam 	struct ifnet *ifp;
25129649Ssam {
252*35383Skarels 	int error = 0;
253*35383Skarels 	int s = splimp();
25429649Ssam 
255*35383Skarels 	if (enpput(ifp))
25629649Ssam 		error = ENOBUFS;
25730230Ssam 	splx(s);
25830230Ssam 	return (error);
25929649Ssam }
26029649Ssam 
26129649Ssam /*
26230230Ssam  * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus.
26329649Ssam  */
264*35383Skarels enpput(ifp)
265*35383Skarels struct ifnet *ifp;
26629649Ssam {
26729649Ssam 	register BCB *bcbp;
26830230Ssam 	register struct enpdevice *addr;
26929649Ssam 	register struct mbuf *mp;
27029649Ssam 	register u_char *bp;
27130230Ssam 	register u_int len;
272*35383Skarels 	int unit = ifp->if_unit;
27330230Ssam 	u_char *mcp;
274*35383Skarels 	struct mbuf *m;
27529649Ssam 
27630230Ssam 	addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
277*35383Skarels again:
27830295Ssam 	if (ringempty((RING *)&addr->enp_hostfree))
27930230Ssam 		return (1);
280*35383Skarels 	IF_DEQUEUE(&ifp->if_snd, m);
281*35383Skarels 	if (m == 0) return (0);
28230295Ssam 	bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree);
28329649Ssam 	bcbp->b_len = 0;
28430986Ssam 	bp = (u_char *)ENPGETLONG(&bcbp->b_addr);
28530230Ssam 	for (mp = m; mp; mp = mp->m_next) {
28629649Ssam 		len = mp->m_len;
28730230Ssam 		if (len == 0)
28829649Ssam 			continue;
28930230Ssam 		mcp = mtod(mp, u_char *);
29030230Ssam 		enpcopy(mcp, bp, len);
29129649Ssam 		bp += len;
29229649Ssam 		bcbp->b_len += len;
29329649Ssam 	}
29430986Ssam 	bcbp->b_len = MAX(ETHERMIN+sizeof (struct ether_header), bcbp->b_len);
29529649Ssam 	bcbp->b_reserved = 0;
29630295Ssam 	if (ringput((RING *)&addr->enp_toenp, bcbp) == 1)
29730230Ssam 		INTR_ENP(addr);
29829649Ssam 	m_freem(m);
299*35383Skarels 	goto again;
30029649Ssam }
30129649Ssam 
30229649Ssam /*
30330230Ssam  * Routine to copy from VERSAbus memory into mbufs.
30429649Ssam  *
30529649Ssam  * Warning: This makes the fairly safe assumption that
30629649Ssam  * mbufs have even lengths.
30729649Ssam  */
30829649Ssam struct mbuf *
309*35383Skarels enpget(rxbuf, totlen, off, ifp)
31030230Ssam 	u_char *rxbuf;
311*35383Skarels 	int totlen, off;
31230230Ssam 	struct ifnet *ifp;
31329649Ssam {
31430230Ssam 	register u_char *cp, *mcp;
31529649Ssam 	register struct mbuf *m;
31630230Ssam 	struct mbuf *top = 0, **mp = &top;
317*35383Skarels 	int len;
318*35383Skarels 	u_char *packet_end;
31929649Ssam 
320*35383Skarels 	rxbuf += sizeof (struct ether_header);
321*35383Skarels 	cp = rxbuf;
322*35383Skarels 	packet_end = cp + totlen;
323*35383Skarels 	if (off) {
324*35383Skarels 		off += 2 * sizeof(u_short);
325*35383Skarels 		totlen -= 2 *sizeof(u_short);
326*35383Skarels 		cp = rxbuf + off;
327*35383Skarels 	}
328*35383Skarels 
329*35383Skarels 	MGETHDR(m, M_DONTWAIT, MT_DATA);
330*35383Skarels 	if (m == 0)
331*35383Skarels 		return (0);
332*35383Skarels 	m->m_pkthdr.rcvif = ifp;
333*35383Skarels 	m->m_pkthdr.len = totlen;
334*35383Skarels 	m->m_len = MHLEN;
335*35383Skarels 
33630230Ssam 	while (totlen > 0) {
337*35383Skarels 		if (top) {
338*35383Skarels 			MGET(m, M_DONTWAIT, MT_DATA);
339*35383Skarels 			if (m == 0) {
340*35383Skarels 				m_freem(top);
341*35383Skarels 				return (0);
342*35383Skarels 			}
343*35383Skarels 			m->m_len = MLEN;
344*35383Skarels 		}
345*35383Skarels 		len = min(totlen, (packet_end - cp));
346*35383Skarels 		if (len >= MINCLSIZE) {
347*35383Skarels 			MCLGET(m, M_DONTWAIT);
348*35383Skarels 			if (m->m_flags & M_EXT)
349*35383Skarels 				m->m_len = len = min(len, MCLBYTES);
35030230Ssam 			else
351*35383Skarels 				len = m->m_len;
35230230Ssam 		} else {
35330230Ssam 			/*
354*35383Skarels 			 * Place initial small packet/header at end of mbuf.
35530230Ssam 			 */
356*35383Skarels 			if (len < m->m_len) {
357*35383Skarels 				if (top == 0 && len < max_linkhdr + m->m_len)
358*35383Skarels 					m->m_data += max_linkhdr;
359*35383Skarels 				m->m_len = len;
360*35383Skarels 			} else
361*35383Skarels 				len = m->m_len;
36230230Ssam 		}
363*35383Skarels 		mcp = mtod(m, u_char *);
36430295Ssam 		enpcopy(cp, mcp, (u_int)len);
36529649Ssam 		*mp = m;
36629649Ssam 		mp = &m->m_next;
367*35383Skarels 		totlen -= len;
368*35383Skarels 		cp += len;
369*35383Skarels 		if (cp == packet_end)
370*35383Skarels 			cp = rxbuf;
37129649Ssam 	}
37229649Ssam 	return (top);
37329649Ssam }
37429649Ssam 
37530230Ssam enpcopy(from, to, cnt)
37630295Ssam 	register u_char *from, *to;
37730295Ssam 	register u_int cnt;
37830230Ssam {
37930230Ssam 	register c;
38030230Ssam 	register short *f, *t;
38130230Ssam 
38230230Ssam 	if (((int)from&01) && ((int)to&01)) {
38330230Ssam 		/* source & dest at odd addresses */
38430230Ssam 		*to++ = *from++;
38530230Ssam 		--cnt;
38630230Ssam 	}
38730230Ssam 	if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
38830230Ssam 		t = (short *)to;
38930230Ssam 		f = (short *)from;
39030230Ssam 		for (c = cnt>>1; c; --c)	/* even address copy */
39130230Ssam 			*t++ = *f++;
39230230Ssam 		cnt &= 1;
39330230Ssam 		if (cnt) {			/* odd len */
39430295Ssam 			from = (u_char *)f;
39530295Ssam 			to = (u_char *)t;
39630230Ssam 			*to = *from;
39730230Ssam 		}
39830230Ssam 	}
39930295Ssam 	while ((int)cnt-- > 0)	/* one of the address(es) must be odd */
40030230Ssam 		*to++ = *from++;
40130230Ssam }
40230230Ssam 
40329649Ssam /*
40429649Ssam  * Process an ioctl request.
40529649Ssam  */
40629649Ssam enpioctl(ifp, cmd, data)
40730230Ssam 	register struct ifnet *ifp;
40830230Ssam 	int cmd;
40930230Ssam 	caddr_t data;
41029649Ssam {
41130230Ssam 	register struct ifaddr *ifa = (struct ifaddr *)data;
41230230Ssam 	struct enpdevice *addr;
41330230Ssam 	int s = splimp(), error = 0;
41429649Ssam 
41529649Ssam 	switch (cmd) {
41629649Ssam 
41729649Ssam 	case SIOCSIFADDR:
41830230Ssam 		ifp->if_flags |= IFF_UP;
41930230Ssam 		switch (ifa->ifa_addr.sa_family) {
42030230Ssam #ifdef INET
42130230Ssam 		case AF_INET:
42230230Ssam 			enpinit(ifp->if_unit);
42330230Ssam 			((struct arpcom *)ifp)->ac_ipaddr =
42430230Ssam 			    IA_SIN(ifa)->sin_addr;
42530230Ssam 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
42629649Ssam 			break;
42730230Ssam #endif
42830230Ssam #ifdef NS
42930230Ssam 		case AF_NS: {
43030230Ssam 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
43130230Ssam 			struct enp_softc *es = &enp_softc[ifp->if_unit];
43230230Ssam 
43330230Ssam 			if (!ns_nullhost(*ina)) {
43430230Ssam 				ifp->if_flags &= ~IFF_RUNNING;
43530230Ssam 				addr = (struct enpdevice *)
43630230Ssam 				    enpinfo[ifp->if_unit]->ui_addr;
43730230Ssam 				enpsetaddr(ifp->if_unit, addr,
43830230Ssam 				    ina->x_host.c_host);
43930230Ssam 			} else
44030986Ssam 				ina->x_host = *(union ns_host *)es->es_addr;
44130230Ssam 			enpinit(ifp->if_unit);
44230230Ssam 			break;
44329649Ssam 		}
44430230Ssam #endif
44530230Ssam 		default:
44630230Ssam 			enpinit(ifp->if_unit);
44730230Ssam 			break;
44829649Ssam 		}
44929649Ssam 		break;
45029649Ssam 
45130230Ssam 	case SIOCSIFFLAGS:
45230230Ssam 		if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
45330230Ssam 			enpinit(ifp->if_unit);		/* reset board */
45430230Ssam 			ifp->if_flags &= ~IFF_RUNNING;
45530230Ssam 		} else if (ifp->if_flags&IFF_UP &&
45630230Ssam 		     (ifp->if_flags&IFF_RUNNING) == 0)
45730230Ssam 			enpinit(ifp->if_unit);
45829649Ssam 		break;
45929649Ssam 
46029649Ssam 	default:
46129649Ssam 		error = EINVAL;
46229649Ssam 	}
46330230Ssam 	splx(s);
46430230Ssam 	return (error);
46529649Ssam }
46629649Ssam 
46730230Ssam enpsetaddr(unit, addr, enaddr)
46830230Ssam 	int unit;
46930230Ssam 	struct enpdevice *addr;
47030230Ssam 	u_char *enaddr;
47129649Ssam {
47229649Ssam 
47330986Ssam 	enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr,
47430986Ssam 	    sizeof (struct ether_addr));
47530230Ssam 	enpinit(unit);
47630986Ssam 	enpgetaddr(unit, addr);
47729649Ssam }
47829649Ssam 
47930986Ssam enpgetaddr(unit, addr)
48030986Ssam 	int unit;
48130986Ssam 	struct enpdevice *addr;
48230986Ssam {
48330986Ssam 	struct enp_softc *es = &enp_softc[unit];
48430986Ssam 
48530986Ssam 	enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr,
48630986Ssam 	    sizeof (struct ether_addr));
48730986Ssam 	printf("enp%d: hardware address %s\n",
48830986Ssam 	    unit, ether_sprintf(es->es_addr));
48930986Ssam }
49030986Ssam 
49129649Ssam /*
49230230Ssam  * Routines to synchronize enp and host.
49329649Ssam  */
49430295Ssam #ifdef notdef
49529649Ssam static
49630230Ssam ringinit(rp, size)
49730230Ssam 	register RING *rp;
49829649Ssam {
49929649Ssam 
50029649Ssam 	rp->r_rdidx = rp->r_wrtidx = 0;
50129649Ssam 	rp->r_size = size;
50229649Ssam }
50329649Ssam 
50429649Ssam static
50530295Ssam ringfull(rp)
50630230Ssam 	register RING *rp;
50729649Ssam {
50830295Ssam 	register short idx;
50930230Ssam 
51030295Ssam 	idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
51130295Ssam 	return (idx == rp->r_rdidx);
51229649Ssam }
51329649Ssam 
51429649Ssam static
51530295Ssam fir(rp)
51630230Ssam 	register RING *rp;
51729649Ssam {
51829649Ssam 
51930295Ssam 	return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0);
52029649Ssam }
52130295Ssam #endif
52229649Ssam 
52329649Ssam static
52430295Ssam ringempty(rp)
52530295Ssam 	register RING *rp;
52630295Ssam {
52730295Ssam 
52830295Ssam 	return (rp->r_rdidx == rp->r_wrtidx);
52930295Ssam }
53030295Ssam 
53130295Ssam static
53230230Ssam ringput(rp, v)
53330230Ssam 	register RING *rp;
53430295Ssam 	BCB *v;
53529649Ssam {
53629649Ssam 	register int idx;
53729649Ssam 
53829649Ssam 	idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
53930230Ssam 	if (idx != rp->r_rdidx) {
54030986Ssam 		ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v);
54129649Ssam 		rp->r_wrtidx = idx;
54230230Ssam 		if ((idx -= rp->r_rdidx) < 0)
54329649Ssam 			idx += rp->r_size;
54430230Ssam 		return (idx);			/* num ring entries */
54529649Ssam 	}
54630230Ssam 	return (0);
54729649Ssam }
54829649Ssam 
54929649Ssam static
55030230Ssam ringget(rp)
55130230Ssam 	register RING *rp;
55229649Ssam {
55329649Ssam 	register int i = 0;
55429649Ssam 
55530230Ssam 	if (rp->r_rdidx != rp->r_wrtidx) {
55630986Ssam 		i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]);
55729649Ssam 		rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
55829649Ssam 	}
55930230Ssam 	return (i);
56029649Ssam }
56129649Ssam 
56230230Ssam /*
56330230Ssam  * ENP Ram device.
56430230Ssam  */
56530230Ssam enpr_open(dev)
56630230Ssam 	dev_t dev;
56729649Ssam {
56830230Ssam 	register int unit = ENPUNIT(dev);
56930230Ssam 	struct vba_device *ui;
57030230Ssam 	struct enpdevice *addr;
57129649Ssam 
57230230Ssam 	if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
57330230Ssam 	    (addr = (struct enpdevice *)ui->ui_addr) == 0)
57430230Ssam 		return (ENODEV);
57530230Ssam 	if (addr->enp_state != S_ENPRESET)
57630230Ssam 		return (EACCES);  /* enp is not in reset state, don't open  */
57730230Ssam 	return (0);
57829649Ssam }
57929649Ssam 
58030295Ssam /*ARGSUSED*/
58130230Ssam enpr_close(dev)
58230230Ssam 	dev_t dev;
58329649Ssam {
58429649Ssam 
58530230Ssam 	return (0);
58629649Ssam }
58729649Ssam 
58830230Ssam enpr_read(dev, uio)
58930230Ssam 	dev_t dev;
59030230Ssam 	register struct uio *uio;
59129649Ssam {
59230230Ssam 	register struct iovec *iov;
59330230Ssam 	struct enpdevice *addr;
59429649Ssam 
59530230Ssam 	if (uio->uio_offset > RAM_SIZE)
59630230Ssam 		return (ENODEV);
59730295Ssam 	iov = uio->uio_iov;
59830230Ssam 	if (uio->uio_offset + iov->iov_len > RAM_SIZE)
59930230Ssam 		iov->iov_len = RAM_SIZE - uio->uio_offset;
60030230Ssam 	addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
60130986Ssam 	if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0)
60230986Ssam 		return (EFAULT);
60330295Ssam 	enpcopy((u_char *)&addr->enp_ram[uio->uio_offset],
60430295Ssam 	    (u_char *)iov->iov_base, (u_int)iov->iov_len);
60530230Ssam 	uio->uio_resid -= iov->iov_len;
60630230Ssam 	iov->iov_len = 0;
60730230Ssam 	return (0);
60829649Ssam }
60929649Ssam 
61030230Ssam enpr_write(dev, uio)
61130230Ssam 	dev_t dev;
61230230Ssam 	register struct uio *uio;
61329649Ssam {
61430230Ssam 	register struct enpdevice *addr;
61530230Ssam 	register struct iovec *iov;
61629649Ssam 
61730230Ssam 	addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
61830230Ssam 	iov = uio->uio_iov;
61930230Ssam 	if (uio->uio_offset > RAM_SIZE)
62030230Ssam 		return (ENODEV);
62130230Ssam 	if (uio->uio_offset + iov->iov_len > RAM_SIZE)
62230230Ssam 		iov->iov_len = RAM_SIZE - uio->uio_offset;
62330986Ssam 	if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0)
62430986Ssam 		return (EFAULT);
62530295Ssam 	enpcopy((u_char *)iov->iov_base,
62630295Ssam 	    (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len);
62730230Ssam 	uio->uio_resid -= iov->iov_len;
62830230Ssam 	iov->iov_len = 0;
62930230Ssam 	return (0);
63029649Ssam }
63129649Ssam 
63230295Ssam /*ARGSUSED*/
63330230Ssam enpr_ioctl(dev, cmd, data)
63430230Ssam 	dev_t dev;
63530230Ssam 	caddr_t data;
63629649Ssam {
63730230Ssam 	register unit = ENPUNIT(dev);
63830986Ssam 	struct enpdevice *addr;
63929649Ssam 
64030230Ssam 	addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
64130230Ssam 	switch(cmd) {
64230230Ssam 
64330230Ssam 	case ENPIOGO:
64430986Ssam 		ENPSETLONG(&addr->enp_base, addr);
64530230Ssam 		addr->enp_intrvec = enp_softc[unit].es_ivec;
64630230Ssam 		ENP_GO(addr, ENPSTART);
64730230Ssam 		DELAY(200000);
64830230Ssam 		enpinit(unit);
64930986Ssam 		/*
65030986Ssam 		 * Fetch Ethernet address after link level
65130986Ssam 		 * is booted (firmware copies manufacturer's
65230986Ssam 		 * address from on-board ROM).
65330986Ssam 		 */
65430986Ssam 		enpgetaddr(unit, addr);
65530986Ssam 		addr->enp_state = S_ENPRUN;
65630230Ssam 		break;
65730230Ssam 
65830230Ssam 	case ENPIORESET:
65930230Ssam 		RESET_ENP(addr);
66030986Ssam 		addr->enp_state = S_ENPRESET;
66130230Ssam 		DELAY(100000);
66230230Ssam 		break;
66330986Ssam 	default:
66430986Ssam 		return (EINVAL);
66529649Ssam 	}
66630230Ssam 	return (0);
66729649Ssam }
66829649Ssam #endif
669