--- if_ep.c.old Wed Feb 21 22:05:09 2001 +++ if_ep.c Wed Feb 21 23:25:33 2001 @@ -522,6 +522,27 @@ * fifo. */ readcheck: + + /* + * Check if the card is wedged. The 3c509 can apparently get into a mode + * where both the fifo status bit and the ERR_RX_INCOMPLETE bit are set. + * We check for this here and reset the adapter. It happens when there is + * a lot of broadcast traffic on the cable. + */ + if ((inw(BASE + EP_W1_RX_STATUS) & ERR_RX_INCOMPLETE) != 0) { + int fifost; + + GO_WINDOW(4); + fifost = inw(BASE + EP_W4_FIFO_DIAG); + GO_WINDOW(1); + if (fifost & 0x1800) { + printf("if_ep: !!! Card wedged, resetting !!!\n"); + s = splhigh(); /* XXX */ + ep_if_init(sc); + splx(s); /* XXX */ + } + } + if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) { /* * we check if we have packets left, in that case we prepare to come @@ -744,6 +765,24 @@ if (status & ERR_RX_INCOMPLETE) { /* we haven't received the complete * packet */ + int fifost, s; + + /* + * If the fifo overrun bits are also set (includ. fifo status overrun), + * then the card has wedged and we need to reset it. + */ + GO_WINDOW(4); + fifost = inw(BASE + EP_W4_FIFO_DIAG); + GO_WINDOW(1); + if (fifost & 0x1800) { + printf("if_ep: !!! Card wedged, resetting !!!\n"); + s = splhigh(); /* XXX */ + ep_if_init(sc); + splx(s); /* XXX */ + + goto read_again; + } + sc->mcur = m; #ifdef EP_LOCAL_STATS sc->rx_no_first++; /* to know how often we come here */