Convert to use <machine/bus.h>, plus 2 bug fixes:
- In egstart(), if the Send Packet command fails, m_freem() the mbuf chain before dequeueing another one (memory leak). - In egintr(), return 1 if a known interrupt was processed. Would manifest itself as spurious interrupts.
This commit is contained in:
parent
af6e1b10a8
commit
c937985d60
|
@ -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 <dean@fsa.ca>
|
||||
|
@ -36,6 +36,7 @@
|
|||
/* To do:
|
||||
* - multicast
|
||||
* - promiscuous
|
||||
* - get rid of isa indirect stuff
|
||||
*/
|
||||
#include "bpfilter.h"
|
||||
|
||||
|
@ -75,7 +76,7 @@
|
|||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
#include <machine/pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/if_egreg.h>
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue