Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150397487
D55976.id173961.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D55976.id173961.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D55976: rge: add support for RTL8127ATF with SFP+ interface
Attached
Detach File
Event Timeline
Log In to Comment