diff options
Diffstat (limited to 'sys/pci/if_rl.c')
-rw-r--r-- | sys/pci/if_rl.c | 227 |
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; |