diff options
| author | Pyun YongHyeon <yongari@FreeBSD.org> | 2011-03-28 19:08:53 +0000 |
|---|---|---|
| committer | Pyun YongHyeon <yongari@FreeBSD.org> | 2011-03-28 19:08:53 +0000 |
| commit | 1da7683a7caa1bb8c7550d467b33adfe9fe515d0 (patch) | |
| tree | ef5f1fbd831b05ac876a40a9be9c1ec2f4afcdff /sys/dev/dc | |
| parent | c45e1b3cad994fd019e36ec9842d2807cd3eae3e (diff) | |
Notes
Diffstat (limited to 'sys/dev/dc')
| -rw-r--r-- | sys/dev/dc/if_dc.c | 90 |
1 files changed, 39 insertions, 51 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index 6d0ebc0dcc44..772eede22f23 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -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. |
