summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_rl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_rl.c')
-rw-r--r--sys/pci/if_rl.c227
1 files changed, 46 insertions, 181 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 87c2fc8..19b84d2 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
@@ -130,7 +131,7 @@ MODULE_DEPEND(rl, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static struct rl_type rl_devs[] = {
+static const struct rl_type const rl_devs[] = {
{ RT_VENDORID, RT_DEVICEID_8129, RL_8129,
"RealTek 8129 10/100BaseTX" },
{ RT_VENDORID, RT_DEVICEID_8139, RL_8139,
@@ -187,10 +188,6 @@ static int rl_ioctl(struct ifnet *, u_long, caddr_t);
static void rl_intr(void *);
static void rl_init(void *);
static void rl_init_locked(struct rl_softc *sc);
-static void rl_mii_send(struct rl_softc *, uint32_t, int);
-static void rl_mii_sync(struct rl_softc *);
-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_miibus_readreg(device_t, int, int);
static void rl_miibus_statchg(device_t);
static int rl_miibus_writereg(device_t, int, int, int);
@@ -215,6 +212,24 @@ static void rl_watchdog(struct rl_softc *);
static void rl_setwol(struct rl_softc *);
static void rl_clrwol(struct rl_softc *);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t rl_mii_bitbang_read(device_t);
+static void rl_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops rl_mii_bitbang_ops = {
+ rl_mii_bitbang_read,
+ rl_mii_bitbang_write,
+ {
+ RL_MII_DATAOUT, /* MII_BIT_MDO */
+ RL_MII_DATAIN, /* MII_BIT_MDI */
+ RL_MII_CLK, /* MII_BIT_MDC */
+ RL_MII_DIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t rl_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, rl_probe),
@@ -340,181 +355,43 @@ rl_read_eeprom(struct rl_softc *sc, uint8_t *dest, int off, int cnt, int swap)
}
/*
- * MII access routines are provided for the 8129, which
- * doesn't have a built-in PHY. For the 8139, we fake things
- * up by diverting rl_phy_readreg()/rl_phy_writereg() to the
- * direct access PHY registers.
- */
-#define MII_SET(x) \
- CSR_WRITE_1(sc, RL_MII, \
- CSR_READ_1(sc, RL_MII) | (x))
-
-#define MII_CLR(x) \
- CSR_WRITE_1(sc, RL_MII, \
- CSR_READ_1(sc, RL_MII) & ~(x))
-
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-rl_mii_sync(struct rl_softc *sc)
-{
- register int i;
-
- MII_SET(RL_MII_DIR|RL_MII_DATAOUT);
-
- for (i = 0; i < 32; i++) {
- MII_SET(RL_MII_CLK);
- DELAY(1);
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- }
-}
-
-/*
- * Clock a series of bits through the MII.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static void
-rl_mii_send(struct rl_softc *sc, uint32_t bits, int cnt)
+static uint32_t
+rl_mii_bitbang_read(device_t dev)
{
- int i;
-
- MII_CLR(RL_MII_CLK);
+ struct rl_softc *sc;
+ uint32_t val;
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- MII_SET(RL_MII_DATAOUT);
- } else {
- MII_CLR(RL_MII_DATAOUT);
- }
- DELAY(1);
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- MII_SET(RL_MII_CLK);
- }
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-rl_mii_readreg(struct rl_softc *sc, struct rl_mii_frame *frame)
-{
- int i, ack;
-
- /* Set up frame for RX. */
- frame->mii_stdelim = RL_MII_STARTDELIM;
- frame->mii_opcode = RL_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- CSR_WRITE_2(sc, RL_MII, 0);
-
- /* Turn on data xmit. */
- MII_SET(RL_MII_DIR);
-
- rl_mii_sync(sc);
-
- /* Send command/address info. */
- rl_mii_send(sc, frame->mii_stdelim, 2);
- rl_mii_send(sc, frame->mii_opcode, 2);
- rl_mii_send(sc, frame->mii_phyaddr, 5);
- rl_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Idle bit */
- MII_CLR((RL_MII_CLK|RL_MII_DATAOUT));
- DELAY(1);
- MII_SET(RL_MII_CLK);
- DELAY(1);
-
- /* Turn off xmit. */
- MII_CLR(RL_MII_DIR);
-
- /* Check for ack */
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- ack = CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN;
- MII_SET(RL_MII_CLK);
- DELAY(1);
-
- /*
- * Now try reading data bits. If the ack failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- if (ack) {
- for(i = 0; i < 16; i++) {
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- MII_SET(RL_MII_CLK);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN)
- frame->mii_data |= i;
- DELAY(1);
- }
- MII_SET(RL_MII_CLK);
- DELAY(1);
- }
+ sc = device_get_softc(dev);
-fail:
- MII_CLR(RL_MII_CLK);
- DELAY(1);
- MII_SET(RL_MII_CLK);
- DELAY(1);
+ val = CSR_READ_1(sc, RL_MII);
+ CSR_BARRIER(sc, RL_MII, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return (ack ? 1 : 0);
+ return (val);
}
/*
- * Write to a PHY register through the MII.
+ * Write the MII serial port for the MII bit-bang module.
*/
-static int
-rl_mii_writereg(struct rl_softc *sc, struct rl_mii_frame *frame)
+static void
+rl_mii_bitbang_write(device_t dev, uint32_t val)
{
+ struct rl_softc *sc;
- /* Set up frame for TX. */
- frame->mii_stdelim = RL_MII_STARTDELIM;
- frame->mii_opcode = RL_MII_WRITEOP;
- frame->mii_turnaround = RL_MII_TURNAROUND;
-
- /* Turn on data output. */
- MII_SET(RL_MII_DIR);
-
- rl_mii_sync(sc);
-
- rl_mii_send(sc, frame->mii_stdelim, 2);
- rl_mii_send(sc, frame->mii_opcode, 2);
- rl_mii_send(sc, frame->mii_phyaddr, 5);
- rl_mii_send(sc, frame->mii_regaddr, 5);
- rl_mii_send(sc, frame->mii_turnaround, 2);
- rl_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- MII_SET(RL_MII_CLK);
- DELAY(1);
- MII_CLR(RL_MII_CLK);
- DELAY(1);
-
- /* Turn off xmit. */
- MII_CLR(RL_MII_DIR);
+ sc = device_get_softc(dev);
- return (0);
+ CSR_WRITE_1(sc, RL_MII, val);
+ CSR_BARRIER(sc, RL_MII, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
rl_miibus_readreg(device_t dev, int phy, int reg)
{
struct rl_softc *sc;
- struct rl_mii_frame frame;
- uint16_t rval = 0;
- uint16_t rl8139_reg = 0;
+ uint16_t rl8139_reg;
sc = device_get_softc(dev);
@@ -545,30 +422,22 @@ rl_miibus_readreg(device_t dev, int phy, int reg)
* us the results of parallel detection.
*/
case RL_MEDIASTAT:
- rval = CSR_READ_1(sc, RL_MEDIASTAT);
- return (rval);
+ return (CSR_READ_1(sc, RL_MEDIASTAT));
default:
device_printf(sc->rl_dev, "bad phy register\n");
return (0);
}
- rval = CSR_READ_2(sc, rl8139_reg);
- return (rval);
+ return (CSR_READ_2(sc, rl8139_reg));
}
- bzero((char *)&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- rl_mii_readreg(sc, &frame);
-
- return (frame.mii_data);
+ return (mii_bitbang_readreg(dev, &rl_mii_bitbang_ops, phy, reg));
}
static int
rl_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct rl_softc *sc;
- struct rl_mii_frame frame;
- uint16_t rl8139_reg = 0;
+ uint16_t rl8139_reg;
sc = device_get_softc(dev);
@@ -601,11 +470,7 @@ rl_miibus_writereg(device_t dev, int phy, int reg, int data)
return (0);
}
- bzero((char *)&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
- rl_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &rl_mii_bitbang_ops, phy, reg, data);
return (0);
}
@@ -719,7 +584,7 @@ rl_reset(struct rl_softc *sc)
static int
rl_probe(device_t dev)
{
- struct rl_type *t;
+ const struct rl_type *t;
uint16_t devid, revid, vendor;
int i;
@@ -773,7 +638,7 @@ rl_attach(device_t dev)
uint16_t as[3];
struct ifnet *ifp;
struct rl_softc *sc;
- struct rl_type *t;
+ const struct rl_type *t;
struct sysctl_ctx_list *ctx;
struct sysctl_oid_list *children;
int error = 0, hwrev, i, phy, pmc, rid;
OpenPOWER on IntegriCloud