diff --git a/sys/dev/isa/if_eg.c b/sys/dev/isa/if_eg.c index 5e1a58060a94..2ecd974ed6a9 100644 --- a/sys/dev/isa/if_eg.c +++ b/sys/dev/isa/if_eg.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_eg.c,v 1.26 1996/05/12 23:52:27 mycroft Exp $ */ +/* $NetBSD: if_eg.c,v 1.27 1996/08/03 02:12:46 thorpej Exp $ */ /* * Copyright (c) 1993 Dean Huxley @@ -36,6 +36,7 @@ /* To do: * - multicast * - promiscuous + * - get rid of isa indirect stuff */ #include "bpfilter.h" @@ -75,7 +76,7 @@ #include #include -#include +#include #include #include @@ -102,17 +103,15 @@ struct eg_softc { struct device sc_dev; void *sc_ih; struct arpcom sc_arpcom; /* Ethernet common part */ - int eg_cmd; /* Command register R/W */ - int eg_ctl; /* Control register R/W (EG_CTL_*) */ - int eg_stat; /* Status register R/O (EG_STAT_*) */ - int eg_data; /* Data register R/W (16 bits) */ - u_char eg_rom_major; /* Cards ROM version (major number) */ - u_char eg_rom_minor; /* Cards ROM version (minor number) */ - short eg_ram; /* Amount of RAM on the card */ - u_char eg_pcb[64]; /* Primary Command Block buffer */ - u_char eg_incount; /* Number of buffers currently used */ - u_char *eg_inbuf; /* Incoming packet buffer */ - u_char *eg_outbuf; /* Outgoing packet buffer */ + bus_chipset_tag_t sc_bc; /* bus chipset identifier */ + bus_io_handle_t sc_ioh; /* i/o handle */ + u_int8_t eg_rom_major; /* Cards ROM version (major number) */ + u_int8_t eg_rom_minor; /* Cards ROM version (minor number) */ + short eg_ram; /* Amount of RAM on the card */ + u_int8_t eg_pcb[64]; /* Primary Command Block buffer */ + u_int8_t eg_incount; /* Number of buffers currently used */ + caddr_t eg_inbuf; /* Incoming packet buffer */ + caddr_t eg_outbuf; /* Outgoing packet buffer */ }; int egprobe __P((struct device *, void *, void *)); @@ -169,13 +168,15 @@ egprintstat(b) static int egoutPCB(sc, b) struct eg_softc *sc; - u_char b; + u_int8_t b; { + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; int i; for (i=0; i < 4000; i++) { - if (inb(sc->eg_stat) & EG_STAT_HCRE) { - outb(sc->eg_cmd, b); + if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HCRE) { + bus_io_write_1(bc, ioh, EG_COMMAND, b); return 0; } delay(10); @@ -187,16 +188,19 @@ egoutPCB(sc, b) static int egreadPCBstat(sc, statb) struct eg_softc *sc; - u_char statb; + u_int8_t statb; { + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; int i; for (i=0; i < 5000; i++) { - if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) + if ((bus_io_read_1(bc, ioh, EG_STATUS) & + EG_PCB_STAT) != EG_PCB_NULL) break; delay(10); } - if ((inb(sc->eg_stat) & EG_PCB_STAT) == statb) + if ((bus_io_read_1(bc, ioh, EG_STATUS) & EG_PCB_STAT) == statb) return 0; return 1; } @@ -205,10 +209,12 @@ static int egreadPCBready(sc) struct eg_softc *sc; { + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; int i; for (i=0; i < 10000; i++) { - if (inb(sc->eg_stat) & EG_STAT_ACRF) + if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_ACRF) return 0; delay(5); } @@ -220,22 +226,26 @@ static int egwritePCB(sc) struct eg_softc *sc; { + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; int i; - u_char len; + u_int8_t len; - outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL); + bus_io_write_1(bc, ioh, EG_CONTROL, + (bus_io_read_1(bc, ioh, 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 (inb(sc->eg_stat) & EG_STAT_HCRE) + if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HCRE) break; delay(10); } - outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_DONE); + bus_io_write_1(bc, ioh, EG_CONTROL, + (inb(EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_DONE); egoutPCB(sc, len); @@ -248,43 +258,48 @@ static int egreadPCB(sc) struct eg_softc *sc; { + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; int i; - u_char b; - - outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL); + u_int8_t b; + + bus_io_write_1(bc, ioh, EG_CONTROL, + (bus_io_read_1(bc, ioh, 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] = inb(sc->eg_cmd); - + sc->eg_pcb[0] = inb(EG_COMMAND); + if (egreadPCBready(sc)) return 1; - sc->eg_pcb[1] = inb(sc->eg_cmd); + sc->eg_pcb[1] = bus_io_read_1(bc, ioh, 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] = inb(sc->eg_cmd); + sc->eg_pcb[2+i] = bus_io_read_1(bc, ioh, EG_COMMAND); } if (egreadPCBready(sc)) return 1; if (egreadPCBstat(sc, EG_PCB_DONE)) return 1; - if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1] + 2) { + if ((b = bus_io_read_1(bc, ioh, EG_COMMAND)) != sc->eg_pcb[1] + 2) { dprintf(("%d != %d\n", b, sc->eg_pcb[1] + 2)); return 1; } - outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_ACCEPT); + bus_io_write_1(bc, ioh, EG_CONTROL, + (bus_io_read_1(bc, ioh, EG_CONTROL) & + ~EG_PCB_STAT) | EG_PCB_ACCEPT); return 0; } @@ -300,52 +315,68 @@ egprobe(parent, match, aux) { struct eg_softc *sc = match; struct isa_attach_args *ia = aux; - int i; + bus_chipset_tag_t bc = ia->ia_bc; + bus_io_handle_t ioh; + int i, rval; + + rval = 0; if (ia->ia_iobase & ~0x07f0 != 0) { dprintf(("Weird iobase %x\n", ia->ia_iobase)); return 0; } - - sc->eg_cmd = ia->ia_iobase + EG_COMMAND; - sc->eg_ctl = ia->ia_iobase + EG_CONTROL; - sc->eg_stat = ia->ia_iobase + EG_STATUS; - sc->eg_data = ia->ia_iobase + EG_DATA; + + /* Map i/o space. */ + if (bus_io_map(bc, ia->ia_iobase, 0x08, &ioh)) { + dprintf(("egprobe: can't map i/o space in probe\n")); + return 0; + } + + /* + * XXX Indirect brokenness. + */ + sc->sc_bc = bc; /* XXX */ + sc->sc_ioh = ioh; /* XXX */ /* hard reset card */ - outb(sc->eg_ctl, EG_CTL_RESET); - outb(sc->eg_ctl, 0); + bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_RESET); + bus_io_write_1(bc, ioh, EG_CONTROL, 0); for (i = 0; i < 5000; i++) { delay(1000); - if ((inb(sc->eg_stat) & EG_PCB_STAT) == EG_PCB_NULL) + if ((bus_io_read_1(bc, ioh, EG_STATUS) & + EG_PCB_STAT) == EG_PCB_NULL) break; } - if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) { - dprintf(("eg: Reset failed\n")); - return 0; + if ((bus_io_read_1(bc, ioh, EG_STATUS) & EG_PCB_STAT) != EG_PCB_NULL) { + dprintf(("egprobe: Reset failed\n")); + goto out; } sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */ sc->eg_pcb[1] = 0; if (egwritePCB(sc) != 0) - return 0; - + goto out; + if (egreadPCB(sc) != 0) { egprintpcb(sc); - return 0; + goto out; } if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */ sc->eg_pcb[1] != 0x0a) { egprintpcb(sc); - return 0; + goto out; } 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; - return 1; + rval = 1; + + out: + bus_io_unmap(bc, ioh, 0x08); + return rval; } void @@ -355,48 +386,64 @@ egattach(parent, self, aux) { struct eg_softc *sc = (void *)self; struct isa_attach_args *ia = aux; + bus_chipset_tag_t bc = ia->ia_bc; + bus_io_handle_t ioh; struct ifnet *ifp = &sc->sc_arpcom.ac_if; int i; - + + printf("\n"); + + /* Map i/o space. */ + if (bus_io_map(bc, ia->ia_iobase, ia->ia_iosize, &ioh)) { + printf("%s: can't map i/o space\n", self->dv_xname); + return; + } + + sc->sc_bc = bc; + sc->sc_ioh = ioh; + 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")); + printf("%s: can't send Get Station Address\n", self->dv_xname); return; } if (egreadPCB(sc) != 0) { - dprintf(("read error\n")); + printf("%s: can't read station address\n", self->dv_xname); 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")); + printf("%s: card responded with garbage (1)\n", + self->dv_xname); 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", + printf("%s: ROM v%d.%02d %dk address %s\n", self->dv_xname, 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")); + printf("%s: can't send Set Station Address\n", self->dv_xname); return; } if (egreadPCB(sc) != 0) { - dprintf(("read error2\n")); + printf("%s: can't read Set Station Address status\n", + self->dv_xname); 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")); + printf("%s: card responded with garbage (2)\n", + self->dv_xname); egprintpcb(sc); return; } @@ -426,13 +473,15 @@ eginit(sc) register struct eg_softc *sc; { register struct ifnet *ifp = &sc->sc_arpcom.ac_if; + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; /* soft reset the board */ - outb(sc->eg_ctl, EG_CTL_FLSH); + bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_FLSH); delay(100); - outb(sc->eg_ctl, EG_CTL_ATTN); + bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_ATTN); delay(100); - outb(sc->eg_ctl, 0); + bus_io_write_1(bc, ioh, EG_CONTROL, 0); delay(200); sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */ @@ -440,23 +489,37 @@ eginit(sc) sc->eg_pcb[2] = 3; /* receive broadcast & multicast */ sc->eg_pcb[3] = 0; if (egwritePCB(sc) != 0) - dprintf(("write error3\n")); + printf("%s: can't send Configure 82586\n", + sc->sc_dev.dv_xname); if (egreadPCB(sc) != 0) { - dprintf(("read error\n")); + printf("%s: can't read Configure 82586 status\n", + sc->sc_dev.dv_xname); 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) + if (sc->eg_inbuf == NULL) { sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); + if (sc->eg_inbuf == NULL) { + printf("%s: can't allocate inbuf\n", + sc->sc_dev.dv_xname); + panic("eginit"); + } + } sc->eg_incount = 0; - if (sc->eg_outbuf == 0) + if (sc->eg_outbuf == NULL) { sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); + if (sc->eg_outbuf == NULL) { + printf("%s: can't allocate outbuf\n", + sc->sc_dev.dv_xname); + panic("eginit"); + } + } - outb(sc->eg_ctl, EG_CTL_CMDE); + bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_CMDE); sc->eg_incount = 0; egrecv(sc); @@ -496,10 +559,12 @@ egstart(ifp) struct ifnet *ifp; { register struct eg_softc *sc = ifp->if_softc; + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; struct mbuf *m0, *m; caddr_t buffer; int len; - u_short *ptr; + u_int16_t *ptr; /* Don't transmit if interface is busy or not running */ if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) @@ -514,8 +579,10 @@ loop: 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"); + if ((m0->m_flags & M_PKTHDR) == 0) { + printf("%s: no header mbuf\n", sc->sc_dev.dv_xname); + panic("egstart"); + } len = max(m0->m_pkthdr.len, ETHER_MIN_LEN); #if NBPFILTER > 0 @@ -532,9 +599,11 @@ loop: sc->eg_pcb[6] = len; /* length of packet */ sc->eg_pcb[7] = len >> 8; if (egwritePCB(sc) != 0) { - dprintf(("egwritePCB in egstart failed\n")); + printf("%s: can't send Send Packet command\n", + sc->sc_dev.dv_xname); ifp->if_oerrors++; ifp->if_flags &= ~IFF_OACTIVE; + m_freem(m0); goto loop; } @@ -545,11 +614,12 @@ loop: } /* set direction bit: host -> adapter */ - outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR); + bus_io_write_1(bc, ioh, EG_CONTROL, + bus_io_read_1(bc, ioh, EG_CONTROL) & ~EG_CTL_DIR); - for (ptr = (u_short *) sc->eg_outbuf; len > 0; len -= 2) { - outw(sc->eg_data, *ptr++); - while (!(inb(sc->eg_stat) & EG_STAT_HRDY)) + for (ptr = (u_int16_t *) sc->eg_outbuf; len > 0; len -= 2) { + bus_io_write_2(bc, ioh, EG_DATA, *ptr++); + while (!(bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HRDY)) ; /* XXX need timeout here */ } @@ -561,22 +631,29 @@ egintr(arg) void *arg; { register struct eg_softc *sc = arg; - int i, len; - u_short *ptr; + bus_chipset_tag_t bc = sc->sc_bc; + bus_io_handle_t ioh = sc->sc_ioh; + int i, len, serviced; + u_int16_t *ptr; - while (inb(sc->eg_stat) & EG_STAT_ACRF) { + serviced = 0; + + while (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_ACRF) { 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 */ - outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR); + bus_io_write_1(bc, ioh, EG_CONTROL, + bus_io_read_1(bc, ioh, EG_CONTROL) | EG_CTL_DIR); - for (ptr = (u_short *) sc->eg_inbuf; len > 0; len -= 2) { - while (!(inb(sc->eg_stat) & EG_STAT_HRDY)) + for (ptr = (u_int16_t *) sc->eg_inbuf; + len > 0; len -= 2) { + while (!(bus_io_read_1(bc, ioh, EG_STATUS) & + EG_STAT_HRDY)) ; - *ptr++ = inw(sc->eg_data); + *ptr++ = bus_io_read_2(bc, ioh, EG_DATA); } len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8); @@ -584,40 +661,51 @@ egintr(arg) sc->eg_incount--; egrecv(sc); + serviced = 1; break; case EG_RSP_SENDPACKET: if (sc->eg_pcb[6] || sc->eg_pcb[7]) { - dprintf(("packet dropped\n")); + dprintf(("%s: packet dropped\n", + sc->sc_dev.dv_xname)); 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_collisions += + sc->eg_pcb[8] & 0xf; sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; egstart(&sc->sc_arpcom.ac_if); + serviced = 1; break; + /* XXX byte-order and type-size bugs here... */ case EG_RSP_GETSTATS: - dprintf(("Card Statistics\n")); + dprintf(("%s: Card Statistics\n", + sc->sc_dev.dv_xname)); 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])); + 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])); + serviced = 1; break; default: - dprintf(("egintr: Unknown response %x??\n", - sc->eg_pcb[0])); + printf("%s: egintr: Unknown response %x??\n", + sc->sc_dev.dv_xname, sc->eg_pcb[0]); egprintpcb(sc); break; } } - return 0; + return serviced; } /* @@ -760,7 +848,7 @@ egioctl(ifp, cmd, data) if (ns_nullhost(*ina)) ina->x_host = - *(union ns_host *)(sc->sc_arpcom.ac_enaddr); + *(union ns_host *)(sc->sc_arpcom.ac_enaddr); else bcopy(ina->x_host.c_host, sc->sc_arpcom.ac_enaddr, @@ -820,7 +908,7 @@ egreset(sc) { int s; - dprintf(("egreset()\n")); + dprintf(("%s: egreset()\n", sc->sc_dev.dv_xname)); s = splnet(); egstop(sc); eginit(sc); @@ -844,5 +932,5 @@ egstop(sc) register struct eg_softc *sc; { - outb(sc->eg_ctl, 0); + bus_io_write_1(sc->sc_bc, sc->sc_ioh, EG_CONTROL, 0); }