From 318b02fdb95e3668f8439ed7eb625c65702b584c Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Wed, 31 May 2000 05:40:53 +0000 Subject: [PATCH] Rework the support for the internal autonegotiation on the 21143 and workalike chips (Macronix 98713A/98715 and PNIC II). Timing is somewhat critical: you need to bring the link as soon as possible after NWAY is done, and the old one second polling interval was too long. Now we poll every 10th of a second until NWAY completes (at which point we return to the 1 second interval again to keep an eye on the link state). I tested all the other cards I had on hand to make sure I didn't bust any of them and they seem to work (including the MII-based 21143 card). This should fix some autoneg problems with DE500-BA cards and the built-in 10/100 ethernet on some alpha systems. (Now before anyone asks why I never noticed this before, the old code worked just find with the Intel swich I used for testing back in NY. Apparently not all switches are as picky about the timing.) --- sys/dev/dc/dcphy.c | 83 ++++++++++++------------------------------- sys/dev/dc/if_dc.c | 50 ++++++++++++++++++-------- sys/dev/dc/if_dcreg.h | 1 + sys/dev/mii/dcphy.c | 83 ++++++++++++------------------------------- sys/pci/if_dc.c | 50 ++++++++++++++++++-------- sys/pci/if_dcreg.h | 1 + 6 files changed, 118 insertions(+), 150 deletions(-) diff --git a/sys/dev/dc/dcphy.c b/sys/dev/dc/dcphy.c index a39adc50fbd9..f8a3f479cc22 100644 --- a/sys/dev/dc/dcphy.c +++ b/sys/dev/dc/dcphy.c @@ -262,6 +262,7 @@ dcphy_service(sc, mii, cmd) switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /*dcphy_reset(sc);*/ + sc->mii_flags &= ~MIIF_DOINGAUTO; (void) dcphy_auto(sc, 0); break; case IFM_100_T4: @@ -322,57 +323,21 @@ dcphy_service(sc, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); - if (sc->mii_flags & MIIF_DOINGAUTO) { - if (++sc->mii_ticks != 5) - return(0); - else { - sc->mii_ticks = 0; - sc->mii_flags &= ~MIIF_DOINGAUTO; - sc->mii_flags |= MIIF_AUTOTIMEOUT; - } - } - - sc->mii_flags &= ~MIIF_DOINGAUTO; - - /* - * Check to see if we have link. If we do, we don't - * need to restart the autonegotiation process. Read - * the BMSR twice in case it's latched. - */ reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & (DC_TSTAT_LS10|DC_TSTAT_LS100); - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX && - !(reg & DC_TSTAT_LS100)) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T && - !(reg & DC_TSTAT_LS10)) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE && - (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (CSR_READ_4(dc_sc, DC_ISR) & DC_ISR_LINKGOOD) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } + if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) + return(0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 50) + return (0); sc->mii_ticks = 0; - /*dcphy_reset(sc);*/ + /*if (DC_IS_INTEL(dc_sc))*/ + sc->mii_flags &= ~MIIF_DOINGAUTO; dcphy_auto(sc, 0); break; @@ -394,7 +359,7 @@ dcphy_status(sc) struct mii_softc *sc; { struct mii_data *mii = sc->mii_pdata; - int reg, anlpar; + int reg, anlpar, tstat = 0; struct dc_softc *dc_sc; dc_sc = mii->mii_ifp->if_softc; @@ -403,32 +368,29 @@ dcphy_status(sc) mii->mii_media_active = IFM_ETHER; reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); + (DC_TSTAT_LS10|DC_TSTAT_LS100); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) mii->mii_media_status |= IFM_ACTIVE; - if (sc->mii_flags & MIIF_DOINGAUTO) { - mii->mii_media_active |= IFM_NONE; - return; - } - - if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL && - CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_ANEGSTAT) { + if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL) { /* Erg, still trying, I guess... */ - if ((CSR_READ_4(dc_sc, DC_10BTSTAT) & - DC_ASTAT_AUTONEGCMP) != DC_ASTAT_AUTONEGCMP) { + tstat = CSR_READ_4(dc_sc, DC_10BTSTAT); + if ((tstat & DC_TSTAT_ANEGSTAT) != DC_ASTAT_AUTONEGCMP) { + if ((DC_IS_MACRONIX(dc_sc) || DC_IS_PNICII(dc_sc)) && + (tstat & DC_TSTAT_ANEGSTAT) == DC_ASTAT_DISABLE) + goto skip; mii->mii_media_active |= IFM_NONE; return; } - if (CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_LP_CAN_NWAY) { - anlpar = CSR_READ_4(dc_sc, DC_10BTSTAT) >> 16; + if (tstat & DC_TSTAT_LP_CAN_NWAY) { + anlpar = tstat >> 16; if (anlpar & ANLPAR_T4 && sc->mii_capabilities & BMSR_100TXHDX) mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX_FD && - sc->mii_capabilities & BMSR_100TXHDX) + sc->mii_capabilities & BMSR_100TXFDX) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX && sc->mii_capabilities & BMSR_100TXHDX) @@ -463,6 +425,7 @@ dcphy_status(sc) return; } +skip: if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SCRAMBLER) mii->mii_media_active |= IFM_100_TX; else diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index a397fbe83b5c..5b8a01b7d289 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -1203,8 +1203,6 @@ static void dc_setcfg(sc, media) } if (IFM_SUBTYPE(media) == IFM_100_TX) { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); if (sc->dc_pmode == DC_PMODE_MII) { DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| @@ -1221,14 +1219,15 @@ static void dc_setcfg(sc, media) DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP); DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); } - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL| - DC_NETCFG_PCS|DC_NETCFG_SCRAMBLER); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); } + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); } if (IFM_SUBTYPE(media) == IFM_10_T) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); if (sc->dc_pmode == DC_PMODE_MII) { DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| @@ -1245,9 +1244,11 @@ static void dc_setcfg(sc, media) DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); } DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS); DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); } + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); } /* @@ -1513,7 +1514,7 @@ static int dc_attach(dev) case DC_DEVICEID_21143: sc->dc_type = DC_TYPE_21143; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_REDUCED_MII_POLL; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_DM9100: case DC_DEVICEID_DM9102: @@ -1538,19 +1539,23 @@ static int dc_attach(dev) case DC_DEVICEID_98713_CP: if (revision < DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713; - sc->dc_flags |= DC_REDUCED_MII_POLL; } - if (revision >= DC_REVISION_98713A) + if (revision >= DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713A; + sc->dc_flags |= DC_21143_NWAY; + } + sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; break; case DC_DEVICEID_987x5: sc->dc_type = DC_TYPE_987x5; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_82C115: sc->dc_type = DC_TYPE_PNICII; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_82C168: sc->dc_type = DC_TYPE_PNIC; @@ -2243,13 +2248,22 @@ static void dc_tick(xsc) mii = device_get_softc(sc->dc_miibus); if (sc->dc_flags & DC_REDUCED_MII_POLL) { - r = CSR_READ_4(sc, DC_ISR); - if (DC_IS_INTEL(sc)) { - if (r & DC_ISR_LINKFAIL) + if (sc->dc_flags & DC_21143_NWAY) { + r = CSR_READ_4(sc, DC_10BTSTAT); + if (IFM_SUBTYPE(mii->mii_media_active) == + IFM_100_TX && (r & DC_TSTAT_LS100)) { sc->dc_link = 0; + mii_mediachg(mii); + } + if (IFM_SUBTYPE(mii->mii_media_active) == + IFM_10_T && (r & DC_TSTAT_LS10)) { + sc->dc_link = 0; + mii_mediachg(mii); + } if (sc->dc_link == 0) mii_tick(mii); } else { + r = CSR_READ_4(sc, DC_ISR); if ((r & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT && sc->dc_cdata.dc_tx_prod == 0) mii_tick(mii); @@ -2286,7 +2300,10 @@ static void dc_tick(xsc) } } - sc->dc_stat_ch = timeout(dc_tick, sc, hz); + if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) + sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); + else + sc->dc_stat_ch = timeout(dc_tick, sc, hz); splx(s); @@ -2677,7 +2694,10 @@ static void dc_init(xsc) (void)splx(s); - sc->dc_stat_ch = timeout(dc_tick, sc, hz); + if (sc->dc_flags & DC_21143_NWAY) + sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); + else + sc->dc_stat_ch = timeout(dc_tick, sc, hz); #ifdef __alpha__ if(sc->dc_srm_media) { diff --git a/sys/dev/dc/if_dcreg.h b/sys/dev/dc/if_dcreg.h index 9620e103c35e..486a2e212586 100644 --- a/sys/dev/dc/if_dcreg.h +++ b/sys/dev/dc/if_dcreg.h @@ -671,6 +671,7 @@ struct dc_softc { #define DC_TX_STORENFWD 0x00000100 #define DC_REDUCED_MII_POLL 0x00000200 #define DC_TX_INTR_ALWAYS 0x00000400 +#define DC_21143_NWAY 0x00000800 /* * register space access macros diff --git a/sys/dev/mii/dcphy.c b/sys/dev/mii/dcphy.c index a39adc50fbd9..f8a3f479cc22 100644 --- a/sys/dev/mii/dcphy.c +++ b/sys/dev/mii/dcphy.c @@ -262,6 +262,7 @@ dcphy_service(sc, mii, cmd) switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /*dcphy_reset(sc);*/ + sc->mii_flags &= ~MIIF_DOINGAUTO; (void) dcphy_auto(sc, 0); break; case IFM_100_T4: @@ -322,57 +323,21 @@ dcphy_service(sc, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); - if (sc->mii_flags & MIIF_DOINGAUTO) { - if (++sc->mii_ticks != 5) - return(0); - else { - sc->mii_ticks = 0; - sc->mii_flags &= ~MIIF_DOINGAUTO; - sc->mii_flags |= MIIF_AUTOTIMEOUT; - } - } - - sc->mii_flags &= ~MIIF_DOINGAUTO; - - /* - * Check to see if we have link. If we do, we don't - * need to restart the autonegotiation process. Read - * the BMSR twice in case it's latched. - */ reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & (DC_TSTAT_LS10|DC_TSTAT_LS100); - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX && - !(reg & DC_TSTAT_LS100)) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T && - !(reg & DC_TSTAT_LS10)) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE && - (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } else if (CSR_READ_4(dc_sc, DC_ISR) & DC_ISR_LINKGOOD) { - if (sc->mii_flags & MIIF_AUTOTIMEOUT) { - sc->mii_flags &= ~MIIF_AUTOTIMEOUT; - break; - } else - return(0); - } + if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) + return(0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 50) + return (0); sc->mii_ticks = 0; - /*dcphy_reset(sc);*/ + /*if (DC_IS_INTEL(dc_sc))*/ + sc->mii_flags &= ~MIIF_DOINGAUTO; dcphy_auto(sc, 0); break; @@ -394,7 +359,7 @@ dcphy_status(sc) struct mii_softc *sc; { struct mii_data *mii = sc->mii_pdata; - int reg, anlpar; + int reg, anlpar, tstat = 0; struct dc_softc *dc_sc; dc_sc = mii->mii_ifp->if_softc; @@ -403,32 +368,29 @@ dcphy_status(sc) mii->mii_media_active = IFM_ETHER; reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); + (DC_TSTAT_LS10|DC_TSTAT_LS100); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) mii->mii_media_status |= IFM_ACTIVE; - if (sc->mii_flags & MIIF_DOINGAUTO) { - mii->mii_media_active |= IFM_NONE; - return; - } - - if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL && - CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_ANEGSTAT) { + if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL) { /* Erg, still trying, I guess... */ - if ((CSR_READ_4(dc_sc, DC_10BTSTAT) & - DC_ASTAT_AUTONEGCMP) != DC_ASTAT_AUTONEGCMP) { + tstat = CSR_READ_4(dc_sc, DC_10BTSTAT); + if ((tstat & DC_TSTAT_ANEGSTAT) != DC_ASTAT_AUTONEGCMP) { + if ((DC_IS_MACRONIX(dc_sc) || DC_IS_PNICII(dc_sc)) && + (tstat & DC_TSTAT_ANEGSTAT) == DC_ASTAT_DISABLE) + goto skip; mii->mii_media_active |= IFM_NONE; return; } - if (CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_LP_CAN_NWAY) { - anlpar = CSR_READ_4(dc_sc, DC_10BTSTAT) >> 16; + if (tstat & DC_TSTAT_LP_CAN_NWAY) { + anlpar = tstat >> 16; if (anlpar & ANLPAR_T4 && sc->mii_capabilities & BMSR_100TXHDX) mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX_FD && - sc->mii_capabilities & BMSR_100TXHDX) + sc->mii_capabilities & BMSR_100TXFDX) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX && sc->mii_capabilities & BMSR_100TXHDX) @@ -463,6 +425,7 @@ dcphy_status(sc) return; } +skip: if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SCRAMBLER) mii->mii_media_active |= IFM_100_TX; else diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index a397fbe83b5c..5b8a01b7d289 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -1203,8 +1203,6 @@ static void dc_setcfg(sc, media) } if (IFM_SUBTYPE(media) == IFM_100_TX) { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); if (sc->dc_pmode == DC_PMODE_MII) { DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| @@ -1221,14 +1219,15 @@ static void dc_setcfg(sc, media) DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP); DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); } - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL| - DC_NETCFG_PCS|DC_NETCFG_SCRAMBLER); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); } + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); } if (IFM_SUBTYPE(media) == IFM_10_T) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); if (sc->dc_pmode == DC_PMODE_MII) { DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| @@ -1245,9 +1244,11 @@ static void dc_setcfg(sc, media) DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); } DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS); DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); } + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); + DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); } /* @@ -1513,7 +1514,7 @@ static int dc_attach(dev) case DC_DEVICEID_21143: sc->dc_type = DC_TYPE_21143; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_REDUCED_MII_POLL; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_DM9100: case DC_DEVICEID_DM9102: @@ -1538,19 +1539,23 @@ static int dc_attach(dev) case DC_DEVICEID_98713_CP: if (revision < DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713; - sc->dc_flags |= DC_REDUCED_MII_POLL; } - if (revision >= DC_REVISION_98713A) + if (revision >= DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713A; + sc->dc_flags |= DC_21143_NWAY; + } + sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; break; case DC_DEVICEID_987x5: sc->dc_type = DC_TYPE_987x5; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_82C115: sc->dc_type = DC_TYPE_PNICII; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; + sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; break; case DC_DEVICEID_82C168: sc->dc_type = DC_TYPE_PNIC; @@ -2243,13 +2248,22 @@ static void dc_tick(xsc) mii = device_get_softc(sc->dc_miibus); if (sc->dc_flags & DC_REDUCED_MII_POLL) { - r = CSR_READ_4(sc, DC_ISR); - if (DC_IS_INTEL(sc)) { - if (r & DC_ISR_LINKFAIL) + if (sc->dc_flags & DC_21143_NWAY) { + r = CSR_READ_4(sc, DC_10BTSTAT); + if (IFM_SUBTYPE(mii->mii_media_active) == + IFM_100_TX && (r & DC_TSTAT_LS100)) { sc->dc_link = 0; + mii_mediachg(mii); + } + if (IFM_SUBTYPE(mii->mii_media_active) == + IFM_10_T && (r & DC_TSTAT_LS10)) { + sc->dc_link = 0; + mii_mediachg(mii); + } if (sc->dc_link == 0) mii_tick(mii); } else { + r = CSR_READ_4(sc, DC_ISR); if ((r & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT && sc->dc_cdata.dc_tx_prod == 0) mii_tick(mii); @@ -2286,7 +2300,10 @@ static void dc_tick(xsc) } } - sc->dc_stat_ch = timeout(dc_tick, sc, hz); + if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) + sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); + else + sc->dc_stat_ch = timeout(dc_tick, sc, hz); splx(s); @@ -2677,7 +2694,10 @@ static void dc_init(xsc) (void)splx(s); - sc->dc_stat_ch = timeout(dc_tick, sc, hz); + if (sc->dc_flags & DC_21143_NWAY) + sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); + else + sc->dc_stat_ch = timeout(dc_tick, sc, hz); #ifdef __alpha__ if(sc->dc_srm_media) { diff --git a/sys/pci/if_dcreg.h b/sys/pci/if_dcreg.h index 9620e103c35e..486a2e212586 100644 --- a/sys/pci/if_dcreg.h +++ b/sys/pci/if_dcreg.h @@ -671,6 +671,7 @@ struct dc_softc { #define DC_TX_STORENFWD 0x00000100 #define DC_REDUCED_MII_POLL 0x00000200 #define DC_TX_INTR_ALWAYS 0x00000400 +#define DC_21143_NWAY 0x00000800 /* * register space access macros