/* 3com etherbox driver */#include "sys/param.h"#include "sys/types.h"#include "sys/sysmacros.h"#include "sys/var.h"#include "errno.h"#include "sys/config.h"#include "net/misc.h"#include "net/mbuf.h"#include "net/protosw.h"#include "net/socket.h"#include "net/ubavar.h"#include "net/if.h"#include "net/route.h"#include "net/in.h"#include "net/in_systm.h"#include "net/ip.h"#include "net/ip_var.h"#include "net/if_ether.h"		#define	EBPUP_PUPTYPE	0x0400		/* PUP protocol */#define	EBPUP_IPTYPE	0x0800		/* IP protocol *//* * The EBPUP_NTRAILER packet types starting at EBPUP_TRAIL have * (type-EBPUP_TRAIL)*512 bytes of data followed * by a PUP type (as given above) and then the (variable-length) header. */#define	EBPUP_TRAIL	0x1000		/* Trailer PUP */#define	EBPUP_NTRAILER	16/* * 3Com Ethernet controller registers. */#define EB_ACTADDR0	0	/* actual address byte 0 */#define EB_ACTADDR1	1	/* actual address byte 0 */#define EB_ACTADDR2	2	/* actual address byte 0 */#define EB_ACTADDR3	3	/* actual address byte 0 */#define EB_ACTADDR4	4	/* actual address byte 0 */#define EB_ACTADDR5	5	/* actual address byte 0 */#define EB_RCVCMD	6	/* receive command */#define EB_XCSR		7	/* transmit csr */#define EB_XBP_HI	8	/* transmit buffer pointer high byte */#define EB_XBP_LO	9	/* transmit buffer pointer low byte */#define EB_BBPCLEAR	10	/* buffer pointer clear(w) */#define EB_PROM		10	/* address prom (r) */#define EB_AUXCSR	11	/* auxiliary command/status */#define EB_COLLCNTR	12	/* collision counter */#define EB_XMTBUF	13	/* transmit buffer */#define EB_RCVBUFA	14	/* receive buffer a */#define EB_RCVBUFB	15	/* receive buffer b *//* * Transmit cmd reg bits */#define	EB_EIEOF	0x8	/* enable ints on end of frame */#define	EB_EI16COLL	4	/* enable ints on 16 collisions */#define	EB_EICOLL	2	/* enable ints on collisions */#define	EB_EIUNDER	1	/* enable ints on underflow *//* * Transmit status reg bits */#define	EB_XREADY	0x8	/* ready for new frame */#define	EB_COLL16	4	/* 16 collisions detected on last xmit */#define	EB_COLL		2	/* collision occurred */#define	EB_UNDERFLOW	1	/* force underflow *//* * Receive command reg bits */#define	EB_MULTI	0xC	/* match station, multi, broadcast */#define	EB_STABROAD	0x80 	/* match station, broadcast */#define	EB_PROMIS	0x40	/* match all packets */#define	EB_ANYGOOD	0x20	/* enable detection of any good frame */#define	EB_ANY		0x10	/* enable detection of any frame */#define	EB_SHORT	0x8	/* enable decection of short frames */#define	EB_DRIBBLE	4	/* enable dectection of dribble error */#define	EB_CRC		2	/* enable dectection of CRC error */#define	EB_OVFLO	1	/* enable detection of overflow error */#define	EB_RCVNORM	(EB_STABROAD|EB_ANYGOOD|EB_DRIBBLE|EB_CRC|EB_OVFLO|EB_SHORT)/* * Receive status reg bits */#define EB_STALE	0x80	/* invalid packet here */#define	EB_SHORTERR	0x40	/* short frame */#define	EB_DRIBERR	0x20	/* dribble error */#define	EB_CRCERR	0x10	/* crc error */#define	EB_OVFLERR	0x8	/* overflow error */#define	EB_RCVERR	0xf8	/* error mask */#define	EB_RBUF		0x7	/* buffer pointer mask *//* * Auxiliary command reg bits */#define	EB_EDLCRES	0x80	/* reset EDLC chip */#define	EB_SYSEI	0x40	/* enable system interrupts */#define	EB_RBBSW	0x20	/* talk to receive buffer b */#define	EB_RBASW	0x10	/* talk to receive buffer a */#define	EB_XBUFSW	0x8	/* talk to transmit buffer */#define	EB_XEOFDIS	2	/* create underflow for testing */#define	EB_POWINTR	1	/* clear power-on interrupt *//* * Auxiliary status reg bits */#define	EB_XCVRUP	0x80	/* the integral transceiver is enabled */#define	EB_BBASW	4	/* receive buf b before a switch */#define	EB_IMASK	0x70	/* interesting bits for rcv. int. routine */#define	EBRDOFF		2	/* packet offset in read buffer */#define	EBMAXTDOFF	(2048-512)	/* max packet offset (min size) */#define NEB 1/* * 3Com Ethernet Controller interface */#define	EBMTU	1500int nulldev(), ebattach(), ebintr(), ebpoll();struct	uba_device *ebinfo[NEB];struct	uba_driver ebdriver = {	nulldev, ebattach, (u_short * )0, ebinfo};#define	EBUNIT(x)	minor(x)int	ebinit(),eboutput(),ebwatch();struct mbuf *ebget();int	ebwr_reg(), ebrd_reg();extern struct ifnet loif;/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct	eb_softc {	struct	arpcom es_ac;		/* common Ethernet structures */#define	es_if	es_ac.ac_if		/* network-visible interface */#define	es_enaddr es_ac.ac_enaddr	/* hardware Ethernet address */	short	es_oactive;		/* is output active? */} eb_softc[NEB];/* temp receive buffer */char ebrbuf[EBMTU];/* for polling */short ebok = 0;/* set low 3 bytes to, eg, DEC manuf. number for us to pretend to be DEC */long eb_masq = 0;/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */ebattach(md)	struct uba_device *md;{	struct eb_softc *es = &eb_softc[md->ui_unit];	register struct ifnet *ifp = &es->es_if;	register pport = (int)md->ui_addr;	struct sockaddr_in *sin;	ifp->if_unit = md->ui_unit;	ifp->if_name = "eb";	ifp->if_mtu = EBMTU;	ifp->if_net = md->ui_flags & 0xFF000000;	if (!appleinit(pport))		return;	ebreset(pport);	/*	 * Read the ethernet address from the box.	 */	ebwr_reg(pport, EB_BBPCLEAR, 0);	/* reset bus-buffer pointer */	ebrd_setup(pport, EB_PROM);		/* setup for read from prom */	ebrd_data(pport, es->es_enaddr, 6);	/* hack to change the manufacturer */	if (eb_masq) {		char *mp;		mp =(char *)&eb_masq;		mp++;		bcopy(mp, es->es_enaddr, 3);	}	printf("Ethernet address = ");	{		char * p = &es->es_enaddr[0];		int i, j = 0;		char buf[14];		for (i = 0; i < 6; i ++) {			buf[j++] = "0123456789ABCDEF"[((*p >> 4)&0xf)];			buf[j++] = "0123456789ABCDEF"[((*p++)&0xf)];		}		buf[j++] = '\n';		buf[j] = 0;		printf(buf);	}	sin = (struct sockaddr_in *)&es->es_if.if_addr;	sin->sin_family = AF_INET;	/*	sin->sin_addr = arpmyaddr((struct arpcom *)0);	*/	/* this is a way to set addresses for now (without an ioctl()) */	sin->sin_addr.s_addr = (u_long)md->ui_flags;	ebsetaddr(ifp, sin);	ifp->if_init = ebinit;	ifp->if_output = eboutput;	ifp->if_watchdog = ebwatch;	if_attach(ifp);}ebwatch(){}/* * Initialization of interface; clear recorded pending * operations. */ebinit(unit)	int unit;{	struct eb_softc *es = &eb_softc[unit];	register struct ifnet *ifp = &es->es_if;	register struct sockaddr_in *sin;	register pport;	int i, s;	char ebuf[6];	sin = (struct sockaddr_in *)&ifp->if_addr;	if (sin->sin_addr.s_addr == 0)		/* address still unknown */	    return;	if ((es->es_if.if_flags & IFF_RUNNING) == 0) {	    pport = (int) ebinfo[unit]->ui_addr;	    s = splimp();	    /* reset EDLC chip by toggeling reset bit */	    ebwr_reg(pport, EB_AUXCSR, EB_EDLCRES);	    ebwr_reg(pport, EB_AUXCSR, 0);	    /* Initialize the address RAM */	    ebwr_reg(pport, EB_BBPCLEAR, 0);	/* reset bus-buffer pointer */	    ebrd_setup(pport, EB_PROM);	    ebrd_data(pport, ebuf, 6);	    for (i = 0; i < 6; i++)		    ebwr_reg(pport, EB_ACTADDR0+i, ebuf[i]);	    /* Hang receive buffers and start any pending writes.  */	    ebwr_reg(pport, EB_RCVCMD, EB_RCVNORM);	/* normal bits */	    ebwr_reg(pport, EB_AUXCSR, (EB_RBASW|EB_RBBSW|EB_SYSEI));	    es->es_oactive = 0;	    es->es_if.if_flags |= IFF_UP|IFF_RUNNING;	    if (es->es_if.if_snd.ifq_head)		    ebstart(unit);	    ebok = pport;	    ebpoll(pport);	    splx(s);	}	if_rtinit(&es->es_if, RTF_UP);	arpattach(&es->es_ac);	arpwhohas(&es->es_ac, &sin->sin_addr);}/* * Start or restart output on interface. * If interface is already active, then this is a retransmit * after a collision, and just restuff registers. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */ebstart(dev)	register dev_t dev;{        register int unit = EBUNIT(dev);	register struct eb_softc *es = &eb_softc[unit];	register int pport;	register struct mbuf *m;	register unsigned char csr;	register x = spl6();	pport = (int)ebinfo[unit]->ui_addr;	if (es->es_oactive)		goto restart;	IF_DEQUEUE(&es->es_if.if_snd, m);	if (m == 0) {		es->es_oactive = 0;		splx(x);		return;	}	ebput(pport, m);	ebwr_reg(pport, EB_XCSR, (EB_EIEOF|EB_EI16COLL));	csr = ebrd_reg(pport, EB_AUXCSR) & EB_IMASK;	ebwr_reg(pport, EB_AUXCSR, csr | (EB_SYSEI|EB_XBUFSW));restart:	splx(x);	es->es_oactive = 1;}int bbuf;int abuf;int bbabuf;int abbbuf;int nopkt;/* * Ethernet interface interrupt.  If received packet examine  * packet to determine type.  If can't determine length * from type, then have to drop packet.  Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. *//* ARGSUSED */ebintr(pport){	register struct eb_softc *es;	register int unit;	register bits = 0;	register unsigned char csr, xcsr;	extern short netoff;	if (netoff)		return;	for (unit = 0; unit < NEB; unit++) {	    es = &eb_softc[unit];	    csr = ebrd_reg(pport, EB_AUXCSR);again:	    switch (csr & (EB_RBASW|EB_RBBSW|EB_BBASW)) {	    case EB_RBASW:	    case EB_RBASW|EB_BBASW:		    /* RBBSW == 0, receive B packet */		    bbuf++;		    ebread(es, pport, EB_RCVBUFB);		    bits |= (EB_RBBSW|EB_SYSEI);		    break;	    case EB_RBBSW:	    case EB_RBBSW|EB_BBASW:		    /* RBASW == 0, receive A packet */		    abuf++;		    ebread(es, pport, EB_RCVBUFA);		    bits |= (EB_RBASW|EB_SYSEI);		    break;	    case EB_BBASW:		    /* RBASW == 0, RBBSW == 0, BBASW, receive B, then A */		    bbabuf++;		    ebread(es, pport, EB_RCVBUFB);		    ebread(es, pport, EB_RCVBUFA);		    bits |= (EB_RBBSW|EB_RBASW|EB_SYSEI);		    break;	    case 0:		    /* RBASW == 0, RBBSW == 0, BBASW == 0, receive A, then B */		    abbbuf++;		    ebread(es, pport, EB_RCVBUFA);		    ebread(es, pport, EB_RCVBUFB);		    bits |= (EB_RBBSW|EB_RBASW|EB_SYSEI);		    break;	    case EB_RBASW|EB_RBBSW:	    case EB_RBASW|EB_RBBSW|EB_BBASW:		    /* no input packets */		    nopkt++;		    bits |= (EB_RBBSW|EB_RBASW|EB_SYSEI);		    break;	    default:		    panic("ebintr: impossible value");		    /* NOT REACHED */	    }	    xcsr = ebrd_reg(pport, EB_AUXCSR);	    if (xcsr != csr) {		    csr = xcsr;		    goto again;	    }	    ebwr_reg(pport, EB_AUXCSR, (int)((csr|bits)&EB_IMASK));	    if (es->es_oactive) {		    if ((csr & EB_XBUFSW) == 0) {			    es->es_if.if_opackets++;			    es->es_oactive = 0;			    csr = ebrd_reg(pport, EB_XCSR);			    if (csr&0xff == 0xff)				    csr = ebrd_reg(pport, EB_XCSR);				    if (csr&0xff == 0xff) {					printf("eb%d xmit status reg. botch\n",					    unit);					goto cont;				    }			    if (csr & EB_COLL)				    /* clear counter */				    ebwr_reg(pport, EB_COLLCNTR, 0);			    if (csr & EB_COLL16) {				    printf("eb%d: 16 collisions; resetting...\n"				   	, unit);				    ebreset(pport);				    ebinit(unit);			    }			    if (es->es_if.if_snd.ifq_head)				    ebstart(unit);		    }	    }cont:	    ebportreset(pport);		/* clear pport */	}}ebread(es, pport, buf)	register struct eb_softc *es;	register int pport;	register int buf;{	register struct ether_header *eb;    	register struct mbuf *m;	register int len, off, eboff;	register unsigned char byte1, byte2;	short resid;	register struct ifqueue *inq;	short x;	es->es_if.if_ipackets++;	ebwr_reg(pport, EB_BBPCLEAR, 0);	/* clear bus buffer pointer */	byte1 = ebrd_reg(pport, buf);		/* first byte of buffer */	if (byte1 & EB_RCVERR) {		printf("ebrcv error %x\n", byte1&0xff);		es->es_if.if_ierrors++;		return;	}	byte2 = ebrd_reg(pport, buf);		/* second byte of buffer */	eboff = (((byte1&EB_RBUF)<<8)|byte2) - EBRDOFF;	/* get data */	ebrd_setup(pport, buf);	ebrd_data(pport, ebrbuf, eboff);	/*	 * Get input data length.	 * Get pointer to ethernet header (in input buffer).	 * Deal with trailer protocol: if type is PUP trailer	 * get true type from first 16-bit word past data.	 * Reebmber that type was trailer by setting off.	 */	len = eboff - sizeof (struct ether_header);	eb = (struct ether_header *)ebrbuf;#define	ebdataaddr(eb, off, type)	((type)(((caddr_t)((eb)+1)+(off))))	if (eb->ether_type >= EBPUP_TRAIL &&	    eb->ether_type < EBPUP_TRAIL+EBPUP_NTRAILER) {		off = (eb->ether_type - EBPUP_TRAIL) * 512;		if (off >= EBMTU)			return;		/* sanity */		eb->ether_type = *ebdataaddr(eb, off, u_short *);		resid = *(ebdataaddr(eb, off+2, u_short *));		if (off + resid > len)			return;		/* sanity */		len = off + resid;	} else		off = 0;	if (len == 0)		return;	/*	 * Put packet into mbufs.  Off is nonzero if packet	 * has trailing header; ebget will then force this header	 * information to be at the front, but we still have to drop	 * the type and length which are at the front of any trailer data.	 */	m = ebget(ebrbuf, len, off);	if (m == 0)		return;	if (off) {		m->m_off += 2 * sizeof (u_short);		m->m_len -= 2 * sizeof (u_short);	}	x = spl6();	switch (eb->ether_type) {#ifdef INET	case EBPUP_IPTYPE:		schednetisr(NETISR_IP);		inq = &ipintrq;		break;	case ETHERPUP_ARPTYPE:		arpinput(&es->es_ac, m);		splx(x);		return;#endif	default:		m_freem(m);		splx(x);		return;	}	if (IF_QFULL(inq)) {		IF_DROP(inq);		splx(x);		m_freem(m);		return;	}	IF_ENQUEUE(inq, m);	splx(x);}/* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. * If destination is this address or broadcast, send packet to * loop device to kludge around the fact that 3com interfaces can't * talk to themselves. */eboutput(ifp, m0, dst)	register struct ifnet *ifp;	register struct mbuf *m0;	register struct sockaddr *dst;{	int type, s, error;	u_char edst[6];	struct in_addr idst;	register struct eb_softc *es = &eb_softc[ifp->if_unit];	register struct mbuf *m = m0;	register struct ether_header *eb;	register int i;	struct mbuf *mcopy = (struct mbuf *) 0;		/* Null */	s = splnet();	switch (dst->sa_family) {#ifdef INET	case AF_INET:		idst = ((struct sockaddr_in *)dst)->sin_addr;		if (!arpresolve(&es->es_ac, m, &idst, edst))			return (0);	/* if not yet resolved */		if (in_lnaof(idst) == INADDR_ANY)			mcopy = m_copy(m, 0, (int)M_COPYALL);		type = EBPUP_IPTYPE;		goto gottype;#endif	case AF_UNSPEC:		eb = (struct ether_header *)dst->sa_data;		bcopy((caddr_t)eb->ether_dhost, (caddr_t)edst, sizeof (edst));		type = eb->ether_type;		goto gottype;	default:		printf("eb%d: can't handle af%d\n", ifp->if_unit,			dst->sa_family);		error = EAFNOSUPPORT;		goto bad;	}gottype:	/*	 * Add local net header.  If no space in first mbuf,	 * allocate another.	 */	if (m->m_off > MMAXOFF ||	    MMINOFF + sizeof (struct ether_header) > m->m_off) {		m = m_get(M_DONTWAIT);		if (m == 0) {			error = ENOBUFS;			goto bad;		}		m->m_next = m0;		m->m_off = MMINOFF;		m->m_len = sizeof (struct ether_header);	} else {		m->m_off -= sizeof (struct ether_header);		m->m_len += sizeof (struct ether_header);	}	eb = mtod(m, struct ether_header *);	bcopy((caddr_t)edst, (caddr_t)eb->ether_dhost, sizeof (edst));	eb->ether_type = htons((u_short)type);	bcopy((caddr_t)es->es_enaddr, (caddr_t)eb->ether_shost, 6);	/*	 * Queue message on interface, and start output if interface	 * not yet active.	 */	s = splimp();	if (IF_QFULL(&ifp->if_snd)) {		IF_DROP(&ifp->if_snd);		error = ENOBUFS;		goto qfull;	}	IF_ENQUEUE(&ifp->if_snd, m);	if (es->es_oactive == 0)		ebstart(ifp->if_unit);	splx(s);gotlocal:	return(mcopy ? looutput(&loif, mcopy, dst) : 0);qfull:	m0 = m;bad:	m_freem(m0);	splx(s);	return(error);}/* * Routine to copy from mbuf chain to transmitter * buffer in Multibus ebmory. */ebput(pport, m)	register int pport;	register struct mbuf *m;{	register struct mbuf *mp;	register short off;	register flag = 0;	register unsigned len;	register u_char *p;	for (off = 2048, mp = m; mp; mp = mp->m_next)		off -= mp->m_len;	if (off > EBMAXTDOFF)		/* enforce minimum packet size */		off = EBMAXTDOFF;	if (off & 01) {		off--;		flag++;	}    	/* load xmit buffer pointer */	ebwr_reg(pport, EB_XBP_LO, off&0xff);	ebwr_reg(pport, EB_XBP_HI, ((off>>8)&7));	ebwr_setup(pport, EB_XMTBUF);	for (mp = m; mp; mp = mp->m_next) {		len = mp->m_len;		if (len == 0)			continue;		p = mtod(mp,u_char*);		ebwr_data(pport, p, (short)len);	}	if (flag)		ebwr_data(pport, "", 1);	/* re-load xmit buffer pointer */	ebwr_reg(pport, EB_XBP_LO, off&0xff);	ebwr_reg(pport, EB_XBP_HI, ((off>>8)&7));	m_freem(m);}/* * Routine to copy from memory into mbufs. */struct mbuf *ebget(ebrbuf, totlen, off0)	register u_char *ebrbuf;	register int totlen, off0;{	register struct mbuf *m;	struct mbuf *top = 0, **mp = &top;	register int off = off0, len;	register u_char *cp;	cp = ebrbuf + sizeof (struct ether_header);#ifdef DUMPIN	{char *cp = ebrbuf; int i; int j; printf("ebget:\n");for(j=0;j<6;j++){for(i=0;i<16;i++)printf("%x ",(((char *)cp)[i+16*j])&0xff);printf("\n");}for(i=0;i<10000;i++);}#endif	while (totlen > 0) {		u_char *mcp;		MGET(m, 0);		if (m == 0){			goto bad;		}		if (off) {			len = totlen - off;			cp = ebrbuf + sizeof (struct ether_header) + off;		} else			len = totlen;		m->m_len = len = MIN(MLEN, len);		m->m_off = MMINOFF;		mcp = mtod(m, u_char *);		bcopy(cp, mcp, len);		cp += len;		*mp = m;		mp = &m->m_next;		if (off == 0) {			totlen -= len;			continue;		}		off += len;		if (off == totlen) {			cp = ebrbuf + sizeof (struct ether_header);			off = 0;			totlen = off0;		}	}	return (top);bad:	m_freem(top);	return (0);}#ifdef notdef/* ebdelay -- wait about tim secs */ebdelay(tim)register tim;{	register i;	while (tim--){		i = 100000;		while (i--)			;	}}#endif/* stuff for apple */#include <sys/pport.h>#include <sys/cops.h>#include <sys/d_profile.h>#include <sys/profile.h>#define	RC	0xa8		/* read cmd */#define	WC	0xa0		/* write cmd */#define	RD	0xb8		/* read data */#define WD	0xb0		/* write data */#define INPUT	0x00		/* ddra input */#define	OUTPUT	0xFF		/* ddra output *//* sometime, put the parallel port data somewhere besides the in disk driver */extern struct device_d *pro_da[];ebreset(pport)register pport;			/* parallel port number */{	register struct device_d *dp =  pro_da[pport];#define	THISISMAGIC#ifdef	THISISMAGIC	/* reset 6522.  */	dp->d_ddra = INPUT;	dp->d_irb = 0x18;	dp->d_ddrb = 0xbc;	dp->d_irb = RC;	dp->d_pcr = 0xb;	dp->d_ier = FIRQ|FCA1;		/* enable interrupts (I guess) */#endif	THISISMAGIC	ebwr_reg(pport, EB_AUXCSR, 1);		/* clear power-on interrupt */	ebportreset(pport);}/* setup a register to write to it */ebwr_setup(pport, regno)int pport, regno;{	register struct device_d *dp =  pro_da[pport];	dp->d_irb = WC;	dp->d_ddra = OUTPUT;	dp->d_ira = regno;	dp->d_irb = WD;}/* setup a register to read from it */ebrd_setup(pport, regno)int pport, regno;{	register struct device_d *dp =  pro_da[pport];	dp->d_irb = WC;	dp->d_ddra = OUTPUT;	dp->d_ira = regno;	dp->d_irb = RD;	dp->d_ddra = INPUT;}/* write data to box.  must have done a ebwr_setup() first */ebwr_data(pport, p, nbytes)int pport;register short nbytes;register char *p;{	register struct device_d *dp =  pro_da[pport];	if (nbytes )		do {			dp->d_ira = *p++;		} while (--nbytes);}/* read data from box.  must have done a ebrd_setup() first */ebrd_data(pport, p, nbytes)int pport;register short nbytes;register char *p;{	register struct device_d *dp =  pro_da[pport];	if (nbytes )		do {			*p++ = dp->d_ira;		} while (--nbytes);}/* write a register */ebwr_reg(pport, regno, byte)int pport, regno, byte;{	register struct device_d *dp =  pro_da[pport];	dp->d_irb = WC;	dp->d_ddra = OUTPUT;	dp->d_ira = regno;	dp->d_irb = WD;	dp->d_ira = byte;}/* read a register */ebrd_reg(pport, regno)int pport, regno;{	register struct device_d *dp =  pro_da[pport];	dp->d_irb = WC;	dp->d_ddra = OUTPUT;	dp->d_ira = regno;	dp->d_irb = RD;	dp->d_ddra = INPUT;	return (dp->d_ira & 0xff);}/* ebportreset - reset port to normal state after xmit command */ebportreset(pport)int pport;{	register struct device_d *dp =  pro_da[pport];	dp->d_irb = RC;	dp->d_ddra = INPUT;}appleinit(i){	register struct device_d *devp;	int ebintr();	extern char slot[];	if (!PPOK(i) || (slot[PPSLOT(i)] != PR0)) {/* check slot # and type */		printf("ethernet init: port %d, ", i);		if (slot[PPSLOT(i)] == PM3)			printf("Priam card\n");		else			printf("card ID 0x%x\n", slot[PPSLOT(i)]);		goto fail;	}	devp = pro_da[i];	if (iocheck(&devp->d_ifr)) {	/* board there ? */		{ asm(" nop "); }		if (prodata[i].pd_da != devp) {	/* not already setup */			if (setppint((prodata[i].pd_da = devp),ebintr))				goto fail;		}		return 1;	} elsefail:	printf("Can't find port for etherbox %d\n", i);	return 0;}#ifdef doneinppintr/* applereset -- reset apple interrupt hware */applereset(pport){	register struct device_d *dp =  pro_da[pport];	dp->d_ifr = dp->d_ifr;		/* reset interrupt trap */}#endif/* sigh */short polleb = 1;/* ...as opposed to pollcat... */ebpoll(pport){	extern time_t lbolt;	if (polleb) {		char ebuf[6];		int i;		/*		ebintr(pport);		*/		ebreset(pport);		/* reset EDLC chip by toggeling reset bit */		ebwr_reg(pport, EB_AUXCSR, EB_EDLCRES);		ebwr_reg(pport, EB_AUXCSR, 0);		/* Initialize the address RAM */		ebwr_reg(pport, EB_BBPCLEAR, 0);	/* reset bus-buffer pointer */		ebrd_setup(pport, EB_PROM);		ebrd_data(pport, ebuf, 6);		for (i = 0; i < 6; i++)		    ebwr_reg(pport, EB_ACTADDR0+i, ebuf[i]);		/* Hang receive buffers and start any pending writes.  */		ebwr_reg(pport, EB_RCVCMD, EB_RCVNORM);	/* normal bits */		ebwr_reg(pport, EB_AUXCSR, (EB_RBASW|EB_RBBSW|EB_SYSEI));		timeout(ebpoll, pport, v.v_hz*10);	}}ebsetaddr(ifp, sin)	register struct ifnet *ifp;	register struct sockaddr_in *sin;{	ifp->if_addr = *(struct sockaddr *)sin;	ifp->if_net = in_netof(sin->sin_addr);	ifp->if_host[0] = in_lnaof(sin->sin_addr);	sin = (struct sockaddr_in *)&ifp->if_broadaddr;	sin->sin_family = AF_INET;	sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);	ifp->if_flags |= IFF_BROADCAST;}