Revise r220046 by introducing dc_netcfg_wait() which waits the end

of active DMA cycle. dc_setcfg() also has to wait until the DMA
engine is stopped so using a common function to handle the job is
better than duplicating the code.

No objection from:	marius
This commit is contained in:
Pyun YongHyeon 2011-03-28 19:08:53 +00:00
parent c45e1b3cad
commit 1da7683a7c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=220106

View file

@ -279,6 +279,7 @@ static void dc_miibus_statchg(device_t);
static void dc_miibus_mediainit(device_t);
static void dc_setcfg(struct dc_softc *, int);
static void dc_netcfg_wait(struct dc_softc *);
static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
static uint32_t dc_mchash_be(const uint8_t *);
static void dc_setfilt_21143(struct dc_softc *);
@ -1370,6 +1371,32 @@ dc_setfilt(struct dc_softc *sc)
dc_setfilt_xircom(sc);
}
static void
dc_netcfg_wait(struct dc_softc *sc)
{
uint32_t isr;
int i;
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE &&
((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
device_printf(sc->dc_dev,
"%s: failed to force tx to idle state\n", __func__);
if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
!DC_HAS_BROKEN_RXSTATE(sc))
device_printf(sc->dc_dev,
"%s: failed to force rx to idle state\n", __func__);
}
}
/*
* In order to fiddle with the 'full-duplex' and '100Mbps' bits in
* the netconfig register, we first have to put the transmit and/or
@ -1378,8 +1405,7 @@ dc_setfilt(struct dc_softc *sc)
static void
dc_setcfg(struct dc_softc *sc, int media)
{
int i, restart = 0, watchdogreg;
uint32_t isr;
int restart = 0, watchdogreg;
if (IFM_SUBTYPE(media) == IFM_NONE)
return;
@ -1387,28 +1413,7 @@ dc_setcfg(struct dc_softc *sc, int media)
if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) {
restart = 1;
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE &&
((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
device_printf(sc->dc_dev,
"%s: failed to force tx to idle state\n",
__func__);
if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
!DC_HAS_BROKEN_RXSTATE(sc))
device_printf(sc->dc_dev,
"%s: failed to force rx to idle state\n",
__func__);
}
dc_netcfg_wait(sc);
}
if (IFM_SUBTYPE(media) == IFM_100_TX) {
@ -3917,7 +3922,7 @@ dc_stop(struct dc_softc *sc)
struct dc_list_data *ld;
struct dc_chain_data *cd;
int i;
uint32_t ctl, isr;
uint32_t ctl, netcfg;
DC_LOCK_ASSERT(sc);
@ -3928,38 +3933,21 @@ dc_stop(struct dc_softc *sc)
callout_stop(&sc->dc_stat_ch);
callout_stop(&sc->dc_wdog_ch);
sc->dc_wdog_timer = 0;
sc->dc_link = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if ((isr & DC_ISR_TX_IDLE ||
(isr & DC_ISR_TX_STATE) == DC_TXSTATE_RESET) &&
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED)
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
if (!((isr & DC_ISR_TX_IDLE) ||
(isr & DC_ISR_TX_STATE) == DC_TXSTATE_RESET) &&
!DC_IS_ASIX(sc) && !DC_IS_DAVICOM(sc))
device_printf(sc->dc_dev,
"%s: failed to force tx to idle state\n",
__func__);
if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED) &&
!DC_HAS_BROKEN_RXSTATE(sc))
device_printf(sc->dc_dev,
"%s: failed to force rx to idle state\n",
__func__);
}
netcfg = CSR_READ_4(sc, DC_NETCFG);
if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
CSR_WRITE_4(sc, DC_NETCFG,
netcfg & ~(DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
/* Wait the completion of TX/RX SM. */
if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
dc_netcfg_wait(sc);
CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
sc->dc_link = 0;
/*
* Free data in the RX lists.