aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/bge
diff options
context:
space:
mode:
authorPyun YongHyeon <yongari@FreeBSD.org>2012-10-05 03:46:25 +0000
committerPyun YongHyeon <yongari@FreeBSD.org>2012-10-05 03:46:25 +0000
commita0a03d1e827c692e390c6bc6cd37deaee54ef6bf (patch)
treef54f702aca6f6562b08602db1f93fdd37264d541 /sys/dev/bge
parente4146b9510d06cf15a49124ae74a11dd4b5ace07 (diff)
downloadsrc-a0a03d1e827c692e390c6bc6cd37deaee54ef6bf.tar.gz
src-a0a03d1e827c692e390c6bc6cd37deaee54ef6bf.zip
APE firmware touches EMAC Mode and TX/RX MAC Mode registers to keep
the MAC connected to the outside world. So keep the accesses atomic.
Notes
Notes: svn path=/head/; revision=241216
Diffstat (limited to 'sys/dev/bge')
-rw-r--r--sys/dev/bge/if_bge.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 8cfe51e8285e..1edc3c70243e 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -896,6 +896,7 @@ bge_miibus_statchg(device_t dev)
{
struct bge_softc *sc;
struct mii_data *mii;
+ uint32_t mac_mode, rx_mode, tx_mode;
sc = device_get_softc(dev);
if ((sc->bge_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
@@ -925,30 +926,39 @@ bge_miibus_statchg(device_t dev)
sc->bge_link = 0;
if (sc->bge_link == 0)
return;
- BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE);
+
+ /*
+ * APE firmware touches these registers to keep the MAC
+ * connected to the outside world. Try to keep the
+ * accesses atomic.
+ */
+
+ /* Set the port mode (MII/GMII) to match the link speed. */
+ mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) &
+ ~(BGE_MACMODE_PORTMODE | BGE_MACMODE_HALF_DUPLEX);
+ tx_mode = CSR_READ_4(sc, BGE_TX_MODE);
+ rx_mode = CSR_READ_4(sc, BGE_RX_MODE);
+
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII);
+ mac_mode |= BGE_PORTMODE_GMII;
else
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII);
+ mac_mode |= BGE_PORTMODE_MII;
+ /* Set MAC flow control behavior to match link flow control settings. */
+ tx_mode &= ~BGE_TXMODE_FLOWCTL_ENABLE;
+ rx_mode &= ~BGE_RXMODE_FLOWCTL_ENABLE;
if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0) {
- BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
- if ((IFM_OPTIONS(mii->mii_media_active) &
- IFM_ETH_TXPAUSE) != 0)
- BGE_SETBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- else
- BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- if ((IFM_OPTIONS(mii->mii_media_active) &
- IFM_ETH_RXPAUSE) != 0)
- BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- else
- BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- } else {
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
- BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- }
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+ tx_mode |= BGE_TXMODE_FLOWCTL_ENABLE;
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+ rx_mode |= BGE_RXMODE_FLOWCTL_ENABLE;
+ } else
+ mac_mode |= BGE_MACMODE_HALF_DUPLEX;
+
+ CSR_WRITE_4(sc, BGE_MAC_MODE, mac_mode);
+ CSR_WRITE_4(sc, BGE_TX_MODE, tx_mode);
+ CSR_WRITE_4(sc, BGE_RX_MODE, rx_mode);
}
/*