Page MenuHomeFreeBSD

D55976.id173961.diff
No OneTemporary

D55976.id173961.diff

diff --git a/sys/dev/rge/if_rge.c b/sys/dev/rge/if_rge.c
--- a/sys/dev/rge/if_rge.c
+++ b/sys/dev/rge/if_rge.c
@@ -1443,6 +1443,54 @@
/*
* Set media options.
*/
+static int
+rge_ifmedia_upd_sds(struct rge_softc *sc)
+{
+ struct ifmedia *ifm = &sc->sc_media;
+ uint16_t val;
+
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_1000_LX:
+ /* index 0, page 1, register 31 */
+ val = rge_read_sds(sc, 0x003f);
+ val &= ~0x0008;
+ rge_write_sds(sc, 0x003f, val);
+
+ /* index 0, page 2, register 0 */
+ val = rge_read_sds(sc, 0x0040);
+ val &= ~0x3040;
+ val |= 0x0040;
+ rge_write_sds(sc, 0x0040, val);
+
+ rge_reset_sds(sc);
+ break;
+ case IFM_10G_LR:
+ case IFM_AUTO:
+ rge_reset_sds(sc);
+
+ RGE_WRITE_2(sc, 0x233a, 0x801a);
+ val = RGE_READ_2(sc, 0x233e);
+ val &= 0x3003;
+ val |= 0x1000;
+ RGE_WRITE_2(sc, 0x233e, val);
+
+ rge_write_phy_ocp(sc, 0xc40a, 0x0000);
+ rge_write_phy_ocp(sc, 0xc466, 0x0003);
+ rge_write_phy_ocp(sc, 0xc808, 0x0000);
+ rge_write_phy_ocp(sc, 0xc80a, 0x0000);
+
+ val = rge_read_phy_ocp(sc, 0xc804);
+ val &= ~0x000f;
+ val |= 0x000c;
+ rge_write_phy_ocp(sc, 0xc804, val);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
static int
rge_ifmedia_upd(if_t ifp)
{
@@ -1459,6 +1507,9 @@
if (RGE_TYPE_R26(sc) || sc->rge_type == MAC_R27)
RGE_PHY_CLRBIT(sc, 0xa5ea, 0x0007);
+ if (sc->rge_sfpmode)
+ return rge_ifmedia_upd_sds(sc);
+
val = rge_read_phy_ocp(sc, 0xa5d4);
switch (sc->rge_type) {
case MAC_R27:
@@ -1551,18 +1602,25 @@
else
ifmr->ifm_active |= IFM_HDX;
- if (status & RGE_PHYSTAT_10MBPS)
- ifmr->ifm_active |= IFM_10_T;
- else if (status & RGE_PHYSTAT_100MBPS)
- ifmr->ifm_active |= IFM_100_TX;
- else if (status & RGE_PHYSTAT_1000MBPS)
- ifmr->ifm_active |= IFM_1000_T;
- else if (status & RGE_PHYSTAT_2500MBPS)
- ifmr->ifm_active |= IFM_2500_T;
- else if (status & RGE_PHYSTAT_5000MBPS)
- ifmr->ifm_active |= IFM_5000_T;
- else if (status & RGE_PHYSTAT_10000MBPS)
- ifmr->ifm_active |= IFM_10G_T;
+ if (sc->rge_sfpmode) {
+ if (status & RGE_PHYSTAT_1000MBPS)
+ ifmr->ifm_active |= IFM_1000_LX;
+ else if (status & RGE_PHYSTAT_10000MBPS)
+ ifmr->ifm_active |= IFM_10G_LR;
+ } else {
+ if (status & RGE_PHYSTAT_10MBPS)
+ ifmr->ifm_active |= IFM_10_T;
+ else if (status & RGE_PHYSTAT_100MBPS)
+ ifmr->ifm_active |= IFM_100_TX;
+ else if (status & RGE_PHYSTAT_1000MBPS)
+ ifmr->ifm_active |= IFM_1000_T;
+ else if (status & RGE_PHYSTAT_2500MBPS)
+ ifmr->ifm_active |= IFM_2500_T;
+ else if (status & RGE_PHYSTAT_5000MBPS)
+ ifmr->ifm_active |= IFM_5000_T;
+ else if (status & RGE_PHYSTAT_10000MBPS)
+ ifmr->ifm_active |= IFM_10G_T;
+ }
}
}
@@ -2463,6 +2521,13 @@
static void
rge_add_media_types(struct rge_softc *sc)
{
+ if (sc->rge_sfpmode) {
+ /* No distinction between SX/SR and LX/LR */
+ ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_1000_LX, 0, NULL);
+ ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10G_LR, 0, NULL);
+ return;
+ }
+
ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10_T, 0, NULL);
ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_100_TX, 0, NULL);
diff --git a/sys/dev/rge/if_rge_hw.h b/sys/dev/rge/if_rge_hw.h
--- a/sys/dev/rge/if_rge_hw.h
+++ b/sys/dev/rge/if_rge_hw.h
@@ -36,6 +36,10 @@
extern uint16_t rge_read_phy(struct rge_softc *, uint16_t, uint16_t);
extern void rge_write_phy_ocp(struct rge_softc *, uint16_t, uint16_t);
extern uint16_t rge_read_phy_ocp(struct rge_softc *sc, uint16_t reg);
+extern int rge_wait_sds(struct rge_softc *);
+extern uint16_t rge_read_sds(struct rge_softc *, uint16_t);
+extern void rge_write_sds(struct rge_softc *, uint16_t, uint16_t);
+extern void rge_reset_sds(struct rge_softc *);
extern int rge_get_link_status(struct rge_softc *);
#endif /* __IF_RGE_HW_H__ */
diff --git a/sys/dev/rge/if_rge_hw.c b/sys/dev/rge/if_rge_hw.c
--- a/sys/dev/rge/if_rge_hw.c
+++ b/sys/dev/rge/if_rge_hw.c
@@ -531,6 +531,15 @@
rge_write_phy_ocp(sc, 0xa436, 0x801e);
sc->rge_rcodever = rge_read_phy_ocp(sc, 0xa438);
+ /* Get fiber mode */
+ if (sc->rge_type == MAC_R27) {
+ uint16_t data;
+
+ data = rge_read_mac_ocp(sc, 0xd006);
+ if ((data & 0xff) == RGE_SFPMODE_RTL8127ATF)
+ sc->rge_sfpmode = 1;
+ }
+
switch (sc->rge_type) {
case MAC_R25:
rge_phy_config_mac_r25(sc);
@@ -2190,6 +2199,63 @@
return (val & RGE_PHYOCP_DATA_MASK);
}
+int
+rge_wait_sds(struct rge_softc *sc)
+{
+ uint16_t tmp;
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ tmp = RGE_READ_2(sc, RGE_SDS_CMD);
+ if (tmp & RGE_SDS_CMD_IN)
+ return 1;
+ DELAY(1);
+ }
+
+ return 0;
+}
+
+uint16_t
+rge_read_sds(struct rge_softc *sc, uint16_t reg)
+{
+ uint16_t val = 0xffff;
+
+ RGE_WRITE_2(sc, RGE_SDS_ADDR, reg);
+ RGE_WRITE_2(sc, RGE_SDS_CMD, RGE_SDS_CMD_IN);
+
+ if (rge_wait_sds(sc))
+ val = RGE_READ_2(sc, RGE_SDS_DATA_OUT);
+
+ return val;
+}
+
+void
+rge_write_sds(struct rge_softc *sc, uint16_t reg, uint16_t val)
+{
+ RGE_WRITE_2(sc, RGE_SDS_DATA_IN, val);
+ RGE_WRITE_2(sc, RGE_SDS_ADDR, reg);
+ RGE_WRITE_2(sc, RGE_SDS_CMD, RGE_SDS_CMD_IN | RGE_SDS_WE_IN);
+
+ rge_wait_sds(sc);
+}
+
+void
+rge_reset_sds(struct rge_softc *sc)
+{
+ uint8_t b;
+
+ b = RGE_READ_1(sc, 0x2350);
+ b &= ~0x01;
+ RGE_WRITE_1(sc, 0x2350, b);
+ DELAY(1);
+
+ RGE_WRITE_2(sc, 0x233a, 0x801f);
+ b = RGE_READ_1(sc, 0x2350);
+ b |= 0x01;
+ RGE_WRITE_1(sc, 0x2350, b);
+ DELAY(10);
+}
+
int
rge_get_link_status(struct rge_softc *sc)
{
diff --git a/sys/dev/rge/if_rgereg.h b/sys/dev/rge/if_rgereg.h
--- a/sys/dev/rge/if_rgereg.h
+++ b/sys/dev/rge/if_rgereg.h
@@ -80,6 +80,10 @@
#define RGE_EPHYAR_EXT_ADDR 0x0ffe
#define RGE_ADDR0 0x19e0
#define RGE_ADDR1 0x19e4
+#define RGE_SDS_CMD 0x2348
+#define RGE_SDS_ADDR 0x234a
+#define RGE_SDS_DATA_IN 0x234c
+#define RGE_SDS_DATA_OUT 0x234e
#define RGE_RSS_CTRL 0x4500
#define RGE_RXQUEUE_CTRL 0x4800
#define RGE_EEE_TXIDLE_TIMER 0x6048
@@ -204,6 +208,10 @@
/* Flags for register RGE_CPLUSCMD */
#define RGE_CPLUSCMD_RXCSUM 0x0020
+/* Flags for register RGE_SDS_CMD */
+#define RGE_SDS_CMD_IN 0x0001
+#define RGE_SDS_WE_IN 0x0002
+
#define RGE_TX_NSEGS 32
#define RGE_TX_LIST_CNT 1024
diff --git a/sys/dev/rge/if_rgevar.h b/sys/dev/rge/if_rgevar.h
--- a/sys/dev/rge/if_rgevar.h
+++ b/sys/dev/rge/if_rgevar.h
@@ -194,6 +194,9 @@
#define RGE_FLAG_MSI 0x00000001
#define RGE_FLAG_PCIE 0x00000002
+ uint8_t rge_sfpmode;
+#define RGE_SFPMODE_RTL8127ATF 0x07
+
uint32_t rge_intrs;
int rge_timerintr;
#define RGE_IMTYPE_NONE 0

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 1, 9:11 PM (13 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30688907
Default Alt Text
D55976.id173961.diff (6 KB)

Event Timeline