diff options
author | wpaul <wpaul@FreeBSD.org> | 2003-08-07 07:00:30 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2003-08-07 07:00:30 +0000 |
commit | ac303d03f64c15b5581bfaab905df79dfde8b9ae (patch) | |
tree | bda5f2ccbceb95cd53ff02766b5166d83da16549 /sys/pci | |
parent | f9723b9c2e612f4e2caaefebc699f5ff896dd502 (diff) | |
download | FreeBSD-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.c | 100 | ||||
-rw-r--r-- | sys/pci/if_rlreg.h | 5 |
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 |