summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_rl.c100
-rw-r--r--sys/pci/if_rlreg.h5
2 files changed, 101 insertions, 4 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 60e26e9..520759e 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -188,6 +188,8 @@ static struct rl_type rl_devs[] = {
"RealTek 8129 10/100BaseTX" },
{ RT_VENDORID, RT_DEVICEID_8139, RL_8139,
"RealTek 8139 10/100BaseTX" },
+ { RT_VENDORID, RT_DEVICEID_8169, RL_8169,
+ "RealTek 8169 10/100/1000BaseTX" },
{ RT_VENDORID, RT_DEVICEID_8138, RL_8139,
"RealTek 8139 10/100BaseTX CardBus" },
{ ACCTON_VENDORID, ACCTON_DEVICEID_5030, RL_8139,
@@ -227,8 +229,12 @@ static struct rl_hwrev rl_hwrevs[] = {
{ RL_HWREV_8139B, RL_8139, "B" },
{ RL_HWREV_8130, RL_8139, "8130" },
{ RL_HWREV_8139C, RL_8139, "C" },
- { RL_HWREV_8139D, RL_8139, "D" },
+ { RL_HWREV_8139D, RL_8139, "8139D/8100B/8100C" },
{ RL_HWREV_8139CPLUS, RL_8139CPLUS, "C+"},
+ { RL_HWREV_8169, RL_8169, "8169"},
+ { RL_HWREV_8110, RL_8169, "8169S/8110S"},
+ { RL_HWREV_8100, RL_8139, "8100"},
+ { RL_HWREV_8101, RL_8139, "8101"},
{ 0, 0, NULL }
};
@@ -273,6 +279,8 @@ static void rl_mii_sync (struct rl_softc *);
static void rl_mii_send (struct rl_softc *, u_int32_t, int);
static int rl_mii_readreg (struct rl_softc *, struct rl_mii_frame *);
static int rl_mii_writereg (struct rl_softc *, struct rl_mii_frame *);
+static int rl_gmii_readreg (device_t, int, int);
+static int rl_gmii_writereg (device_t, int, int, int);
static int rl_miibus_readreg (device_t, int, int);
static int rl_miibus_writereg (device_t, int, int, int);
@@ -668,6 +676,71 @@ rl_mii_writereg(sc, frame)
}
static int
+rl_gmii_readreg(dev, phy, reg)
+ device_t dev;
+ int phy, reg;
+{
+ struct rl_softc *sc;
+ u_int32_t rval;
+ int i;
+
+ if (phy != 1)
+ return(0);
+
+ sc = device_get_softc(dev);
+
+ CSR_WRITE_4(sc, RL_PHYAR, reg << 16);
+ DELAY(1000);
+
+ for (i = 0; i < RL_TIMEOUT; i++) {
+ rval = CSR_READ_4(sc, RL_PHYAR);
+ if (rval & RL_PHYAR_BUSY)
+ break;
+ DELAY(100);
+ }
+
+ if (i == RL_TIMEOUT) {
+ printf ("rl%d: PHY read failed\n", sc->rl_unit);
+ return (0);
+ }
+
+ return (rval & RL_PHYAR_PHYDATA);
+}
+
+static int
+rl_gmii_writereg(dev, phy, reg, data)
+ device_t dev;
+ int phy, reg, data;
+{
+ struct rl_softc *sc;
+ u_int32_t rval;
+ int i;
+
+ if (phy > 0)
+ return(0);
+
+ sc = device_get_softc(dev);
+
+ CSR_WRITE_4(sc, RL_PHYAR, (reg << 16) |
+ (data | RL_PHYAR_PHYDATA) | RL_PHYAR_BUSY);
+ DELAY(1000);
+
+ for (i = 0; i < RL_TIMEOUT; i++) {
+ rval = CSR_READ_4(sc, RL_PHYAR);
+ if (!(rval & RL_PHYAR_BUSY))
+ break;
+ DELAY(100);
+ }
+
+ if (i == RL_TIMEOUT) {
+ printf ("rl%d: PHY write failed\n", sc->rl_unit);
+ return (0);
+ }
+
+ return (0);
+}
+
+static int
rl_miibus_readreg(dev, phy, reg)
device_t dev;
int phy, reg;
@@ -680,6 +753,12 @@ rl_miibus_readreg(dev, phy, reg)
sc = device_get_softc(dev);
RL_LOCK(sc);
+ if (sc->rl_type == RL_8169) {
+ rval = rl_gmii_readreg(dev, phy, reg);
+ RL_UNLOCK(sc);
+ return (rval);
+ }
+
if (sc->rl_type == RL_8139 || sc->rl_type == RL_8139CPLUS) {
/* Pretend the internal PHY is only at address 0 */
if (phy) {
@@ -744,10 +823,17 @@ rl_miibus_writereg(dev, phy, reg, data)
struct rl_softc *sc;
struct rl_mii_frame frame;
u_int16_t rl8139_reg = 0;
+ int rval = 0;
sc = device_get_softc(dev);
RL_LOCK(sc);
+ if (sc->rl_type == RL_8169) {
+ rval = rl_gmii_writereg(dev, phy, reg, data);
+ RL_UNLOCK(sc);
+ return (rval);
+ }
+
if (sc->rl_type == RL_8139 || sc->rl_type == RL_8139CPLUS) {
/* Pretend the internal PHY is only at address 0 */
if (phy) {
@@ -903,6 +989,8 @@ rl_reset(sc)
if (i == RL_TIMEOUT)
printf("rl%d: reset never completed!\n", sc->rl_unit);
+ CSR_WRITE_1(sc, 0x82, 1);
+
return;
}
@@ -963,7 +1051,8 @@ rl_probe(dev)
if (hw_rev->rl_desc == NULL)
sprintf(desc, "%s, rev. %s",
t->rl_name, "unknown");
- }
+ } else
+ sprintf(desc, "%s", t->rl_name);
bus_release_resource(dev, RL_RES,
RL_RID, sc->rl_res);
RL_UNLOCK(sc);
@@ -1039,7 +1128,7 @@ rl_dma_map_desc(arg, segs, nseg, mapsize, error)
cmdstat |= RL_TDESC_CMD_SOF;
else
cmdstat |= RL_TDESC_CMD_OWN;
- if (idx == RL_RX_DESC_CNT)
+ if (idx == (RL_RX_DESC_CNT - 1))
cmdstat |= RL_TDESC_CMD_EOR;
d->rl_cmdstat = htole32(cmdstat);
i++;
@@ -2663,7 +2752,10 @@ rl_init(xsc)
* moderation, which dramatically improves TX frame rate.
*/
- CSR_WRITE_4(sc, RL_TIMERINT, 0x400);
+ if (sc->rl_type == RL_8169)
+ CSR_WRITE_4(sc, RL_TIMERINT_8169, 0x400);
+ else
+ CSR_WRITE_4(sc, RL_TIMERINT, 0x400);
/*
* For 8169 gigE NICs, set the max allowed RX packet
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 6af61a1..086b61b 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -120,6 +120,7 @@
/*
* Registers specific to the 8169 gigE chip
*/
+#define RL_TIMERINT_8169 0x0058 /* different offset than 8139 */
#define RL_PHYAR 0x0060
#define RL_TBICSR 0x0064
#define RL_TBI_ANAR 0x0068
@@ -138,6 +139,8 @@
#define RL_TXCFG_IFG 0x03000000 /* interframe gap */
#define RL_TXCFG_HWREV 0x7CC00000
+#define RL_HWREV_8169 0x00000000
+#define RL_HWREV_8110 0x00800000
#define RL_HWREV_8139 0x60000000
#define RL_HWREV_8139A 0x70000000
#define RL_HWREV_8139AG 0x70800000
@@ -146,6 +149,8 @@
#define RL_HWREV_8139C 0x74000000
#define RL_HWREV_8139D 0x74400000
#define RL_HWREV_8139CPLUS 0x74800000
+#define RL_HWREV_8101 0x74c00000
+#define RL_HWREV_8100 0x78800000
#define RL_TXDMA_16BYTES 0x00000000
#define RL_TXDMA_32BYTES 0x00000100
OpenPOWER on IntegriCloud