if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) panic("%s: can't map I/O space", sc->sc_dev.dv_xname);
if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) { printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); return; }
struct mbuf *egget __P((struct eg_softc *, caddr_t, int));void egstop __P((struct eg_softc *));static __inline void egprintpcb __P((struct eg_softc *));static __inline void egprintstat __P((u_char));static int egoutPCB __P((struct eg_softc *, u_char));static int egreadPCBstat __P((struct eg_softc *, u_char));static int egreadPCBready __P((struct eg_softc *));static int egwritePCB __P((struct eg_softc *));static int egreadPCB __P((struct eg_softc *));/* * Support stuff */	static __inline voidegprintpcb(sc)	struct eg_softc *sc;{	int i;		for (i = 0; i < sc->eg_pcb[1] + 2; i++)		dprintf(("pcb[%2d] = %x\n", i, sc->eg_pcb[i]));}static __inline voidegprintstat(b)	u_char b;{	dprintf(("%s %s %s %s %s %s %s\n", 	    (b & EG_STAT_HCRE)?"HCRE":"",	    (b & EG_STAT_ACRF)?"ACRF":"",	    (b & EG_STAT_DIR )?"DIR ":"",	    (b & EG_STAT_DONE)?"DONE":"",	    (b & EG_STAT_ASF3)?"ASF3":"",	    (b & EG_STAT_ASF2)?"ASF2":"",	    (b & EG_STAT_ASF1)?"ASF1":""));}static integoutPCB(sc, b)	struct eg_softc *sc;	u_char b;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int i;	for (i=0; i < 4000; i++) {		if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE) {			bus_space_write_1(bst, bsh, EG_COMMAND, b);			return 0;		}		delay(10);	}	dprintf(("egoutPCB failed\n"));	return (1);}	static integreadPCBstat(sc, statb)	struct eg_softc *sc;	u_char statb;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int i;	for (i=0; i < 5000; i++) {		if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=		    EG_PCB_NULL) 			break;		delay(10);	}	if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) == statb) 		return (0);	return (1);}static integreadPCBready(sc)	struct eg_softc *sc;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int i;	for (i=0; i < 10000; i++) {		if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF)			return (0);		delay(5);	}	dprintf(("PCB read not ready\n"));	return (1);}	static integwritePCB(sc)	struct eg_softc *sc;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int i;	u_char len;	bus_space_write_1(bst, bsh, EG_CONTROL,	    (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |	    EG_PCB_NULL);	len = sc->eg_pcb[1] + 2;	for (i = 0; i < len; i++)		egoutPCB(sc, sc->eg_pcb[i]);		for (i=0; i < 4000; i++) {		if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE)			break;		delay(10);	}	bus_space_write_1(bst, bsh, EG_CONTROL,	    (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |	    EG_PCB_DONE);	egoutPCB(sc, len);	if (egreadPCBstat(sc, EG_PCB_ACCEPT))		return (1);	return (0);}		static integreadPCB(sc)	struct eg_softc *sc;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int i;	u_char b;		bus_space_write_1(bst, bsh, EG_CONTROL,	    (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |	    EG_PCB_NULL);	bzero(sc->eg_pcb, sizeof(sc->eg_pcb));	if (egreadPCBready(sc))		return (1);	sc->eg_pcb[0] = bus_space_read_1(bst, bsh, EG_COMMAND);		if (egreadPCBready(sc))		return (1);	sc->eg_pcb[1] = bus_space_read_1(bst, bsh, EG_COMMAND);	if (sc->eg_pcb[1] > 62) {		dprintf(("len %d too large\n", sc->eg_pcb[1]));		return (1);	}		for (i = 0; i < sc->eg_pcb[1]; i++) {		if (egreadPCBready(sc))			return (1);		sc->eg_pcb[2+i] = bus_space_read_1(bst, bsh, EG_COMMAND);	}	if (egreadPCBready(sc))		return (1);	if (egreadPCBstat(sc, EG_PCB_DONE))		return (1);	if ((b = bus_space_read_1(bst, bsh, EG_COMMAND)) != sc->eg_pcb[1] + 2)	    {		dprintf(("%d != %d\n", b, sc->eg_pcb[1] + 2));		return (1);	}	bus_space_write_1(bst, bsh, EG_CONTROL,	    (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |	    EG_PCB_ACCEPT);	return (0);}	/* * Real stuff */integprobe(parent, match, aux)	struct device *parent;	void *match, *aux;{	struct eg_softc *sc = match;	struct isa_attach_args *ia = aux;	bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;	bus_space_handle_t bsh;	int i;	if ((ia->ia_iobase & ~0x07f0) != 0) {		dprintf(("Weird iobase %x\n", ia->ia_iobase));		return (0);	}		if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) {		printf("%s: can't map I/O space\n", sc->sc_dev.dv_xname);		return (0);	}	sc->sc_bsh = bsh;	/* hard reset card */	bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_RESET); 	bus_space_write_1(bst, bsh, EG_CONTROL, 0);	for (i = 0; i < 5000; i++) {		delay(1000);		if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) ==		    EG_PCB_NULL) 			break;	}	if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=	    EG_PCB_NULL) {		dprintf(("eg: Reset failed\n"));		goto lose;	}	sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */	sc->eg_pcb[1] = 0;	if (egwritePCB(sc) != 0)		goto lose;		if (egreadPCB(sc) != 0) {		egprintpcb(sc);		goto lose;	}	if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */	    sc->eg_pcb[1] != 0x0a) {		egprintpcb(sc);		goto lose;	}	sc->eg_rom_major = sc->eg_pcb[3];	sc->eg_rom_minor = sc->eg_pcb[2];	sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);		ia->ia_iosize = 0x08;	ia->ia_msize = 0;	bus_space_unmap(bst, bsh, EG_IO_PORTS);	return (1);lose:	sc->sc_bst = sc->sc_bsh = 0;	bus_space_unmap(bst, bsh, EG_IO_PORTS);	return (0);}voidegattach(parent, self, aux)	struct device *parent, *self;	void *aux;{	struct eg_softc *sc = (void *)self;	struct isa_attach_args *ia = aux;	bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;	bus_space_handle_t bsh;	struct ifnet *ifp = &sc->sc_arpcom.ac_if;		if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh))		panic("%s: can't map I/O space", sc->sc_dev.dv_xname);	sc->sc_bsh = bsh;	egstop(sc);	sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */	sc->eg_pcb[1] = 0;	if (egwritePCB(sc) != 0) {		dprintf(("write error\n"));		return;	}		if (egreadPCB(sc) != 0) {		dprintf(("read error\n"));		egprintpcb(sc);		return;	}	/* check Get station address response */	if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) { 		dprintf(("parse error\n"));		egprintpcb(sc);		return;	}	bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);	printf(": ROM v%d.%02d %dk address %s\n",	    sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram,	    ether_sprintf(sc->sc_arpcom.ac_enaddr));	sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */	if (egwritePCB(sc) != 0) {		dprintf(("write error2\n"));		return;	}	if (egreadPCB(sc) != 0) {		dprintf(("read error2\n"));		egprintpcb(sc);		return;	}	if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||	    sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {		dprintf(("parse error2\n"));		egprintpcb(sc);		return;	}	/* Initialize ifnet structure. */	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);	ifp->if_softc = sc;	ifp->if_start = egstart;	ifp->if_ioctl = egioctl;	ifp->if_watchdog = egwatchdog;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;		/* Now we can attach the interface. */	if_attach(ifp);	ether_ifattach(ifp);		sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,	    IPL_NET, egintr, sc, sc->sc_dev.dv_xname);}voideginit(sc)	register struct eg_softc *sc;{	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;	/* soft reset the board */	bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_FLSH);	delay(100);	bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_ATTN);	delay(100);	bus_space_write_1(bst, bsh, EG_CONTROL, 0);	delay(200);	sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */	sc->eg_pcb[1] = 2;	sc->eg_pcb[2] = 3; /* receive broadcast & multicast */	sc->eg_pcb[3] = 0;	if (egwritePCB(sc) != 0)		dprintf(("write error3\n"));	if (egreadPCB(sc) != 0) {		dprintf(("read error\n"));		egprintpcb(sc);	} else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)		printf("%s: configure card command failed\n",		    sc->sc_dev.dv_xname);	if (sc->eg_inbuf == 0)		sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);	sc->eg_incount = 0;	if (sc->eg_outbuf == 0)		sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);	bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_CMDE);	sc->eg_incount = 0;	egrecv(sc);	/* Interface is now `running', with no output active. */	ifp->if_flags |= IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	/* Attempt to start output, if any. */	egstart(ifp);}voidegrecv(sc)	struct eg_softc *sc;{	while (sc->eg_incount < EG_INLEN) {		sc->eg_pcb[0] = EG_CMD_RECVPACKET;		sc->eg_pcb[1] = 0x08;		sc->eg_pcb[2] = 0; /* address not used.. we send zero */		sc->eg_pcb[3] = 0;		sc->eg_pcb[4] = 0;		sc->eg_pcb[5] = 0;		sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */		sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;		sc->eg_pcb[8] = 0; /* timeout, 0 == none */		sc->eg_pcb[9] = 0;		if (egwritePCB(sc) != 0)			break;		sc->eg_incount++;	}}voidegstart(ifp)	struct ifnet *ifp;{	struct eg_softc *sc = ifp->if_softc;	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	struct mbuf *m0, *m;	caddr_t buffer;	int len;	u_short *ptr;	/* Don't transmit if interface is busy or not running */	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)		return;loop:	/* Dequeue the next datagram. */	IF_DEQUEUE(&ifp->if_snd, m0);	if (m0 == 0)		return;		ifp->if_flags |= IFF_OACTIVE;	/* We need to use m->m_pkthdr.len, so require the header */	if ((m0->m_flags & M_PKTHDR) == 0)		panic("egstart: no header mbuf");	len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);#if NBPFILTER > 0	if (ifp->if_bpf)		bpf_mtap(ifp->if_bpf, m0);#endif	sc->eg_pcb[0] = EG_CMD_SENDPACKET;	sc->eg_pcb[1] = 0x06;	sc->eg_pcb[2] = 0; /* address not used, we send zero */	sc->eg_pcb[3] = 0;	sc->eg_pcb[4] = 0;	sc->eg_pcb[5] = 0;	sc->eg_pcb[6] = len; /* length of packet */	sc->eg_pcb[7] = len >> 8;	if (egwritePCB(sc) != 0) {		dprintf(("egwritePCB in egstart failed\n"));		ifp->if_oerrors++;		ifp->if_flags &= ~IFF_OACTIVE;		m_freem(m0);		goto loop;	}	buffer = sc->eg_outbuf;	for (m = m0; m != 0; m = m->m_next) {		bcopy(mtod(m, caddr_t), buffer, m->m_len);		buffer += m->m_len;	}	/* set direction bit: host -> adapter */	bus_space_write_1(bst, bsh, EG_CONTROL,	    bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_CTL_DIR); 		for (ptr = (u_short *)sc->eg_outbuf; len > 0; len -= 2) {		bus_space_write_2(bst, bsh, EG_DATA, *ptr++);		while (!(bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HRDY))			; /* XXX need timeout here */	}		m_freem(m0);}integintr(arg)	void *arg;{	struct eg_softc *sc = arg;	bus_space_tag_t bst = sc->sc_bst;	bus_space_handle_t bsh = sc->sc_bsh;	int ret = 0;	int i, len;	u_short *ptr;	while (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF) {		ret = 1;		egreadPCB(sc);		switch (sc->eg_pcb[0]) {		case EG_RSP_RECVPACKET:			len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);				/* Set direction bit : Adapter -> host */			bus_space_write_1(bst, bsh, EG_CONTROL,			    bus_space_read_1(bst, bsh, EG_CONTROL) |			    EG_CTL_DIR); 			for (ptr = (u_short *)sc->eg_inbuf; len > 0; len -= 2)			    {				while (!(bus_space_read_1(bst, bsh,				    EG_STATUS) & EG_STAT_HRDY))					;				*ptr++ = bus_space_read_2(bst, bsh, EG_DATA);			}			len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);			egread(sc, sc->eg_inbuf, len);			sc->eg_incount--;			egrecv(sc);			break;		case EG_RSP_SENDPACKET:			if (sc->eg_pcb[6] || sc->eg_pcb[7]) {				dprintf(("packet dropped\n"));				sc->sc_arpcom.ac_if.if_oerrors++;			} else				sc->sc_arpcom.ac_if.if_opackets++;			sc->sc_arpcom.ac_if.if_collisions +=			    sc->eg_pcb[8] & 0xf;			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;			egstart(&sc->sc_arpcom.ac_if);			break;		case EG_RSP_GETSTATS:			dprintf(("Card Statistics\n"));			bcopy(&sc->eg_pcb[2], &i, sizeof(i));			dprintf(("Receive Packets %d\n", i));			bcopy(&sc->eg_pcb[6], &i, sizeof(i));			dprintf(("Transmit Packets %d\n", i));			dprintf(("CRC errors %d\n", *(short*)&sc->eg_pcb[10]));			dprintf(("alignment errors %d\n",			    *(short*)&sc->eg_pcb[12]));			dprintf(("no resources errors %d\n",			    *(short*)&sc->eg_pcb[14]));			dprintf(("overrun errors %d\n",			    *(short*)&sc->eg_pcb[16]));			break;					default:			dprintf(("egintr: Unknown response %x??\n",			    sc->eg_pcb[0]));			egprintpcb(sc);			break;		}	}	return (ret);}/* * Pass a packet up to the higher levels. */voidegread(sc, buf, len)	struct eg_softc *sc;	caddr_t buf;	int len;{	struct ifnet *ifp = &sc->sc_arpcom.ac_if;	struct mbuf *m;	struct ether_header *eh;		if (len <= sizeof(struct ether_header) ||	    len > ETHER_MAX_LEN) {		printf("%s: invalid packet size %d; dropping\n",		    sc->sc_dev.dv_xname, len);		ifp->if_ierrors++;		return;	}	/* Pull packet off interface. */	m = egget(sc, buf, len);	if (m == 0) {		ifp->if_ierrors++;		return;	}	ifp->if_ipackets++;	/* We assume the header fit entirely in one mbuf. */	eh = mtod(m, struct ether_header *);#if NBPFILTER > 0	/*	 * Check if there's a BPF listener on this interface.	 * If so, hand off the raw packet to BPF.	 */	if (ifp->if_bpf)		bpf_mtap(ifp->if_bpf, m);#endif	/* We assume the header fit entirely in one mbuf. */	m_adj(m, sizeof(struct ether_header));	ether_input(ifp, eh, m);}/* * convert buf into mbufs */struct mbuf *egget(sc, buf, totlen)	struct eg_softc *sc;	caddr_t buf;	int totlen;{	struct ifnet *ifp = &sc->sc_arpcom.ac_if;	struct mbuf *top, **mp, *m;	int len;	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0)		return (0);	m->m_pkthdr.rcvif = ifp;	m->m_pkthdr.len = totlen;	len = MHLEN;	top = 0;	mp = &top;	while (totlen > 0) {		if (top) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				m_freem(top);				return (0);			}			len = MLEN;		}		if (totlen >= MINCLSIZE) {			MCLGET(m, M_DONTWAIT);			if (m->m_flags & M_EXT)				len = MCLBYTES;		}		m->m_len = len = min(totlen, len);		bcopy((caddr_t)buf, mtod(m, caddr_t), len);		buf += len;		totlen -= len;		*mp = m;		mp = &m->m_next;	}	return (top);}