summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2011-11-01 16:13:59 +0000
committermarius <marius@FreeBSD.org>2011-11-01 16:13:59 +0000
commitb4610d98b0096971fd87d53d90c40f4da7db34e2 (patch)
treead9ba266ea9f21e3bb8157cdc1c2c7c8b1a6b9a3 /sys/pci
parentd08a02f709c03ad61dd57d1fa39412d6de62189d (diff)
downloadFreeBSD-src-b4610d98b0096971fd87d53d90c40f4da7db34e2.zip
FreeBSD-src-b4610d98b0096971fd87d53d90c40f4da7db34e2.tar.gz
- Import the common MII bitbang'ing code from NetBSD and convert drivers to
take advantage of it instead of duplicating it. This reduces the size of the i386 GENERIC kernel by about 4k. The only potential in-tree user left unconverted is xe(4), which generally should be changed to use miibus(4) instead of implementing PHY handling on its own, as otherwise it makes not much sense to add a dependency on miibus(4)/mii_bitbang(4) to xe(4) just for the MII bitbang'ing code. The common MII bitbang'ing code also is useful in the embedded space for using GPIO pins to implement MII access. - Based on lessons learnt with dc(4) (see r185750), add bus barriers to the MII bitbang read and write functions of the other drivers converted in order to ensure the intended ordering. Given that register access via an index register as well as register bank/window switching is subject to the same problem, also add bus barriers to the respective functions of smc(4), tl(4) and xl(4). - Sprinkle some const. Thanks to the following testers: Andrew Bliznak (nge(4)), nwhitehorn@ (bm(4)), yongari@ (sis(4) and ste(4)) Thanks to Hans-Joerg Sirtl for supplying hardware to test stge(4). Reviewed by: yongari (subset of drivers) Obtained from: NetBSD (partially)
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_rl.c227
-rw-r--r--sys/pci/if_rlreg.h26
2 files changed, 52 insertions, 201 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;
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 3a9da2e..6e7c0c1 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -597,33 +597,16 @@ struct rl_type {
uint16_t rl_vid;
uint16_t rl_did;
int rl_basetype;
- char *rl_name;
+ const char *rl_name;
};
struct rl_hwrev {
uint32_t rl_rev;
int rl_type;
- char *rl_desc;
+ const char *rl_desc;
int rl_max_mtu;
};
-struct rl_mii_frame {
- uint8_t mii_stdelim;
- uint8_t mii_opcode;
- uint8_t mii_phyaddr;
- uint8_t mii_regaddr;
- uint8_t mii_turnaround;
- uint16_t mii_data;
-};
-
-/*
- * MII constants
- */
-#define RL_MII_STARTDELIM 0x01
-#define RL_MII_READOP 0x02
-#define RL_MII_WRITEOP 0x01
-#define RL_MII_TURNAROUND 0x02
-
#define RL_8129 1
#define RL_8139 2
#define RL_8139CPLUS 3
@@ -880,7 +863,7 @@ struct rl_softc {
device_t rl_miibus;
bus_dma_tag_t rl_parent_tag;
uint8_t rl_type;
- struct rl_hwrev *rl_hwrev;
+ const struct rl_hwrev *rl_hwrev;
int rl_eecmd_read;
int rl_eewidth;
int rl_txthresh;
@@ -950,6 +933,9 @@ struct rl_softc {
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->rl_btag, sc->rl_bhandle, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_space_barrier(sc->rl_btag, sc->rl_bhandle, reg, length, flags)
+
#define CSR_SETBIT_1(sc, offset, val) \
CSR_WRITE_1(sc, offset, CSR_READ_1(sc, offset) | (val))
OpenPOWER on IntegriCloud