summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-08-07 07:00:30 +0000
committerwpaul <wpaul@FreeBSD.org>2003-08-07 07:00:30 +0000
commitac303d03f64c15b5581bfaab905df79dfde8b9ae (patch)
treebda5f2ccbceb95cd53ff02766b5166d83da16549 /sys/pci
parentf9723b9c2e612f4e2caaefebc699f5ff896dd502 (diff)
downloadFreeBSD-src-ac303d03f64c15b5581bfaab905df79dfde8b9ae.zip
FreeBSD-src-ac303d03f64c15b5581bfaab905df79dfde8b9ae.tar.gz
Add preliminary support for the RealTek 8169 gigE chip. Changes:
- Fix a bug in rl_dma_map_desc(): set the 'end of ring' bit in the right descriptor (DESC_CNT - 1, not DESC_CNT). The 8139C+ is limited to 64 descriptors and automatically wraps at 64 descriptors even if the EOR bit isn't set, but the 8169 NIC can have up to 1024 descriptors per ring, so we must set the wrap point in the right place. - RealTek moved the RL_TIMERINT register from offset 0x54 to 0x58 in the 8169 -- account for this. - Added rl_gmii_readreg() and rl_gmii_writereg() routines. - Fix rl_probe() to deal with the case where the base type is not RL_8139. The next step is to add jumbo buffer support. Tested with the Xterasys XN-152 NIC (hard to beat $29 for a gigE NIC).
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