summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/conf/GUMSTIX1
-rw-r--r--sys/conf/NOTES14
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/bm/if_bm.c218
-rw-r--r--sys/dev/bm/if_bmreg.h10
-rw-r--r--sys/dev/bm/if_bmvar.h12
-rw-r--r--sys/dev/dc/if_dc.c210
-rw-r--r--sys/dev/dc/if_dcreg.h22
-rw-r--r--sys/dev/mii/mii_bitbang.c180
-rw-r--r--sys/dev/mii/mii_bitbang.h54
-rw-r--r--sys/dev/nge/if_nge.c230
-rw-r--r--sys/dev/nge/if_ngereg.h24
-rw-r--r--sys/dev/sis/if_sis.c226
-rw-r--r--sys/dev/sis/if_sisreg.h19
-rw-r--r--sys/dev/smc/if_smc.c145
-rw-r--r--sys/dev/ste/if_ste.c225
-rw-r--r--sys/dev/ste/if_stereg.h22
-rw-r--r--sys/dev/stge/if_stge.c236
-rw-r--r--sys/dev/stge/if_stgereg.h20
-rw-r--r--sys/dev/tl/if_tl.c343
-rw-r--r--sys/dev/tl/if_tlreg.h37
-rw-r--r--sys/dev/wb/if_wb.c272
-rw-r--r--sys/dev/wb/if_wbreg.h22
-rw-r--r--sys/dev/xl/if_xl.c205
-rw-r--r--sys/dev/xl/if_xlreg.h32
-rw-r--r--sys/modules/mii/Makefile7
-rw-r--r--sys/pci/if_rl.c227
-rw-r--r--sys/pci/if_rlreg.h26
28 files changed, 866 insertions, 2174 deletions
diff --git a/sys/arm/conf/GUMSTIX b/sys/arm/conf/GUMSTIX
index 8017a7a..dbd658e 100644
--- a/sys/arm/conf/GUMSTIX
+++ b/sys/arm/conf/GUMSTIX
@@ -70,6 +70,7 @@ options PREEMPTION
device loop
device ether
device mii
+device mii_bitbang
device smc
device smcphy
device uart
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index ed94494..b80df35 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1846,13 +1846,15 @@ device puc
# MII bus support is required for many PCI Ethernet NICs,
# namely those which use MII-compliant transceivers or implement
# transceiver control interfaces that operate like an MII. Adding
-# "device miibus" to the kernel config pulls in support for
-# the generic miibus API and all of the PHY drivers, including a
-# generic one for PHYs that aren't specifically handled by an
-# individual driver. Support for specific PHYs may be built by adding
-# "device mii" then adding the appropriate PHY driver.
-device miibus # MII support including all PHYs
+# "device miibus" to the kernel config pulls in support for the generic
+# miibus API, the common support for for bit-bang'ing the MII and all
+# of the PHY drivers, including a generic one for PHYs that aren't
+# specifically handled by an individual driver. Support for specific
+# PHYs may be built by adding "device mii", "device mii_bitbang" if
+# needed by the NIC driver and then adding the appropriate PHY driver.
device mii # Minimal MII support
+device mii_bitbang # Common module for bit-bang'ing the MII
+device miibus # MII support w/ bit-bang'ing and all PHYs
device acphy # Altima Communications AC101
device amphy # AMD AM79c873 / Davicom DM910{1,2}
diff --git a/sys/conf/files b/sys/conf/files
index 90e7b76..e6dfe63 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1425,6 +1425,7 @@ dev/mii/ip1000phy.c optional miibus | ip1000phy
dev/mii/jmphy.c optional miibus | jmphy
dev/mii/lxtphy.c optional miibus | lxtphy
dev/mii/mii.c optional miibus | mii
+dev/mii/mii_bitbang.c optional miibus | mii_bitbang
dev/mii/mii_physubr.c optional miibus | mii
dev/mii/miibus_if.m optional miibus | mii
dev/mii/mlphy.c optional miibus | mlphy
diff --git a/sys/dev/bm/if_bm.c b/sys/dev/bm/if_bm.c
index 1977f92..c478e7b 100644
--- a/sys/dev/bm/if_bm.c
+++ b/sys/dev/bm/if_bm.c
@@ -63,6 +63,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/ofw/ofw_bus.h>
@@ -105,17 +106,28 @@ static void bm_tick (void *xsc);
static int bm_ifmedia_upd (struct ifnet *);
static void bm_ifmedia_sts (struct ifnet *, struct ifmediareq *);
-static void bm_miicsr_dwrite (struct bm_softc *, u_int16_t);
-static void bm_mii_writebit (struct bm_softc *, int);
-static int bm_mii_readbit (struct bm_softc *);
-static void bm_mii_sync (struct bm_softc *);
-static void bm_mii_send (struct bm_softc *, u_int32_t, int);
-static int bm_mii_readreg (struct bm_softc *, struct bm_mii_frame *);
-static int bm_mii_writereg (struct bm_softc *, struct bm_mii_frame *);
static int bm_miibus_readreg (device_t, int, int);
static int bm_miibus_writereg (device_t, int, int, int);
static void bm_miibus_statchg (device_t);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t bm_mii_bitbang_read(device_t);
+static void bm_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops bm_mii_bitbang_ops = {
+ bm_mii_bitbang_read,
+ bm_mii_bitbang_write,
+ {
+ BM_MII_DATAOUT, /* MII_BIT_MDO */
+ BM_MII_DATAIN, /* MII_BIT_MDI */
+ BM_MII_CLK, /* MII_BIT_MDC */
+ BM_MII_OENABLE, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t bm_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bm_probe),
@@ -150,171 +162,36 @@ DRIVER_MODULE(miibus, bm, miibus_driver, miibus_devclass, 0, 0);
*/
/*
- * Write to the MII csr, introducing a delay to allow valid
- * MII clock pulses to be formed
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-bm_miicsr_dwrite(struct bm_softc *sc, u_int16_t val)
-{
- CSR_WRITE_2(sc, BM_MII_CSR, val);
- /*
- * Assume this is a clock toggle and generate a 1us delay
- * to cover both MII's 160ns high/low minimum and 400ns
- * cycle miniumum
- */
- DELAY(1);
-}
-
-/*
- * Write a bit to the MII bus.
- */
-static void
-bm_mii_writebit(struct bm_softc *sc, int bit)
-{
- u_int16_t regval;
-
- regval = BM_MII_OENABLE;
- if (bit)
- regval |= BM_MII_DATAOUT;
-
- bm_miicsr_dwrite(sc, regval);
- bm_miicsr_dwrite(sc, regval | BM_MII_CLK);
- bm_miicsr_dwrite(sc, regval);
-}
-
-/*
- * Read a bit from the MII bus.
- */
-static int
-bm_mii_readbit(struct bm_softc *sc)
-{
- u_int16_t regval, bitin;
-
- /* ~BM_MII_OENABLE */
- regval = 0;
-
- bm_miicsr_dwrite(sc, regval);
- bm_miicsr_dwrite(sc, regval | BM_MII_CLK);
- bm_miicsr_dwrite(sc, regval);
- bitin = CSR_READ_2(sc, BM_MII_CSR) & BM_MII_DATAIN;
-
- return (bitin == BM_MII_DATAIN);
-}
-
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-bm_mii_sync(struct bm_softc *sc)
-{
- int i;
- u_int16_t regval;
-
- regval = BM_MII_OENABLE | BM_MII_DATAOUT;
-
- bm_miicsr_dwrite(sc, regval);
- for (i = 0; i < 32; i++) {
- bm_miicsr_dwrite(sc, regval | BM_MII_CLK);
- bm_miicsr_dwrite(sc, regval);
- }
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-bm_mii_send(struct bm_softc *sc, u_int32_t bits, int cnt)
-{
- int i;
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1)
- bm_mii_writebit(sc, bits & i);
-}
-
-/*
- * Read a PHY register through the MII.
- */
-static int
-bm_mii_readreg(struct bm_softc *sc, struct bm_mii_frame *frame)
+bm_mii_bitbang_write(device_t dev, uint32_t val)
{
- int i, ack, bit;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = BM_MII_STARTDELIM;
- frame->mii_opcode = BM_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- /*
- * Sync the PHYs
- */
- bm_mii_sync(sc);
-
- /*
- * Send command/address info
- */
- bm_mii_send(sc, frame->mii_stdelim, 2);
- bm_mii_send(sc, frame->mii_opcode, 2);
- bm_mii_send(sc, frame->mii_phyaddr, 5);
- bm_mii_send(sc, frame->mii_regaddr, 5);
-
- /*
- * Check for ack.
- */
- ack = bm_mii_readbit(sc);
-
- /*
- * Now try reading data bits. If the ack failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- for (i = 0x8000; i; i >>= 1) {
- bit = bm_mii_readbit(sc);
- if (!ack && bit)
- frame->mii_data |= i;
- }
+ struct bm_softc *sc;
- /*
- * Skip through idle bit-times
- */
- bm_mii_writebit(sc, 0);
- bm_mii_writebit(sc, 0);
+ sc = device_get_softc(dev);
- return ((ack) ? 1 : 0);
+ CSR_WRITE_2(sc, BM_MII_CSR, val);
+ CSR_BARRIER(sc, BM_MII_CSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
/*
- * Write to a PHY register through the MII.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static int
-bm_mii_writereg(struct bm_softc *sc, struct bm_mii_frame *frame)
+static uint32_t
+bm_mii_bitbang_read(device_t dev)
{
- /*
- * Set up frame for tx
- */
- frame->mii_stdelim = BM_MII_STARTDELIM;
- frame->mii_opcode = BM_MII_WRITEOP;
- frame->mii_turnaround = BM_MII_TURNAROUND;
-
- /*
- * Sync the phy and start the bitbang write sequence
- */
- bm_mii_sync(sc);
+ struct bm_softc *sc;
+ uint32_t reg;
- bm_mii_send(sc, frame->mii_stdelim, 2);
- bm_mii_send(sc, frame->mii_opcode, 2);
- bm_mii_send(sc, frame->mii_phyaddr, 5);
- bm_mii_send(sc, frame->mii_regaddr, 5);
- bm_mii_send(sc, frame->mii_turnaround, 2);
- bm_mii_send(sc, frame->mii_data, 16);
+ sc = device_get_softc(dev);
- /*
- * Idle bit.
- */
- bm_mii_writebit(sc, 0);
+ reg = CSR_READ_2(sc, BM_MII_CSR);
+ CSR_BARRIER(sc, BM_MII_CSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return (0);
+ return (reg);
}
/*
@@ -323,34 +200,15 @@ bm_mii_writereg(struct bm_softc *sc, struct bm_mii_frame *frame)
static int
bm_miibus_readreg(device_t dev, int phy, int reg)
{
- struct bm_softc *sc;
- struct bm_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- bm_mii_readreg(sc, &frame);
-
- return (frame.mii_data);
+ return (mii_bitbang_readreg(dev, &bm_mii_bitbang_ops, phy, reg));
}
static int
bm_miibus_writereg(device_t dev, int phy, int reg, int data)
{
- struct bm_softc *sc;
- struct bm_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
- bm_mii_writereg(sc, &frame);
+ mii_bitbang_readreg(dev, &bm_mii_bitbang_ops, phy, reg);
return (0);
}
diff --git a/sys/dev/bm/if_bmreg.h b/sys/dev/bm/if_bmreg.h
index 15ee1fe..39d9b48 100644
--- a/sys/dev/bm/if_bmreg.h
+++ b/sys/dev/bm/if_bmreg.h
@@ -129,14 +129,6 @@
#define BM_MII_DATAIN 0x0008 /* MDIO data in */
/*
- * MII constants
- */
-#define BM_MII_STARTDELIM 0x01
-#define BM_MII_READOP 0x02
-#define BM_MII_WRITEOP 0x01
-#define BM_MII_TURNAROUND 0x02
-
-/*
* Various flags
*/
@@ -174,3 +166,5 @@
#define CSR_READ_1(sc, reg) \
bus_read_1(sc->sc_memr, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_barrier(sc->sc_memr, reg, length, flags)
diff --git a/sys/dev/bm/if_bmvar.h b/sys/dev/bm/if_bmvar.h
index 7d31489..b50d65b 100644
--- a/sys/dev/bm/if_bmvar.h
+++ b/sys/dev/bm/if_bmvar.h
@@ -46,7 +46,6 @@
/*
* software state for transmit job mbufs (may be elements of mbuf chains)
*/
-
struct bm_txsoft {
struct mbuf *txs_mbuf; /* head of our mbuf chain */
bus_dmamap_t txs_dmamap; /* our DMA map */
@@ -71,7 +70,6 @@ struct bm_rxsoft {
bus_dma_segment_t segment;
};
-
struct bm_softc {
struct ifnet *sc_ifp;
struct mtx sc_mtx;
@@ -113,13 +111,3 @@ struct bm_softc {
dbdma_channel_t *sc_txdma, *sc_rxdma;
};
-
-struct bm_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
-};
-
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 184fa8f..57acb39 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -122,6 +122,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>
@@ -149,7 +150,7 @@ MODULE_DEPEND(dc, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static const struct dc_type dc_devs[] = {
+static const struct dc_type const dc_devs[] = {
{ DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143), 0,
"Intel 21143 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009), 0,
@@ -272,12 +273,6 @@ static void dc_eeprom_getword_xircom(struct dc_softc *, int, uint16_t *);
static void dc_eeprom_width(struct dc_softc *);
static void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int);
-static void dc_mii_writebit(struct dc_softc *, int);
-static int dc_mii_readbit(struct dc_softc *);
-static void dc_mii_sync(struct dc_softc *);
-static void dc_mii_send(struct dc_softc *, uint32_t, int);
-static int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *);
-static int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *);
static int dc_miibus_readreg(device_t, int, int);
static int dc_miibus_writereg(device_t, int, int, int);
static void dc_miibus_statchg(device_t);
@@ -307,6 +302,24 @@ static int dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
static void dc_apply_fixup(struct dc_softc *, int);
static int dc_check_multiport(struct dc_softc *);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t dc_mii_bitbang_read(device_t);
+static void dc_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops dc_mii_bitbang_ops = {
+ dc_mii_bitbang_read,
+ dc_mii_bitbang_write,
+ {
+ DC_SIO_MII_DATAOUT, /* MII_BIT_MDO */
+ DC_SIO_MII_DATAIN, /* MII_BIT_MDI */
+ DC_SIO_MII_CLK, /* MII_BIT_MDC */
+ 0, /* MII_BIT_DIR_HOST_PHY */
+ DC_SIO_MII_DIR, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
#ifdef DC_USEIOSPACE
#define DC_RES SYS_RES_IOPORT
#define DC_RID DC_PCI_CFBIO
@@ -611,185 +624,45 @@ dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
}
/*
- * The following two routines are taken from the Macronix 98713
- * Application Notes pp.19-21.
- */
-/*
- * Write a bit to the MII bus.
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-dc_mii_writebit(struct dc_softc *sc, int bit)
+dc_mii_bitbang_write(device_t dev, uint32_t val)
{
- uint32_t reg;
+ struct dc_softc *sc;
- reg = DC_SIO_ROMCTL_WRITE | (bit != 0 ? DC_SIO_MII_DATAOUT : 0);
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
+ sc = device_get_softc(dev);
- CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
+ CSR_WRITE_4(sc, DC_SIO, val);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
}
/*
- * Read a bit from the MII bus.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static int
-dc_mii_readbit(struct dc_softc *sc)
+static uint32_t
+dc_mii_bitbang_read(device_t dev)
{
- uint32_t reg;
-
- reg = DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR;
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- (void)CSR_READ_4(sc, DC_SIO);
- CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN)
- return (1);
-
- return (0);
-}
+ struct dc_softc *sc;
+ uint32_t val;
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-dc_mii_sync(struct dc_softc *sc)
-{
- int i;
+ sc = device_get_softc(dev);
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
+ val = CSR_READ_4(sc, DC_SIO);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- for (i = 0; i < 32; i++)
- dc_mii_writebit(sc, 1);
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-dc_mii_send(struct dc_softc *sc, uint32_t bits, int cnt)
-{
- int i;
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1)
- dc_mii_writebit(sc, bits & i);
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
- int i;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_READOP;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
-
- /*
- * Now try reading data bits. If the turnaround failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- frame->mii_turnaround = dc_mii_readbit(sc);
- if (frame->mii_turnaround != 0) {
- for (i = 0; i < 16; i++)
- dc_mii_readbit(sc);
- goto fail;
- }
- for (i = 0x8000; i; i >>= 1) {
- if (dc_mii_readbit(sc))
- frame->mii_data |= i;
- }
-
-fail:
-
- /* Clock the idle bits. */
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- if (frame->mii_turnaround != 0)
- return (1);
- return (0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
-
- /*
- * Set up frame for TX.
- */
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_WRITEOP;
- frame->mii_turnaround = DC_MII_TURNAROUND;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
- dc_mii_send(sc, frame->mii_turnaround, 2);
- dc_mii_send(sc, frame->mii_data, 16);
-
- /* Clock the idle bits. */
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- return (0);
+ return (val);
}
static int
dc_miibus_readreg(device_t dev, int phy, int reg)
{
- struct dc_mii_frame frame;
- struct dc_softc *sc;
+ struct dc_softc *sc;
int i, rval, phy_reg = 0;
sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
if (sc->dc_pmode != DC_PMODE_MII) {
if (phy == (MII_NPHY - 1)) {
@@ -881,34 +754,29 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
}
rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF;
-
if (rval == 0xFFFF)
return (0);
return (rval);
}
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
- dc_mii_readreg(sc, &frame);
+ rval = mii_bitbang_readreg(dev, &dc_mii_bitbang_ops, phy, reg);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
- return (frame.mii_data);
+ return (rval);
}
static int
dc_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct dc_softc *sc;
- struct dc_mii_frame frame;
int i, phy_reg = 0;
sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
if (DC_IS_PNIC(sc)) {
CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE |
@@ -964,15 +832,11 @@ dc_miibus_writereg(device_t dev, int phy, int reg, int data)
return (0);
}
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
-
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
- dc_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &dc_mii_bitbang_ops, phy, reg, data);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
diff --git a/sys/dev/dc/if_dcreg.h b/sys/dev/dc/if_dcreg.h
index acd80c0..cbbe39f 100644
--- a/sys/dev/dc/if_dcreg.h
+++ b/sys/dev/dc/if_dcreg.h
@@ -531,27 +531,9 @@ struct dc_mediainfo {
struct dc_type {
uint32_t dc_devid;
uint8_t dc_minrev;
- char *dc_name;
+ const char *dc_name;
};
-struct dc_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 DC_MII_STARTDELIM 0x01
-#define DC_MII_READOP 0x02
-#define DC_MII_WRITEOP 0x01
-#define DC_MII_TURNAROUND 0x02
-
-
/*
* Registers specific to clone devices.
* This mainly relates to RX filter programming: not all 21x4x clones
@@ -827,7 +809,7 @@ struct dc_softc {
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->dc_btag, sc->dc_bhandle, reg)
-#define CSR_BARRIER_4(sc, reg, flags) \
+#define CSR_BARRIER_4(sc, reg, flags) \
bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
#define DC_TIMEOUT 1000
diff --git a/sys/dev/mii/mii_bitbang.c b/sys/dev/mii/mii_bitbang.c
new file mode 100644
index 0000000..6a5f5dc
--- /dev/null
+++ b/sys/dev/mii/mii_bitbang.c
@@ -0,0 +1,180 @@
+/* $NetBSD: mii_bitbang.c,v 1.12 2008/05/04 17:06:09 xtraeme Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following didevlaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following didevlaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Common module for bit-bang'ing the MII.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
+
+MODULE_VERSION(mii_bitbang, 1);
+
+static void mii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops,
+ uint32_t data, int nbits);
+
+#define MWRITE(x) \
+do { \
+ ops->mbo_write(dev, (x)); \
+ DELAY(1); \
+} while (/* CONSTCOND */ 0)
+
+#define MREAD ops->mbo_read(dev)
+
+#define MDO ops->mbo_bits[MII_BIT_MDO]
+#define MDI ops->mbo_bits[MII_BIT_MDI]
+#define MDC ops->mbo_bits[MII_BIT_MDC]
+#define MDIRPHY ops->mbo_bits[MII_BIT_DIR_HOST_PHY]
+#define MDIRHOST ops->mbo_bits[MII_BIT_DIR_PHY_HOST]
+
+/*
+ * mii_bitbang_sync:
+ *
+ * Synchronize the MII.
+ */
+void
+mii_bitbang_sync(device_t dev, mii_bitbang_ops_t ops)
+{
+ int i;
+ uint32_t v;
+
+ v = MDIRPHY | MDO;
+
+ MWRITE(v);
+ for (i = 0; i < 32; i++) {
+ MWRITE(v | MDC);
+ MWRITE(v);
+ }
+}
+
+/*
+ * mii_bitbang_sendbits:
+ *
+ * Send a series of bits to the MII.
+ */
+static void
+mii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops, uint32_t data,
+ int nbits)
+{
+ int i;
+ uint32_t v;
+
+ v = MDIRPHY;
+ MWRITE(v);
+
+ for (i = 1 << (nbits - 1); i != 0; i >>= 1) {
+ if (data & i)
+ v |= MDO;
+ else
+ v &= ~MDO;
+ MWRITE(v);
+ MWRITE(v | MDC);
+ MWRITE(v);
+ }
+}
+
+/*
+ * mii_bitbang_readreg:
+ *
+ * Read a PHY register by bit-bang'ing the MII.
+ */
+int
+mii_bitbang_readreg(device_t dev, mii_bitbang_ops_t ops, int phy, int reg)
+{
+ int i, error, val;
+
+ mii_bitbang_sync(dev, ops);
+
+ mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2);
+ mii_bitbang_sendbits(dev, ops, MII_COMMAND_READ, 2);
+ mii_bitbang_sendbits(dev, ops, phy, 5);
+ mii_bitbang_sendbits(dev, ops, reg, 5);
+
+ /* Switch direction to PHY->host, without a clock transition. */
+ MWRITE(MDIRHOST);
+
+ /* Turnaround clock. */
+ MWRITE(MDIRHOST | MDC);
+ MWRITE(MDIRHOST);
+
+ /* Check for error. */
+ error = MREAD & MDI;
+
+ /* Idle clock. */
+ MWRITE(MDIRHOST | MDC);
+ MWRITE(MDIRHOST);
+
+ val = 0;
+ for (i = 0; i < 16; i++) {
+ val <<= 1;
+ /* Read data prior to clock low-high transition. */
+ if (error == 0 && (MREAD & MDI) != 0)
+ val |= 1;
+
+ MWRITE(MDIRHOST | MDC);
+ MWRITE(MDIRHOST);
+ }
+
+ /* Set direction to host->PHY, without a clock transition. */
+ MWRITE(MDIRPHY);
+
+ return (error != 0 ? 0 : val);
+}
+
+/*
+ * mii_bitbang_writereg:
+ *
+ * Write a PHY register by bit-bang'ing the MII.
+ */
+void
+mii_bitbang_writereg(device_t dev, mii_bitbang_ops_t ops, int phy, int reg,
+ int val)
+{
+
+ mii_bitbang_sync(dev, ops);
+
+ mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2);
+ mii_bitbang_sendbits(dev, ops, MII_COMMAND_WRITE, 2);
+ mii_bitbang_sendbits(dev, ops, phy, 5);
+ mii_bitbang_sendbits(dev, ops, reg, 5);
+ mii_bitbang_sendbits(dev, ops, MII_COMMAND_ACK, 2);
+ mii_bitbang_sendbits(dev, ops, val, 16);
+
+ MWRITE(MDIRPHY);
+}
diff --git a/sys/dev/mii/mii_bitbang.h b/sys/dev/mii/mii_bitbang.h
new file mode 100644
index 0000000..2bc7427
--- /dev/null
+++ b/sys/dev/mii/mii_bitbang.h
@@ -0,0 +1,54 @@
+/* $NetBSD: mii_bitbang.h,v 1.6 2009/05/12 14:31:27 cegger Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define MII_BIT_MDO 0 /* data out (host->PHY) */
+#define MII_BIT_MDI 1 /* data in (PHY->host) */
+#define MII_BIT_MDC 2 /* clock */
+#define MII_BIT_DIR_HOST_PHY 3 /* set direction: host->PHY */
+#define MII_BIT_DIR_PHY_HOST 4 /* set direction: PHY->host */
+#define MII_NBITS 5
+
+struct mii_bitbang_ops {
+ uint32_t (*mbo_read)(device_t);
+ void (*mbo_write)(device_t, uint32_t);
+ uint32_t mbo_bits[MII_NBITS];
+};
+
+typedef const struct mii_bitbang_ops *mii_bitbang_ops_t;
+
+int mii_bitbang_readreg(device_t dev, mii_bitbang_ops_t ops,
+ int phy, int reg);
+void mii_bitbang_sync(device_t dev, mii_bitbang_ops_t ops);
+void mii_bitbang_writereg(device_t dev, mii_bitbang_ops_t ops,
+ int phy, int reg, int val);
diff --git a/sys/dev/nge/if_nge.c b/sys/dev/nge/if_nge.c
index db20ad2..3d7ad63 100644
--- a/sys/dev/nge/if_nge.c
+++ b/sys/dev/nge/if_nge.c
@@ -117,6 +117,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_vlan_var.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
@@ -138,7 +139,7 @@ MODULE_DEPEND(nge, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static struct nge_type nge_devs[] = {
+static const struct nge_type const nge_devs[] = {
{ NGE_VENDORID, NGE_DEVICEID,
"National Semiconductor Gigabit Ethernet" },
{ 0, 0, NULL }
@@ -180,11 +181,6 @@ static void nge_eeprom_putbyte(struct nge_softc *, int);
static void nge_eeprom_getword(struct nge_softc *, int, uint16_t *);
static void nge_read_eeprom(struct nge_softc *, caddr_t, int, int);
-static void nge_mii_sync(struct nge_softc *);
-static void nge_mii_send(struct nge_softc *, uint32_t, int);
-static int nge_mii_readreg(struct nge_softc *, struct nge_mii_frame *);
-static int nge_mii_writereg(struct nge_softc *, struct nge_mii_frame *);
-
static int nge_miibus_readreg(device_t, int, int);
static int nge_miibus_writereg(device_t, int, int, int);
static void nge_miibus_statchg(device_t);
@@ -200,6 +196,24 @@ static void nge_sysctl_node(struct nge_softc *);
static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
static int sysctl_hw_nge_int_holdoff(SYSCTL_HANDLER_ARGS);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t nge_mii_bitbang_read(device_t);
+static void nge_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops nge_mii_bitbang_ops = {
+ nge_mii_bitbang_read,
+ nge_mii_bitbang_write,
+ {
+ NGE_MEAR_MII_DATA, /* MII_BIT_MDO */
+ NGE_MEAR_MII_DATA, /* MII_BIT_MDI */
+ NGE_MEAR_MII_CLK, /* MII_BIT_MDC */
+ NGE_MEAR_MII_DIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t nge_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nge_probe),
@@ -366,180 +380,42 @@ nge_read_eeprom(struct nge_softc *sc, caddr_t dest, int off, int cnt)
}
/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-nge_mii_sync(struct nge_softc *sc)
-{
- int i;
-
- SIO_SET(NGE_MEAR_MII_DIR|NGE_MEAR_MII_DATA);
-
- for (i = 0; i < 32; i++) {
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- }
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-nge_mii_send(struct nge_softc *sc, uint32_t bits, int cnt)
-{
- int i;
-
- SIO_CLR(NGE_MEAR_MII_CLK);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- SIO_SET(NGE_MEAR_MII_DATA);
- } else {
- SIO_CLR(NGE_MEAR_MII_DATA);
- }
- DELAY(1);
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- SIO_SET(NGE_MEAR_MII_CLK);
- }
-}
-
-/*
- * Read an PHY register through the MII.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static int
-nge_mii_readreg(struct nge_softc *sc, struct nge_mii_frame *frame)
+static uint32_t
+nge_mii_bitbang_read(device_t dev)
{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = NGE_MII_STARTDELIM;
- frame->mii_opcode = NGE_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- CSR_WRITE_4(sc, NGE_MEAR, 0);
-
- /*
- * Turn on data xmit.
- */
- SIO_SET(NGE_MEAR_MII_DIR);
-
- nge_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- nge_mii_send(sc, frame->mii_stdelim, 2);
- nge_mii_send(sc, frame->mii_opcode, 2);
- nge_mii_send(sc, frame->mii_phyaddr, 5);
- nge_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Idle bit */
- SIO_CLR((NGE_MEAR_MII_CLK|NGE_MEAR_MII_DATA));
- DELAY(1);
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
-
- /* Turn off xmit. */
- SIO_CLR(NGE_MEAR_MII_DIR);
- /* Check for ack */
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- ack = CSR_READ_4(sc, NGE_MEAR) & NGE_MEAR_MII_DATA;
- SIO_SET(NGE_MEAR_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++) {
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_4(sc, NGE_MEAR) & NGE_MEAR_MII_DATA)
- frame->mii_data |= i;
- DELAY(1);
- }
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
- }
+ struct nge_softc *sc;
+ uint32_t val;
-fail:
+ sc = device_get_softc(dev);
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
+ val = CSR_READ_4(sc, NGE_MEAR);
+ CSR_BARRIER_4(sc, NGE_MEAR,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (ack)
- return (1);
- return (0);
+ return (val);
}
/*
- * Write to a PHY register through the MII.
+ * Write the MII serial port for the MII bit-bang module.
*/
-static int
-nge_mii_writereg(struct nge_softc *sc, struct nge_mii_frame *frame)
+static void
+nge_mii_bitbang_write(device_t dev, uint32_t val)
{
+ struct nge_softc *sc;
- /*
- * Set up frame for TX.
- */
-
- frame->mii_stdelim = NGE_MII_STARTDELIM;
- frame->mii_opcode = NGE_MII_WRITEOP;
- frame->mii_turnaround = NGE_MII_TURNAROUND;
-
- /*
- * Turn on data output.
- */
- SIO_SET(NGE_MEAR_MII_DIR);
-
- nge_mii_sync(sc);
-
- nge_mii_send(sc, frame->mii_stdelim, 2);
- nge_mii_send(sc, frame->mii_opcode, 2);
- nge_mii_send(sc, frame->mii_phyaddr, 5);
- nge_mii_send(sc, frame->mii_regaddr, 5);
- nge_mii_send(sc, frame->mii_turnaround, 2);
- nge_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- SIO_SET(NGE_MEAR_MII_CLK);
- DELAY(1);
- SIO_CLR(NGE_MEAR_MII_CLK);
- DELAY(1);
-
- /*
- * Turn off xmit.
- */
- SIO_CLR(NGE_MEAR_MII_DIR);
+ sc = device_get_softc(dev);
- return (0);
+ CSR_WRITE_4(sc, NGE_MEAR, val);
+ CSR_BARRIER_4(sc, NGE_MEAR,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
nge_miibus_readreg(device_t dev, int phy, int reg)
{
struct nge_softc *sc;
- struct nge_mii_frame frame;
int rv;
sc = device_get_softc(dev);
@@ -583,20 +459,13 @@ nge_miibus_readreg(device_t dev, int phy, int reg)
return (CSR_READ_4(sc, reg));
}
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- nge_mii_readreg(sc, &frame);
-
- return (frame.mii_data);
+ return (mii_bitbang_readreg(dev, &nge_mii_bitbang_ops, phy, reg));
}
static int
nge_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct nge_softc *sc;
- struct nge_mii_frame frame;
sc = device_get_softc(dev);
if ((sc->nge_flags & NGE_FLAG_TBI) != 0) {
@@ -633,12 +502,7 @@ nge_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;
- nge_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &nge_mii_bitbang_ops, phy, reg, data);
return (0);
}
@@ -813,7 +677,7 @@ nge_rxfilter(struct nge_softc *sc)
rxfilt = CSR_READ_4(sc, NGE_RXFILT_CTL);
rxfilt &= ~NGE_RXFILTCTL_ENABLE;
CSR_WRITE_4(sc, NGE_RXFILT_CTL, rxfilt);
- CSR_BARRIER_WRITE_4(sc, NGE_RXFILT_CTL);
+ CSR_BARRIER_4(sc, NGE_RXFILT_CTL, BUS_SPACE_BARRIER_WRITE);
rxfilt &= ~(NGE_RXFILTCTL_ALLMULTI | NGE_RXFILTCTL_ALLPHYS);
rxfilt &= ~NGE_RXFILTCTL_BROAD;
@@ -882,7 +746,7 @@ done:
/* Turn the receive filter on. */
rxfilt |= NGE_RXFILTCTL_ENABLE;
CSR_WRITE_4(sc, NGE_RXFILT_CTL, rxfilt);
- CSR_BARRIER_WRITE_4(sc, NGE_RXFILT_CTL);
+ CSR_BARRIER_4(sc, NGE_RXFILT_CTL, BUS_SPACE_BARRIER_WRITE);
}
static void
@@ -932,7 +796,7 @@ nge_reset(struct nge_softc *sc)
static int
nge_probe(device_t dev)
{
- struct nge_type *t;
+ const struct nge_type *t;
t = nge_devs;
@@ -2216,7 +2080,7 @@ nge_init_locked(struct nge_softc *sc)
/* Disable Rx filter prior to programming Rx filter. */
CSR_WRITE_4(sc, NGE_RXFILT_CTL, 0);
- CSR_BARRIER_WRITE_4(sc, NGE_RXFILT_CTL);
+ CSR_BARRIER_4(sc, NGE_RXFILT_CTL, BUS_SPACE_BARRIER_WRITE);
mii = device_get_softc(sc->nge_miibus);
@@ -2704,12 +2568,12 @@ nge_wol(struct nge_softc *sc)
* (i.e. Silent Rx mode.)
*/
CSR_WRITE_4(sc, NGE_RX_LISTPTR_HI, 0);
- CSR_BARRIER_WRITE_4(sc, NGE_RX_LISTPTR_HI);
+ CSR_BARRIER_4(sc, NGE_RX_LISTPTR_HI, BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_4(sc, NGE_RX_LISTPTR_LO, 0);
- CSR_BARRIER_WRITE_4(sc, NGE_RX_LISTPTR_LO);
+ CSR_BARRIER_4(sc, NGE_RX_LISTPTR_LO, BUS_SPACE_BARRIER_WRITE);
/* Enable Rx again. */
NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RX_ENABLE);
- CSR_BARRIER_WRITE_4(sc, NGE_CSR);
+ CSR_BARRIER_4(sc, NGE_CSR, BUS_SPACE_BARRIER_WRITE);
/* Configure WOL events. */
reg = 0;
diff --git a/sys/dev/nge/if_ngereg.h b/sys/dev/nge/if_ngereg.h
index 4ad1bf9..9df0d92 100644
--- a/sys/dev/nge/if_ngereg.h
+++ b/sys/dev/nge/if_ngereg.h
@@ -611,26 +611,9 @@ struct nge_ring_data {
struct nge_type {
uint16_t nge_vid;
uint16_t nge_did;
- char *nge_name;
+ const char *nge_name;
};
-struct nge_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 NGE_MII_STARTDELIM 0x01
-#define NGE_MII_READOP 0x02
-#define NGE_MII_WRITEOP 0x01
-#define NGE_MII_TURNAROUND 0x02
-
#define NGE_JUMBO_FRAMELEN 9022
#define NGE_JUMBO_MTU \
(NGE_JUMBO_FRAMELEN - sizeof(struct ether_vlan_header) - ETHER_CRC_LEN)
@@ -691,8 +674,9 @@ struct nge_softc {
*/
#define CSR_WRITE_4(sc, reg, val) \
bus_write_4((sc)->nge_res, reg, val)
-#define CSR_BARRIER_WRITE_4(sc, reg) \
- bus_barrier((sc)->nge_res, reg, 4, BUS_SPACE_BARRIER_WRITE)
+
+#define CSR_BARRIER_4(sc, reg, flags) \
+ bus_barrier((sc)->nge_res, reg, 4, flags)
#define CSR_READ_4(sc, reg) \
bus_read_4((sc)->nge_res, reg)
diff --git a/sys/dev/sis/if_sis.c b/sys/dev/sis/if_sis.c
index d0be783..630281d 100644
--- a/sys/dev/sis/if_sis.c
+++ b/sys/dev/sis/if_sis.c
@@ -90,6 +90,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>
@@ -119,10 +120,13 @@ MODULE_DEPEND(sis, miibus, 1, 1, 1);
#define CSR_READ_2(sc, reg) bus_read_2(sc->sis_res[0], reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_barrier(sc->sis_res[0], reg, length, flags)
+
/*
* Various supported device vendors/types and their names.
*/
-static struct sis_type sis_devs[] = {
+static const struct sis_type const sis_devs[] = {
{ SIS_VENDORID, SIS_DEVICEID_900, "SiS 900 10/100BaseTX" },
{ SIS_VENDORID, SIS_DEVICEID_7016, "SiS 7016 10/100BaseTX" },
{ NS_VENDORID, NS_DEVICEID_DP83815, "NatSemi DP8381[56] 10/100BaseTX" },
@@ -145,6 +149,8 @@ static void sis_init(void *);
static void sis_initl(struct sis_softc *);
static void sis_intr(void *);
static int sis_ioctl(struct ifnet *, u_long, caddr_t);
+static uint32_t sis_mii_bitbang_read(device_t);
+static void sis_mii_bitbang_write(device_t, uint32_t);
static int sis_newbuf(struct sis_softc *, struct sis_rxdesc *);
static int sis_resume(device_t);
static int sis_rxeof(struct sis_softc *);
@@ -159,6 +165,20 @@ static void sis_add_sysctls(struct sis_softc *);
static void sis_watchdog(struct sis_softc *);
static void sis_wol(struct sis_softc *);
+/*
+ * MII bit-bang glue
+ */
+static const struct mii_bitbang_ops sis_mii_bitbang_ops = {
+ sis_mii_bitbang_read,
+ sis_mii_bitbang_write,
+ {
+ SIS_MII_DATA, /* MII_BIT_MDO */
+ SIS_MII_DATA, /* MII_BIT_MDI */
+ SIS_MII_CLK, /* MII_BIT_MDC */
+ SIS_MII_DIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
static struct resource_spec sis_res_spec[] = {
#ifdef SIS_USEIOSPACE
@@ -412,179 +432,41 @@ sis_read_mac(struct sis_softc *sc, device_t dev, caddr_t dest)
#endif
/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static void
-sis_mii_sync(struct sis_softc *sc)
+static uint32_t
+sis_mii_bitbang_read(device_t dev)
{
- int i;
+ struct sis_softc *sc;
+ uint32_t val;
- SIO_SET(SIS_MII_DIR|SIS_MII_DATA);
+ sc = device_get_softc(dev);
- for (i = 0; i < 32; i++) {
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- }
+ val = CSR_READ_4(sc, SIS_EECTL);
+ CSR_BARRIER(sc, SIS_EECTL, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ return (val);
}
/*
- * Clock a series of bits through the MII.
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-sis_mii_send(struct sis_softc *sc, uint32_t bits, int cnt)
-{
- int i;
-
- SIO_CLR(SIS_MII_CLK);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- SIO_SET(SIS_MII_DATA);
- } else {
- SIO_CLR(SIS_MII_DATA);
- }
- DELAY(1);
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- SIO_SET(SIS_MII_CLK);
- }
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-sis_mii_readreg(struct sis_softc *sc, struct sis_mii_frame *frame)
+sis_mii_bitbang_write(device_t dev, uint32_t val)
{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = SIS_MII_STARTDELIM;
- frame->mii_opcode = SIS_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- /*
- * Turn on data xmit.
- */
- SIO_SET(SIS_MII_DIR);
-
- sis_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- sis_mii_send(sc, frame->mii_stdelim, 2);
- sis_mii_send(sc, frame->mii_opcode, 2);
- sis_mii_send(sc, frame->mii_phyaddr, 5);
- sis_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Idle bit */
- SIO_CLR((SIS_MII_CLK|SIS_MII_DATA));
- DELAY(1);
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
-
- /* Turn off xmit. */
- SIO_CLR(SIS_MII_DIR);
-
- /* Check for ack */
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- ack = CSR_READ_4(sc, SIS_EECTL) & SIS_MII_DATA;
- SIO_SET(SIS_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++) {
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_4(sc, SIS_EECTL) & SIS_MII_DATA)
- frame->mii_data |= i;
- DELAY(1);
- }
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
- }
-
-fail:
-
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
-
- if (ack)
- return (1);
- return (0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-sis_mii_writereg(struct sis_softc *sc, struct sis_mii_frame *frame)
-{
-
- /*
- * Set up frame for TX.
- */
-
- frame->mii_stdelim = SIS_MII_STARTDELIM;
- frame->mii_opcode = SIS_MII_WRITEOP;
- frame->mii_turnaround = SIS_MII_TURNAROUND;
-
- /*
- * Turn on data output.
- */
- SIO_SET(SIS_MII_DIR);
-
- sis_mii_sync(sc);
-
- sis_mii_send(sc, frame->mii_stdelim, 2);
- sis_mii_send(sc, frame->mii_opcode, 2);
- sis_mii_send(sc, frame->mii_phyaddr, 5);
- sis_mii_send(sc, frame->mii_regaddr, 5);
- sis_mii_send(sc, frame->mii_turnaround, 2);
- sis_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- SIO_SET(SIS_MII_CLK);
- DELAY(1);
- SIO_CLR(SIS_MII_CLK);
- DELAY(1);
+ struct sis_softc *sc;
- /*
- * Turn off xmit.
- */
- SIO_CLR(SIS_MII_DIR);
+ sc = device_get_softc(dev);
- return (0);
+ CSR_WRITE_4(sc, SIS_EECTL, val);
+ CSR_BARRIER(sc, SIS_EECTL, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
sis_miibus_readreg(device_t dev, int phy, int reg)
{
struct sis_softc *sc;
- struct sis_mii_frame frame;
sc = device_get_softc(dev);
@@ -628,7 +510,8 @@ sis_miibus_readreg(device_t dev, int phy, int reg)
}
if (i == SIS_TIMEOUT) {
- device_printf(sc->sis_dev, "PHY failed to come ready\n");
+ device_printf(sc->sis_dev,
+ "PHY failed to come ready\n");
return (0);
}
@@ -638,22 +521,15 @@ sis_miibus_readreg(device_t dev, int phy, int reg)
return (0);
return (val);
- } else {
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- sis_mii_readreg(sc, &frame);
-
- return (frame.mii_data);
- }
+ } else
+ return (mii_bitbang_readreg(dev, &sis_mii_bitbang_ops, phy,
+ reg));
}
static int
sis_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct sis_softc *sc;
- struct sis_mii_frame frame;
sc = device_get_softc(dev);
@@ -686,15 +562,11 @@ sis_miibus_writereg(device_t dev, int phy, int reg, int data)
}
if (i == SIS_TIMEOUT)
- device_printf(sc->sis_dev, "PHY failed to come ready\n");
- } else {
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
- sis_mii_writereg(sc, &frame);
- }
+ device_printf(sc->sis_dev,
+ "PHY failed to come ready\n");
+ } else
+ mii_bitbang_writereg(dev, &sis_mii_bitbang_ops, phy, reg,
+ data);
return (0);
}
@@ -989,7 +861,7 @@ sis_reset(struct sis_softc *sc)
static int
sis_probe(device_t dev)
{
- struct sis_type *t;
+ const struct sis_type *t;
t = sis_devs;
diff --git a/sys/dev/sis/if_sisreg.h b/sys/dev/sis/if_sisreg.h
index c86a13d..b400806 100644
--- a/sys/dev/sis/if_sisreg.h
+++ b/sys/dev/sis/if_sisreg.h
@@ -433,26 +433,9 @@ struct sis_desc {
struct sis_type {
uint16_t sis_vid;
uint16_t sis_did;
- char *sis_name;
+ const char *sis_name;
};
-struct sis_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 SIS_MII_STARTDELIM 0x01
-#define SIS_MII_READOP 0x02
-#define SIS_MII_WRITEOP 0x01
-#define SIS_MII_TURNAROUND 0x02
-
#define SIS_TYPE_900 1
#define SIS_TYPE_7016 2
#define SIS_TYPE_83815 3
diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c
index 4aa0396..9404f56 100644
--- a/sys/dev/smc/if_smc.c
+++ b/sys/dev/smc/if_smc.c
@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
#include <dev/smc/if_smcvar.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx)
@@ -123,11 +124,33 @@ static timeout_t smc_watchdog;
static poll_handler_t smc_poll;
#endif
+/*
+ * MII bit-bang glue
+ */
+static uint32_t smc_mii_bitbang_read(device_t);
+static void smc_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops smc_mii_bitbang_ops = {
+ smc_mii_bitbang_read,
+ smc_mii_bitbang_write,
+ {
+ MGMT_MDO, /* MII_BIT_MDO */
+ MGMT_MDI, /* MII_BIT_MDI */
+ MGMT_MCLK, /* MII_BIT_MDC */
+ MGMT_MDOE, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static __inline void
smc_select_bank(struct smc_softc *sc, uint16_t bank)
{
+ bus_barrier(sc->smc_reg, BSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
bus_write_2(sc->smc_reg, BSR, bank & BSR_BANK_MASK);
+ bus_barrier(sc->smc_reg, BSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
/* Never call this when not in bank 2. */
@@ -143,35 +166,35 @@ smc_mmu_wait(struct smc_softc *sc)
}
static __inline uint8_t
-smc_read_1(struct smc_softc *sc, bus_addr_t offset)
+smc_read_1(struct smc_softc *sc, bus_size_t offset)
{
return (bus_read_1(sc->smc_reg, offset));
}
static __inline void
-smc_write_1(struct smc_softc *sc, bus_addr_t offset, uint8_t val)
+smc_write_1(struct smc_softc *sc, bus_size_t offset, uint8_t val)
{
bus_write_1(sc->smc_reg, offset, val);
}
static __inline uint16_t
-smc_read_2(struct smc_softc *sc, bus_addr_t offset)
+smc_read_2(struct smc_softc *sc, bus_size_t offset)
{
return (bus_read_2(sc->smc_reg, offset));
}
static __inline void
-smc_write_2(struct smc_softc *sc, bus_addr_t offset, uint16_t val)
+smc_write_2(struct smc_softc *sc, bus_size_t offset, uint16_t val)
{
bus_write_2(sc->smc_reg, offset, val);
}
static __inline void
-smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
+smc_read_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap,
bus_size_t count)
{
@@ -179,13 +202,21 @@ smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
}
static __inline void
-smc_write_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
+smc_write_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap,
bus_size_t count)
{
bus_write_multi_2(sc->smc_reg, offset, datap, count);
}
+static __inline void
+smc_barrier(struct smc_softc *sc, bus_size_t offset, bus_size_t length,
+ int flags)
+{
+
+ bus_barrier(sc->smc_reg, offset, length, flags);
+}
+
int
smc_probe(device_t dev)
{
@@ -900,70 +931,43 @@ smc_task_intr(void *context, int pending)
SMC_UNLOCK(sc);
}
-static u_int
-smc_mii_readbits(struct smc_softc *sc, int nbits)
+static uint32_t
+smc_mii_bitbang_read(device_t dev)
{
- u_int mgmt, mask, val;
+ struct smc_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
SMC_ASSERT_LOCKED(sc);
KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3,
- ("%s: smc_mii_readbits called with bank %d (!= 3)",
+ ("%s: smc_mii_bitbang_read called with bank %d (!= 3)",
device_get_nameunit(sc->smc_dev),
smc_read_2(sc, BSR) & BSR_BANK_MASK));
- /*
- * Set up the MGMT (aka MII) register.
- */
- mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO);
- smc_write_2(sc, MGMT, mgmt);
-
- /*
- * Read the bits in.
- */
- for (mask = 1 << (nbits - 1), val = 0; mask; mask >>= 1) {
- if (smc_read_2(sc, MGMT) & MGMT_MDI)
- val |= mask;
-
- smc_write_2(sc, MGMT, mgmt);
- DELAY(1);
- smc_write_2(sc, MGMT, mgmt | MGMT_MCLK);
- DELAY(1);
- }
+ val = smc_read_2(sc, MGMT);
+ smc_barrier(sc, MGMT, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return (val);
}
static void
-smc_mii_writebits(struct smc_softc *sc, u_int val, int nbits)
+smc_mii_bitbang_write(device_t dev, uint32_t val)
{
- u_int mgmt, mask;
+ struct smc_softc *sc;
+
+ sc = device_get_softc(dev);
SMC_ASSERT_LOCKED(sc);
KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3,
- ("%s: smc_mii_writebits called with bank %d (!= 3)",
+ ("%s: smc_mii_bitbang_write called with bank %d (!= 3)",
device_get_nameunit(sc->smc_dev),
smc_read_2(sc, BSR) & BSR_BANK_MASK));
- /*
- * Set up the MGMT (aka MII) register).
- */
- mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO);
- mgmt |= MGMT_MDOE;
-
- /*
- * Push the bits out.
- */
- for (mask = 1 << (nbits - 1); mask; mask >>= 1) {
- if (val & mask)
- mgmt |= MGMT_MDO;
- else
- mgmt &= ~MGMT_MDO;
-
- smc_write_2(sc, MGMT, mgmt);
- DELAY(1);
- smc_write_2(sc, MGMT, mgmt | MGMT_MCLK);
- DELAY(1);
- }
+ smc_write_2(sc, MGMT, val);
+ smc_barrier(sc, MGMT, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
int
@@ -978,26 +982,7 @@ smc_miibus_readreg(device_t dev, int phy, int reg)
smc_select_bank(sc, 3);
- /*
- * Send out the idle pattern.
- */
- smc_mii_writebits(sc, 0xffffffff, 32);
-
- /*
- * Start code + read opcode + phy address + phy register
- */
- smc_mii_writebits(sc, 6 << 10 | phy << 5 | reg, 14);
-
- /*
- * Turnaround + data
- */
- val = smc_mii_readbits(sc, 18);
-
- /*
- * Reset the MDIO interface.
- */
- smc_write_2(sc, MGMT,
- smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO));
+ val = mii_bitbang_readreg(dev, &smc_mii_bitbang_ops, phy, reg);
SMC_UNLOCK(sc);
return (val);
@@ -1014,23 +999,7 @@ smc_miibus_writereg(device_t dev, int phy, int reg, int data)
smc_select_bank(sc, 3);
- /*
- * Send idle pattern.
- */
- smc_mii_writebits(sc, 0xffffffff, 32);
-
- /*
- * Start code + write opcode + phy address + phy register + turnaround
- * + data.
- */
- smc_mii_writebits(sc, 5 << 28 | phy << 23 | reg << 18 | 2 << 16 | data,
- 32);
-
- /*
- * Reset MDIO interface.
- */
- smc_write_2(sc, MGMT,
- smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO));
+ mii_bitbang_writereg(dev, &smc_mii_bitbang_ops, phy, reg, data);
SMC_UNLOCK(sc);
return (0);
diff --git a/sys/dev/ste/if_ste.c b/sys/dev/ste/if_ste.c
index 846761c..a6fc00b 100644
--- a/sys/dev/ste/if_ste.c
+++ b/sys/dev/ste/if_ste.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
@@ -84,7 +85,7 @@ MODULE_DEPEND(ste, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static struct ste_type ste_devs[] = {
+static const struct ste_type const ste_devs[] = {
{ ST_VENDORID, ST_DEVICEID_ST201_1, "Sundance ST201 10/100BaseTX" },
{ ST_VENDORID, ST_DEVICEID_ST201_2, "Sundance ST201 10/100BaseTX" },
{ DL_VENDORID, DL_DEVICEID_DL10050, "D-Link DL10050 10/100BaseTX" },
@@ -112,10 +113,8 @@ static int ste_init_rx_list(struct ste_softc *);
static void ste_init_tx_list(struct ste_softc *);
static void ste_intr(void *);
static int ste_ioctl(struct ifnet *, u_long, caddr_t);
-static int ste_mii_readreg(struct ste_softc *, struct ste_mii_frame *);
-static void ste_mii_send(struct ste_softc *, uint32_t, int);
-static void ste_mii_sync(struct ste_softc *);
-static int ste_mii_writereg(struct ste_softc *, struct ste_mii_frame *);
+static uint32_t ste_mii_bitbang_read(device_t);
+static void ste_mii_bitbang_write(device_t, uint32_t);
static int ste_miibus_readreg(device_t, int, int);
static void ste_miibus_statchg(device_t);
static int ste_miibus_writereg(device_t, int, int, int);
@@ -138,6 +137,21 @@ static void ste_txeof(struct ste_softc *);
static void ste_wait(struct ste_softc *);
static void ste_watchdog(struct ste_softc *);
+/*
+ * MII bit-bang glue
+ */
+static const struct mii_bitbang_ops ste_mii_bitbang_ops = {
+ ste_mii_bitbang_read,
+ ste_mii_bitbang_write,
+ {
+ STE_PHYCTL_MDATA, /* MII_BIT_MDO */
+ STE_PHYCTL_MDATA, /* MII_BIT_MDI */
+ STE_PHYCTL_MCLK, /* MII_BIT_MDC */
+ STE_PHYCTL_MDIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t ste_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ste_probe),
@@ -188,210 +202,51 @@ DRIVER_MODULE(miibus, ste, miibus_driver, miibus_devclass, 0, 0);
#define STE_CLRBIT1(sc, reg, x) \
CSR_WRITE_1(sc, reg, CSR_READ_1(sc, reg) & ~(x))
-
-#define MII_SET(x) STE_SETBIT1(sc, STE_PHYCTL, x)
-#define MII_CLR(x) STE_CLRBIT1(sc, STE_PHYCTL, x)
-
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-ste_mii_sync(struct ste_softc *sc)
-{
- int i;
-
- MII_SET(STE_PHYCTL_MDIR|STE_PHYCTL_MDATA);
-
- for (i = 0; i < 32; i++) {
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
- }
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-ste_mii_send(struct ste_softc *sc, uint32_t bits, int cnt)
-{
- int i;
-
- MII_CLR(STE_PHYCTL_MCLK);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- MII_SET(STE_PHYCTL_MDATA);
- } else {
- MII_CLR(STE_PHYCTL_MDATA);
- }
- DELAY(1);
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
- MII_SET(STE_PHYCTL_MCLK);
- }
-}
-
/*
- * Read an PHY register through the MII.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static int
-ste_mii_readreg(struct ste_softc *sc, struct ste_mii_frame *frame)
+static uint32_t
+ste_mii_bitbang_read(device_t dev)
{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = STE_MII_STARTDELIM;
- frame->mii_opcode = STE_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- CSR_WRITE_2(sc, STE_PHYCTL, 0);
- /*
- * Turn on data xmit.
- */
- MII_SET(STE_PHYCTL_MDIR);
-
- ste_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- ste_mii_send(sc, frame->mii_stdelim, 2);
- ste_mii_send(sc, frame->mii_opcode, 2);
- ste_mii_send(sc, frame->mii_phyaddr, 5);
- ste_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Turn off xmit. */
- MII_CLR(STE_PHYCTL_MDIR);
-
- /* Idle bit */
- MII_CLR((STE_PHYCTL_MCLK|STE_PHYCTL_MDATA));
- DELAY(1);
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
-
- /* Check for ack */
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
- ack = CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA;
- MII_SET(STE_PHYCTL_MCLK);
- 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(STE_PHYCTL_MCLK);
- DELAY(1);
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA)
- frame->mii_data |= i;
- DELAY(1);
- }
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
- }
+ struct ste_softc *sc;
+ uint32_t val;
-fail:
+ sc = device_get_softc(dev);
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
+ val = CSR_READ_1(sc, STE_PHYCTL);
+ CSR_BARRIER(sc, STE_PHYCTL, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (ack)
- return (1);
- return (0);
+ return (val);
}
/*
- * Write to a PHY register through the MII.
+ * Write the MII serial port for the MII bit-bang module.
*/
-static int
-ste_mii_writereg(struct ste_softc *sc, struct ste_mii_frame *frame)
+static void
+ste_mii_bitbang_write(device_t dev, uint32_t val)
{
+ struct ste_softc *sc;
- /*
- * Set up frame for TX.
- */
-
- frame->mii_stdelim = STE_MII_STARTDELIM;
- frame->mii_opcode = STE_MII_WRITEOP;
- frame->mii_turnaround = STE_MII_TURNAROUND;
-
- /*
- * Turn on data output.
- */
- MII_SET(STE_PHYCTL_MDIR);
-
- ste_mii_sync(sc);
-
- ste_mii_send(sc, frame->mii_stdelim, 2);
- ste_mii_send(sc, frame->mii_opcode, 2);
- ste_mii_send(sc, frame->mii_phyaddr, 5);
- ste_mii_send(sc, frame->mii_regaddr, 5);
- ste_mii_send(sc, frame->mii_turnaround, 2);
- ste_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- MII_SET(STE_PHYCTL_MCLK);
- DELAY(1);
- MII_CLR(STE_PHYCTL_MCLK);
- DELAY(1);
-
- /*
- * Turn off xmit.
- */
- MII_CLR(STE_PHYCTL_MDIR);
+ sc = device_get_softc(dev);
- return (0);
+ CSR_WRITE_1(sc, STE_PHYCTL, val);
+ CSR_BARRIER(sc, STE_PHYCTL, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
ste_miibus_readreg(device_t dev, int phy, int reg)
{
- struct ste_softc *sc;
- struct ste_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- ste_mii_readreg(sc, &frame);
-
- return (frame.mii_data);
+ return (mii_bitbang_readreg(dev, &ste_mii_bitbang_ops, phy, reg));
}
static int
ste_miibus_writereg(device_t dev, int phy, int reg, int data)
{
- struct ste_softc *sc;
- struct ste_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
- ste_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &ste_mii_bitbang_ops, phy, reg, data);
return (0);
}
@@ -1027,7 +882,7 @@ ste_stats_update(struct ste_softc *sc)
static int
ste_probe(device_t dev)
{
- struct ste_type *t;
+ const struct ste_type *t;
t = ste_devs;
diff --git a/sys/dev/ste/if_stereg.h b/sys/dev/ste/if_stereg.h
index 840e0bf..e3aa51b 100644
--- a/sys/dev/ste/if_stereg.h
+++ b/sys/dev/ste/if_stereg.h
@@ -492,6 +492,9 @@ struct ste_desc_onefrag {
#define CSR_READ_1(sc, reg) \
bus_read_1((sc)->ste_res, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_barrier((sc)->ste_res, reg, length, flags)
+
#define STE_DESC_ALIGN 8
#define STE_RX_LIST_CNT 128
#define STE_TX_LIST_CNT 128
@@ -519,7 +522,7 @@ struct ste_desc_onefrag {
struct ste_type {
uint16_t ste_vid;
uint16_t ste_did;
- char *ste_name;
+ const char *ste_name;
};
struct ste_list_data {
@@ -590,20 +593,3 @@ struct ste_softc {
#define STE_LOCK(_sc) mtx_lock(&(_sc)->ste_mtx)
#define STE_UNLOCK(_sc) mtx_unlock(&(_sc)->ste_mtx)
#define STE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->ste_mtx, MA_OWNED)
-
-struct ste_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 STE_MII_STARTDELIM 0x01
-#define STE_MII_READOP 0x02
-#define STE_MII_WRITEOP 0x01
-#define STE_MII_TURNAROUND 0x02
diff --git a/sys/dev/stge/if_stge.c b/sys/dev/stge/if_stge.c
index 5058a4d..b18da27 100644
--- a/sys/dev/stge/if_stge.c
+++ b/sys/dev/stge/if_stge.c
@@ -67,6 +67,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>
@@ -86,11 +87,11 @@ MODULE_DEPEND(stge, miibus, 1, 1, 1);
/*
* Devices supported by this driver.
*/
-static struct stge_product {
+static const struct stge_product {
uint16_t stge_vendorid;
uint16_t stge_deviceid;
const char *stge_name;
-} stge_products[] = {
+} const stge_products[] = {
{ VENDOR_SUNDANCETI, DEVICEID_SUNDANCETI_ST1023,
"Sundance ST-1023 Gigabit Ethernet" },
@@ -160,10 +161,6 @@ static int stge_newbuf(struct stge_softc *, int);
static __inline struct mbuf *stge_fixup_rx(struct stge_softc *, struct mbuf *);
#endif
-static void stge_mii_sync(struct stge_softc *);
-static void stge_mii_send(struct stge_softc *, uint32_t, int);
-static int stge_mii_readreg(struct stge_softc *, struct stge_mii_frame *);
-static int stge_mii_writereg(struct stge_softc *, struct stge_mii_frame *);
static int stge_miibus_readreg(device_t, int, int);
static int stge_miibus_writereg(device_t, int, int, int);
static void stge_miibus_statchg(device_t);
@@ -185,6 +182,24 @@ static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
static int sysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS);
static int sysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t stge_mii_bitbang_read(device_t);
+static void stge_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops stge_mii_bitbang_ops = {
+ stge_mii_bitbang_read,
+ stge_mii_bitbang_write,
+ {
+ PC_MgmtData, /* MII_BIT_MDO */
+ PC_MgmtData, /* MII_BIT_MDI */
+ PC_MgmtClk, /* MII_BIT_MDC */
+ PC_MgmtDir, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t stge_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, stge_probe),
@@ -225,176 +240,40 @@ static struct resource_spec stge_res_spec_mem[] = {
{ -1, 0, 0 }
};
-#define MII_SET(x) \
- CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) | (x))
-#define MII_CLR(x) \
- CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) & ~(x))
-
/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
+ * stge_mii_bitbang_read: [mii bit-bang interface function]
+ *
+ * Read the MII serial port for the MII bit-bang module.
*/
-static void
-stge_mii_sync(struct stge_softc *sc)
+static uint32_t
+stge_mii_bitbang_read(device_t dev)
{
- int i;
+ struct stge_softc *sc;
+ uint32_t val;
- MII_SET(PC_MgmtDir | PC_MgmtData);
+ sc = device_get_softc(dev);
- for (i = 0; i < 32; i++) {
- MII_SET(PC_MgmtClk);
- DELAY(1);
- MII_CLR(PC_MgmtClk);
- DELAY(1);
- }
+ val = CSR_READ_1(sc, STGE_PhyCtrl);
+ CSR_BARRIER(sc, STGE_PhyCtrl, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ return (val);
}
/*
- * Clock a series of bits through the MII.
+ * stge_mii_bitbang_write: [mii big-bang interface function]
+ *
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-stge_mii_send(struct stge_softc *sc, uint32_t bits, int cnt)
-{
- int i;
-
- MII_CLR(PC_MgmtClk);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i)
- MII_SET(PC_MgmtData);
- else
- MII_CLR(PC_MgmtData);
- DELAY(1);
- MII_CLR(PC_MgmtClk);
- DELAY(1);
- MII_SET(PC_MgmtClk);
- }
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-stge_mii_readreg(struct stge_softc *sc, struct stge_mii_frame *frame)
+stge_mii_bitbang_write(device_t dev, uint32_t val)
{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = STGE_MII_STARTDELIM;
- frame->mii_opcode = STGE_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- CSR_WRITE_1(sc, STGE_PhyCtrl, 0 | sc->sc_PhyCtrl);
- /*
- * Turn on data xmit.
- */
- MII_SET(PC_MgmtDir);
-
- stge_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- stge_mii_send(sc, frame->mii_stdelim, 2);
- stge_mii_send(sc, frame->mii_opcode, 2);
- stge_mii_send(sc, frame->mii_phyaddr, 5);
- stge_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Turn off xmit. */
- MII_CLR(PC_MgmtDir);
-
- /* Idle bit */
- MII_CLR((PC_MgmtClk | PC_MgmtData));
- DELAY(1);
- MII_SET(PC_MgmtClk);
- DELAY(1);
-
- /* Check for ack */
- MII_CLR(PC_MgmtClk);
- DELAY(1);
- ack = CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData;
- MII_SET(PC_MgmtClk);
- 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(PC_MgmtClk);
- DELAY(1);
- MII_SET(PC_MgmtClk);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- MII_CLR(PC_MgmtClk);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData)
- frame->mii_data |= i;
- DELAY(1);
- }
- MII_SET(PC_MgmtClk);
- DELAY(1);
- }
-
-fail:
- MII_CLR(PC_MgmtClk);
- DELAY(1);
- MII_SET(PC_MgmtClk);
- DELAY(1);
-
- if (ack)
- return(1);
- return(0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-stge_mii_writereg(struct stge_softc *sc, struct stge_mii_frame *frame)
-{
-
- /*
- * Set up frame for TX.
- */
- frame->mii_stdelim = STGE_MII_STARTDELIM;
- frame->mii_opcode = STGE_MII_WRITEOP;
- frame->mii_turnaround = STGE_MII_TURNAROUND;
-
- /*
- * Turn on data output.
- */
- MII_SET(PC_MgmtDir);
-
- stge_mii_sync(sc);
-
- stge_mii_send(sc, frame->mii_stdelim, 2);
- stge_mii_send(sc, frame->mii_opcode, 2);
- stge_mii_send(sc, frame->mii_phyaddr, 5);
- stge_mii_send(sc, frame->mii_regaddr, 5);
- stge_mii_send(sc, frame->mii_turnaround, 2);
- stge_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- MII_SET(PC_MgmtClk);
- DELAY(1);
- MII_CLR(PC_MgmtClk);
- DELAY(1);
+ struct stge_softc *sc;
- /*
- * Turn off xmit.
- */
- MII_CLR(PC_MgmtDir);
+ sc = device_get_softc(dev);
- return(0);
+ CSR_WRITE_1(sc, STGE_PhyCtrl, val);
+ CSR_BARRIER(sc, STGE_PhyCtrl, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
/*
@@ -406,8 +285,7 @@ static int
stge_miibus_readreg(device_t dev, int phy, int reg)
{
struct stge_softc *sc;
- struct stge_mii_frame frame;
- int error;
+ int error, val;
sc = device_get_softc(dev);
@@ -418,21 +296,11 @@ stge_miibus_readreg(device_t dev, int phy, int reg)
STGE_MII_UNLOCK(sc);
return (error);
}
- bzero(&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
STGE_MII_LOCK(sc);
- error = stge_mii_readreg(sc, &frame);
+ val = mii_bitbang_readreg(dev, &stge_mii_bitbang_ops, phy, reg);
STGE_MII_UNLOCK(sc);
-
- if (error != 0) {
- /* Don't show errors for PHY probe request */
- if (reg != 1)
- device_printf(sc->sc_dev, "phy read fail\n");
- return (0);
- }
- return (frame.mii_data);
+ return (val);
}
/*
@@ -444,22 +312,12 @@ static int
stge_miibus_writereg(device_t dev, int phy, int reg, int val)
{
struct stge_softc *sc;
- struct stge_mii_frame frame;
- int error;
sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = val;
-
STGE_MII_LOCK(sc);
- error = stge_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &stge_mii_bitbang_ops, phy, reg, val);
STGE_MII_UNLOCK(sc);
-
- if (error != 0)
- device_printf(sc->sc_dev, "phy write fail\n");
return (0);
}
@@ -550,7 +408,7 @@ stge_read_eeprom(struct stge_softc *sc, int offset, uint16_t *data)
static int
stge_probe(device_t dev)
{
- struct stge_product *sp;
+ const struct stge_product *sp;
int i;
uint16_t vendor, devid;
diff --git a/sys/dev/stge/if_stgereg.h b/sys/dev/stge/if_stgereg.h
index 6ecbdf9..f14142a 100644
--- a/sys/dev/stge/if_stgereg.h
+++ b/sys/dev/stge/if_stgereg.h
@@ -99,6 +99,9 @@
#define CSR_READ_1(_sc, reg) \
bus_read_1((_sc)->sc_res[0], (reg))
+#define CSR_BARRIER(_sc, reg, length, flags) \
+ bus_barrier((_sc)->sc_res[0], reg, length, flags)
+
/*
* TC9021 buffer fragment descriptor.
*/
@@ -677,23 +680,6 @@ do { \
#define STGE_TIMEOUT 1000
-struct stge_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 STGE_MII_STARTDELIM 0x01
-#define STGE_MII_READOP 0x02
-#define STGE_MII_WRITEOP 0x01
-#define STGE_MII_TURNAROUND 0x02
-
#define STGE_RESET_NONE 0x00
#define STGE_RESET_TX 0x01
#define STGE_RESET_RX 0x02
diff --git a/sys/dev/tl/if_tl.c b/sys/dev/tl/if_tl.c
index a256552..b7f4100 100644
--- a/sys/dev/tl/if_tl.c
+++ b/sys/dev/tl/if_tl.c
@@ -203,6 +203,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>
@@ -228,7 +229,7 @@ MODULE_DEPEND(tl, miibus, 1, 1, 1);
* Various supported device vendors/types and their names.
*/
-static struct tl_type tl_devs[] = {
+static const struct tl_type const tl_devs[] = {
{ TI_VENDORID, TI_DEVICEID_THUNDERLAN,
"Texas Instruments ThunderLAN" },
{ COMPAQ_VENDORID, COMPAQ_DEVICEID_NETEL_10,
@@ -290,10 +291,6 @@ static u_int8_t tl_eeprom_putbyte(struct tl_softc *, int);
static u_int8_t tl_eeprom_getbyte(struct tl_softc *, int, u_int8_t *);
static int tl_read_eeprom(struct tl_softc *, caddr_t, int, int);
-static void tl_mii_sync(struct tl_softc *);
-static void tl_mii_send(struct tl_softc *, u_int32_t, int);
-static int tl_mii_readreg(struct tl_softc *, struct tl_mii_frame *);
-static int tl_mii_writereg(struct tl_softc *, struct tl_mii_frame *);
static int tl_miibus_readreg(device_t, int, int);
static int tl_miibus_writereg(device_t, int, int, int);
static void tl_miibus_statchg(device_t);
@@ -318,6 +315,24 @@ static void tl_dio_clrbit(struct tl_softc *, int, int);
static void tl_dio_setbit16(struct tl_softc *, int, int);
static void tl_dio_clrbit16(struct tl_softc *, int, int);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t tl_mii_bitbang_read(device_t);
+static void tl_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops tl_mii_bitbang_ops = {
+ tl_mii_bitbang_read,
+ tl_mii_bitbang_write,
+ {
+ TL_SIO_MDATA, /* MII_BIT_MDO */
+ TL_SIO_MDATA, /* MII_BIT_MDI */
+ TL_SIO_MCLK, /* MII_BIT_MDC */
+ TL_SIO_MTXEN, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
#ifdef TL_USEIOSPACE
#define TL_RES SYS_RES_IOPORT
#define TL_RID TL_PCI_LOIO
@@ -360,7 +375,12 @@ static u_int8_t tl_dio_read8(sc, reg)
struct tl_softc *sc;
int reg;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return(CSR_READ_1(sc, TL_DIO_DATA + (reg & 3)));
}
@@ -368,7 +388,12 @@ static u_int16_t tl_dio_read16(sc, reg)
struct tl_softc *sc;
int reg;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return(CSR_READ_2(sc, TL_DIO_DATA + (reg & 3)));
}
@@ -376,7 +401,12 @@ static u_int32_t tl_dio_read32(sc, reg)
struct tl_softc *sc;
int reg;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return(CSR_READ_4(sc, TL_DIO_DATA + (reg & 3)));
}
@@ -385,9 +415,13 @@ static void tl_dio_write8(sc, reg, val)
int reg;
int val;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_1(sc, TL_DIO_DATA + (reg & 3), val);
- return;
}
static void tl_dio_write16(sc, reg, val)
@@ -395,9 +429,13 @@ static void tl_dio_write16(sc, reg, val)
int reg;
int val;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_DATA + (reg & 3), val);
- return;
}
static void tl_dio_write32(sc, reg, val)
@@ -405,9 +443,13 @@ static void tl_dio_write32(sc, reg, val)
int reg;
int val;
{
+
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_4(sc, TL_DIO_DATA + (reg & 3), val);
- return;
}
static void
@@ -418,12 +460,16 @@ tl_dio_setbit(sc, reg, bit)
{
u_int8_t f;
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
f = CSR_READ_1(sc, TL_DIO_DATA + (reg & 3));
f |= bit;
+ CSR_BARRIER(sc, TL_DIO_DATA + (reg & 3), 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_1(sc, TL_DIO_DATA + (reg & 3), f);
-
- return;
}
static void
@@ -434,12 +480,16 @@ tl_dio_clrbit(sc, reg, bit)
{
u_int8_t f;
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
f = CSR_READ_1(sc, TL_DIO_DATA + (reg & 3));
f &= ~bit;
+ CSR_BARRIER(sc, TL_DIO_DATA + (reg & 3), 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_1(sc, TL_DIO_DATA + (reg & 3), f);
-
- return;
}
static void tl_dio_setbit16(sc, reg, bit)
@@ -449,12 +499,16 @@ static void tl_dio_setbit16(sc, reg, bit)
{
u_int16_t f;
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
f = CSR_READ_2(sc, TL_DIO_DATA + (reg & 3));
f |= bit;
+ CSR_BARRIER(sc, TL_DIO_DATA + (reg & 3), 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_DATA + (reg & 3), f);
-
- return;
}
static void tl_dio_clrbit16(sc, reg, bit)
@@ -464,12 +518,16 @@ static void tl_dio_clrbit16(sc, reg, bit)
{
u_int16_t f;
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_ADDR, reg);
+ CSR_BARRIER(sc, TL_DIO_ADDR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
f = CSR_READ_2(sc, TL_DIO_DATA + (reg & 3));
f &= ~bit;
+ CSR_BARRIER(sc, TL_DIO_DATA + (reg & 3), 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
CSR_WRITE_2(sc, TL_DIO_DATA + (reg & 3), f);
-
- return;
}
/*
@@ -608,61 +666,55 @@ tl_read_eeprom(sc, dest, off, cnt)
return(err ? 1 : 0);
}
-static void
-tl_mii_sync(sc)
- struct tl_softc *sc;
+#define TL_SIO_MII (TL_SIO_MCLK | TL_SIO_MDATA | TL_SIO_MTXEN)
+
+/*
+ * Read the MII serial port for the MII bit-bang module.
+ */
+static uint32_t
+tl_mii_bitbang_read(device_t dev)
{
- register int i;
+ struct tl_softc *sc;
+ uint32_t val;
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MTXEN);
+ sc = device_get_softc(dev);
- for (i = 0; i < 32; i++) {
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- }
+ val = tl_dio_read8(sc, TL_NETSIO) & TL_SIO_MII;
+ CSR_BARRIER(sc, TL_NETSIO, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return;
+ return (val);
}
+/*
+ * Write the MII serial port for the MII bit-bang module.
+ */
static void
-tl_mii_send(sc, bits, cnt)
- struct tl_softc *sc;
- u_int32_t bits;
- int cnt;
+tl_mii_bitbang_write(device_t dev, uint32_t val)
{
- int i;
+ struct tl_softc *sc;
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- if (bits & i) {
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MDATA);
- } else {
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MDATA);
- }
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- }
+ sc = device_get_softc(dev);
+
+ val = (tl_dio_read8(sc, TL_NETSIO) & ~TL_SIO_MII) | val;
+ CSR_BARRIER(sc, TL_NETSIO, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ tl_dio_write8(sc, TL_NETSIO, val);
+ CSR_BARRIER(sc, TL_NETSIO, 1,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
-tl_mii_readreg(sc, frame)
- struct tl_softc *sc;
- struct tl_mii_frame *frame;
-
+tl_miibus_readreg(dev, phy, reg)
+ device_t dev;
+ int phy, reg;
{
- int i, ack;
- int minten = 0;
+ struct tl_softc *sc;
+ int minten, val;
- tl_mii_sync(sc);
+ sc = device_get_softc(dev);
/*
- * Set up frame for RX.
- */
- frame->mii_stdelim = TL_MII_STARTDELIM;
- frame->mii_opcode = TL_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- /*
* Turn off MII interrupt by forcing MINTEN low.
*/
minten = tl_dio_read8(sc, TL_NETSIO) & TL_SIO_MINTEN;
@@ -670,89 +722,26 @@ tl_mii_readreg(sc, frame)
tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MINTEN);
}
- /*
- * Turn on data xmit.
- */
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MTXEN);
-
- /*
- * Send command/address info.
- */
- tl_mii_send(sc, frame->mii_stdelim, 2);
- tl_mii_send(sc, frame->mii_opcode, 2);
- tl_mii_send(sc, frame->mii_phyaddr, 5);
- tl_mii_send(sc, frame->mii_regaddr, 5);
-
- /*
- * Turn off xmit.
- */
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MTXEN);
-
- /* Idle bit */
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
-
- /* Check for ack */
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- ack = tl_dio_read8(sc, TL_NETSIO) & TL_SIO_MDATA;
-
- /* Complete the cycle */
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
-
- /*
- * Now try reading data bits. If the ack failed, we still
- * need to clock through 16 cycles to keep the PHYs in sync.
- */
- if (ack) {
- for(i = 0; i < 16; i++) {
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
- if (!ack) {
- if (tl_dio_read8(sc, TL_NETSIO) & TL_SIO_MDATA)
- frame->mii_data |= i;
- }
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- }
-
-fail:
-
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
+ val = mii_bitbang_readreg(dev, &tl_mii_bitbang_ops, phy, reg);
- /* Reenable interrupts */
+ /* Reenable interrupts. */
if (minten) {
tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MINTEN);
}
- if (ack)
- return(1);
- return(0);
+ return (val);
}
static int
-tl_mii_writereg(sc, frame)
- struct tl_softc *sc;
- struct tl_mii_frame *frame;
-
+tl_miibus_writereg(dev, phy, reg, data)
+ device_t dev;
+ int phy, reg, data;
{
+ struct tl_softc *sc;
int minten;
- tl_mii_sync(sc);
-
- /*
- * Set up frame for TX.
- */
+ sc = device_get_softc(dev);
- frame->mii_stdelim = TL_MII_STARTDELIM;
- frame->mii_opcode = TL_MII_WRITEOP;
- frame->mii_turnaround = TL_MII_TURNAROUND;
-
/*
* Turn off MII interrupt by forcing MINTEN low.
*/
@@ -761,67 +750,12 @@ tl_mii_writereg(sc, frame)
tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MINTEN);
}
- /*
- * Turn on data output.
- */
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MTXEN);
-
- tl_mii_send(sc, frame->mii_stdelim, 2);
- tl_mii_send(sc, frame->mii_opcode, 2);
- tl_mii_send(sc, frame->mii_phyaddr, 5);
- tl_mii_send(sc, frame->mii_regaddr, 5);
- tl_mii_send(sc, frame->mii_turnaround, 2);
- tl_mii_send(sc, frame->mii_data, 16);
+ mii_bitbang_writereg(dev, &tl_mii_bitbang_ops, phy, reg, data);
- tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MCLK);
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MCLK);
-
- /*
- * Turn off xmit.
- */
- tl_dio_clrbit(sc, TL_NETSIO, TL_SIO_MTXEN);
-
- /* Reenable interrupts */
- if (minten)
+ /* Reenable interrupts. */
+ if (minten) {
tl_dio_setbit(sc, TL_NETSIO, TL_SIO_MINTEN);
-
- return(0);
-}
-
-static int
-tl_miibus_readreg(dev, phy, reg)
- device_t dev;
- int phy, reg;
-{
- struct tl_softc *sc;
- struct tl_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- tl_mii_readreg(sc, &frame);
-
- return(frame.mii_data);
-}
-
-static int
-tl_miibus_writereg(dev, phy, reg, data)
- device_t dev;
- int phy, reg, data;
-{
- struct tl_softc *sc;
- struct tl_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
-
- tl_mii_writereg(sc, &frame);
+ }
return(0);
}
@@ -841,8 +775,6 @@ tl_miibus_statchg(dev)
} else {
tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_DUPLEX);
}
-
- return;
}
/*
@@ -865,8 +797,6 @@ tl_setmode(sc, media)
tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_DUPLEX);
}
}
-
- return;
}
/*
@@ -909,8 +839,6 @@ tl_setfilt(sc, addr, slot)
for (i = 0; i < ETHER_ADDR_LEN; i++)
tl_dio_write8(sc, regaddr + i, *(addr + i));
-
- return;
}
/*
@@ -980,8 +908,6 @@ tl_setmulti(sc)
tl_dio_write32(sc, TL_HASH1, hashes[0]);
tl_dio_write32(sc, TL_HASH2, hashes[1]);
-
- return;
}
/*
@@ -1000,7 +926,7 @@ tl_hardreset(dev)
sc = device_get_softc(dev);
- tl_mii_sync(sc);
+ mii_bitbang_sync(dev, &tl_mii_bitbang_ops);
flags = BMCR_LOOP|BMCR_ISO|BMCR_PDOWN;
@@ -1010,11 +936,10 @@ tl_hardreset(dev)
tl_miibus_writereg(dev, 31, MII_BMCR, BMCR_ISO);
DELAY(50000);
tl_miibus_writereg(dev, 31, MII_BMCR, BMCR_LOOP|BMCR_ISO);
- tl_mii_sync(sc);
+ mii_bitbang_sync(dev, &tl_mii_bitbang_ops);
while(tl_miibus_readreg(dev, 31, MII_BMCR) & BMCR_RESET);
DELAY(50000);
- return;
}
static void
@@ -1072,8 +997,6 @@ tl_softreset(sc, internal)
/* Wait for things to settle down a little. */
DELAY(500);
-
- return;
}
/*
@@ -1084,7 +1007,7 @@ static int
tl_probe(dev)
device_t dev;
{
- struct tl_type *t;
+ const struct tl_type *t;
t = tl_devs;
@@ -1105,7 +1028,7 @@ tl_attach(dev)
device_t dev;
{
u_int16_t did, vid;
- struct tl_type *t;
+ const struct tl_type *t;
struct ifnet *ifp;
struct tl_softc *sc;
int error, flags, i, rid, unit;
@@ -1415,9 +1338,9 @@ static int
tl_list_rx_init(sc)
struct tl_softc *sc;
{
- struct tl_chain_data *cd;
- struct tl_list_data *ld;
- int i;
+ struct tl_chain_data *cd;
+ struct tl_list_data *ld;
+ int i;
cd = &sc->tl_cdata;
ld = sc->tl_ldata;
@@ -1783,8 +1706,6 @@ tl_intr(xsc)
tl_start_locked(ifp);
TL_UNLOCK(sc);
-
- return;
}
static void
@@ -1843,8 +1764,6 @@ tl_stats_update(xsc)
mii = device_get_softc(sc->tl_miibus);
mii_tick(mii);
}
-
- return;
}
/*
@@ -2046,8 +1965,6 @@ tl_start_locked(ifp)
* Set a timeout in case the chip goes out to lunch.
*/
sc->tl_timer = 5;
-
- return;
}
static void
@@ -2143,8 +2060,6 @@ tl_init_locked(sc)
/* Start the stats update counter */
callout_reset(&sc->tl_stat_callout, hz, tl_stats_update, sc);
-
- return;
}
/*
@@ -2204,8 +2119,6 @@ tl_ifmedia_sts(ifp, ifmr)
ifmr->ifm_status = mii->mii_media_status;
}
TL_UNLOCK(sc);
-
- return;
}
static int
@@ -2284,8 +2197,6 @@ tl_watchdog(sc)
tl_softreset(sc, 1);
tl_init_locked(sc);
-
- return;
}
/*
@@ -2351,8 +2262,6 @@ tl_stop(sc)
sizeof(sc->tl_ldata->tl_tx_list));
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- return;
}
/*
diff --git a/sys/dev/tl/if_tlreg.h b/sys/dev/tl/if_tlreg.h
index 4e340b1..4a82cc5 100644
--- a/sys/dev/tl/if_tlreg.h
+++ b/sys/dev/tl/if_tlreg.h
@@ -32,11 +32,10 @@
* $FreeBSD$
*/
-
struct tl_type {
u_int16_t tl_vid;
u_int16_t tl_did;
- char *tl_name;
+ const char *tl_name;
};
/*
@@ -203,6 +202,7 @@ struct tl_softc {
#define TL_INT_MASK 0x001C
#define TL_VEC_MASK 0x1FE0
+
/*
* Host command register bits
*/
@@ -390,36 +390,6 @@ struct tl_softc {
#define TL_MASK_MASK5 0x20
#define TL_MASK_MASK4 0x10
-/*
- * MII frame format
- */
-#ifdef ANSI_DOESNT_ALLOW_BITFIELDS
-struct tl_mii_frame {
- u_int16_t mii_stdelim:2,
- mii_opcode:2,
- mii_phyaddr:5,
- mii_regaddr:5,
- mii_turnaround:2;
- u_int16_t mii_data;
-};
-#else
-struct tl_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
-};
-#endif
-/*
- * MII constants
- */
-#define TL_MII_STARTDELIM 0x01
-#define TL_MII_READOP 0x02
-#define TL_MII_WRITEOP 0x01
-#define TL_MII_TURNAROUND 0x02
-
#define TL_LAST_FRAG 0x80000000
#define TL_CSTAT_UNUSED 0x8000
#define TL_CSTAT_FRAMECMP 0x4000
@@ -499,6 +469,9 @@ struct tl_stats {
#define CSR_READ_2(sc, reg) bus_read_2(sc->tl_res, reg)
#define CSR_READ_1(sc, reg) bus_read_1(sc->tl_res, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_barrier(sc->tl_res, reg, length, flags)
+
#define CMD_PUT(sc, x) CSR_WRITE_4(sc, TL_HOSTCMD, x)
#define CMD_SET(sc, x) \
CSR_WRITE_4(sc, TL_HOSTCMD, CSR_READ_4(sc, TL_HOSTCMD) | (x))
diff --git a/sys/dev/wb/if_wb.c b/sys/dev/wb/if_wb.c
index f924d3e..daac022 100644
--- a/sys/dev/wb/if_wb.c
+++ b/sys/dev/wb/if_wb.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
/* "device miibus" required. See GENERIC if you get errors here. */
@@ -129,7 +130,7 @@ MODULE_DEPEND(wb, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static struct wb_type wb_devs[] = {
+static const struct wb_type const wb_devs[] = {
{ WB_VENDORID, WB_DEVICEID_840F,
"Winbond W89C840F 10/100BaseTX" },
{ CP_VENDORID, CP_DEVICEID_RL100,
@@ -166,10 +167,6 @@ static void wb_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static void wb_eeprom_putbyte(struct wb_softc *, int);
static void wb_eeprom_getword(struct wb_softc *, int, u_int16_t *);
static void wb_read_eeprom(struct wb_softc *, caddr_t, int, int, int);
-static void wb_mii_sync(struct wb_softc *);
-static void wb_mii_send(struct wb_softc *, u_int32_t, int);
-static int wb_mii_readreg(struct wb_softc *, struct wb_mii_frame *);
-static int wb_mii_writereg(struct wb_softc *, struct wb_mii_frame *);
static void wb_setcfg(struct wb_softc *, u_int32_t);
static void wb_setmulti(struct wb_softc *);
@@ -182,6 +179,24 @@ static int wb_miibus_readreg(device_t, int, int);
static int wb_miibus_writereg(device_t, int, int, int);
static void wb_miibus_statchg(device_t);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t wb_mii_bitbang_read(device_t);
+static void wb_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops wb_mii_bitbang_ops = {
+ wb_mii_bitbang_read,
+ wb_mii_bitbang_write,
+ {
+ WB_SIO_MII_DATAOUT, /* MII_BIT_MDO */
+ WB_SIO_MII_DATAIN, /* MII_BIT_MDI */
+ WB_SIO_MII_CLK, /* MII_BIT_MDC */
+ WB_SIO_MII_DIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
#ifdef WB_USEIOSPACE
#define WB_RES SYS_RES_IOPORT
#define WB_RID WB_PCI_LOIO
@@ -262,8 +277,6 @@ wb_eeprom_putbyte(sc, addr)
SIO_CLR(WB_SIO_EE_CLK);
DELAY(100);
}
-
- return;
}
/*
@@ -304,8 +317,6 @@ wb_eeprom_getword(sc, addr, dest)
CSR_WRITE_4(sc, WB_SIO, 0);
*dest = word;
-
- return;
}
/*
@@ -330,194 +341,39 @@ wb_read_eeprom(sc, dest, off, cnt, swap)
else
*ptr = word;
}
-
- return;
}
/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static void
-wb_mii_sync(sc)
- struct wb_softc *sc;
+static uint32_t
+wb_mii_bitbang_read(device_t dev)
{
- register int i;
+ struct wb_softc *sc;
+ uint32_t val;
- SIO_SET(WB_SIO_MII_DIR|WB_SIO_MII_DATAIN);
+ sc = device_get_softc(dev);
- for (i = 0; i < 32; i++) {
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- }
+ val = CSR_READ_4(sc, WB_SIO);
+ CSR_BARRIER(sc, WB_SIO, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return;
+ return (val);
}
/*
- * Clock a series of bits through the MII.
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-wb_mii_send(sc, bits, cnt)
- struct wb_softc *sc;
- u_int32_t bits;
- int cnt;
-{
- int i;
-
- SIO_CLR(WB_SIO_MII_CLK);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- SIO_SET(WB_SIO_MII_DATAIN);
- } else {
- SIO_CLR(WB_SIO_MII_DATAIN);
- }
- DELAY(1);
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_SET(WB_SIO_MII_CLK);
- }
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-wb_mii_readreg(sc, frame)
- struct wb_softc *sc;
- struct wb_mii_frame *frame;
-
+wb_mii_bitbang_write(device_t dev, uint32_t val)
{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = WB_MII_STARTDELIM;
- frame->mii_opcode = WB_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- CSR_WRITE_4(sc, WB_SIO, 0);
-
- /*
- * Turn on data xmit.
- */
- SIO_SET(WB_SIO_MII_DIR);
-
- wb_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- wb_mii_send(sc, frame->mii_stdelim, 2);
- wb_mii_send(sc, frame->mii_opcode, 2);
- wb_mii_send(sc, frame->mii_phyaddr, 5);
- wb_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Idle bit */
- SIO_CLR((WB_SIO_MII_CLK|WB_SIO_MII_DATAIN));
- DELAY(1);
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
-
- /* Turn off xmit. */
- SIO_CLR(WB_SIO_MII_DIR);
- /* Check for ack */
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- ack = CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT;
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_SET(WB_SIO_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++) {
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
- }
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- if (!ack) {
- if (CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT)
- frame->mii_data |= i;
- DELAY(1);
- }
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
- }
-
-fail:
+ struct wb_softc *sc;
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
-
- if (ack)
- return(1);
- return(0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-wb_mii_writereg(sc, frame)
- struct wb_softc *sc;
- struct wb_mii_frame *frame;
-
-{
-
- /*
- * Set up frame for TX.
- */
-
- frame->mii_stdelim = WB_MII_STARTDELIM;
- frame->mii_opcode = WB_MII_WRITEOP;
- frame->mii_turnaround = WB_MII_TURNAROUND;
-
- /*
- * Turn on data output.
- */
- SIO_SET(WB_SIO_MII_DIR);
-
- wb_mii_sync(sc);
-
- wb_mii_send(sc, frame->mii_stdelim, 2);
- wb_mii_send(sc, frame->mii_opcode, 2);
- wb_mii_send(sc, frame->mii_phyaddr, 5);
- wb_mii_send(sc, frame->mii_regaddr, 5);
- wb_mii_send(sc, frame->mii_turnaround, 2);
- wb_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- SIO_SET(WB_SIO_MII_CLK);
- DELAY(1);
- SIO_CLR(WB_SIO_MII_CLK);
- DELAY(1);
-
- /*
- * Turn off xmit.
- */
- SIO_CLR(WB_SIO_MII_DIR);
+ sc = device_get_softc(dev);
- return(0);
+ CSR_WRITE_4(sc, WB_SIO, val);
+ CSR_BARRIER(sc, WB_SIO, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
@@ -525,18 +381,8 @@ wb_miibus_readreg(dev, phy, reg)
device_t dev;
int phy, reg;
{
- struct wb_softc *sc;
- struct wb_mii_frame frame;
-
- sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- wb_mii_readreg(sc, &frame);
-
- return(frame.mii_data);
+ return (mii_bitbang_readreg(dev, &wb_mii_bitbang_ops, phy, reg));
}
static int
@@ -544,18 +390,8 @@ wb_miibus_writereg(dev, phy, reg, data)
device_t dev;
int phy, reg, data;
{
- struct wb_softc *sc;
- struct wb_mii_frame frame;
- sc = device_get_softc(dev);
-
- bzero((char *)&frame, sizeof(frame));
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
-
- wb_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &wb_mii_bitbang_ops, phy, reg, data);
return(0);
}
@@ -570,8 +406,6 @@ wb_miibus_statchg(dev)
sc = device_get_softc(dev);
mii = device_get_softc(sc->wb_miibus);
wb_setcfg(sc, mii->mii_media_active);
-
- return;
}
/*
@@ -627,8 +461,6 @@ wb_setmulti(sc)
CSR_WRITE_4(sc, WB_MAR0, hashes[0]);
CSR_WRITE_4(sc, WB_MAR1, hashes[1]);
CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
-
- return;
}
/*
@@ -671,8 +503,6 @@ wb_setcfg(sc, media)
if (restart)
WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON|WB_NETCFG_RX_ON);
-
- return;
}
static void
@@ -742,7 +572,7 @@ static int
wb_probe(dev)
device_t dev;
{
- struct wb_type *t;
+ const struct wb_type *t;
t = wb_devs;
@@ -1001,7 +831,7 @@ wb_bfree(buf, args)
void *buf;
void *args;
{
- return;
+
}
/*
@@ -1127,8 +957,6 @@ wb_rxeoc(sc)
WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
if (CSR_READ_4(sc, WB_ISR) & WB_RXSTATE_SUSPEND)
CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
-
- return;
}
/*
@@ -1185,8 +1013,6 @@ wb_txeof(sc)
sc->wb_cdata.wb_tx_head = cur_tx->wb_nextdesc;
}
-
- return;
}
/*
@@ -1212,8 +1038,6 @@ wb_txeoc(sc)
CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
}
}
-
- return;
}
static void
@@ -1300,8 +1124,6 @@ wb_intr(arg)
}
WB_UNLOCK(sc);
-
- return;
}
static void
@@ -1320,8 +1142,6 @@ wb_tick(xsc)
if (sc->wb_timer > 0 && --sc->wb_timer == 0)
wb_watchdog(sc);
callout_reset(&sc->wb_stat_callout, hz, wb_tick, sc);
-
- return;
}
/*
@@ -1520,8 +1340,6 @@ wb_start_locked(ifp)
* Set a timeout in case the chip goes out to lunch.
*/
sc->wb_timer = 5;
-
- return;
}
static void
@@ -1647,8 +1465,6 @@ wb_init_locked(sc)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
callout_reset(&sc->wb_stat_callout, hz, wb_tick, sc);
-
- return;
}
/*
@@ -1690,8 +1506,6 @@ wb_ifmedia_sts(ifp, ifmr)
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
WB_UNLOCK(sc);
-
- return;
}
static int
@@ -1757,8 +1571,6 @@ wb_watchdog(sc)
if (ifp->if_snd.ifq_head != NULL)
wb_start_locked(ifp);
-
- return;
}
/*
@@ -1809,8 +1621,6 @@ wb_stop(sc)
sizeof(sc->wb_ldata->wb_tx_list));
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- return;
}
/*
diff --git a/sys/dev/wb/if_wbreg.h b/sys/dev/wb/if_wbreg.h
index 95d0a8e..16eb8a1 100644
--- a/sys/dev/wb/if_wbreg.h
+++ b/sys/dev/wb/if_wbreg.h
@@ -341,26 +341,9 @@ struct wb_chain_data {
struct wb_type {
u_int16_t wb_vid;
u_int16_t wb_did;
- char *wb_name;
+ const char *wb_name;
};
-struct wb_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
-};
-
-/*
- * MII constants
- */
-#define WB_MII_STARTDELIM 0x01
-#define WB_MII_READOP 0x02
-#define WB_MII_WRITEOP 0x01
-#define WB_MII_TURNAROUND 0x02
-
struct wb_softc {
struct ifnet *wb_ifp; /* interface info */
device_t wb_dev;
@@ -395,6 +378,9 @@ struct wb_softc {
#define CSR_READ_2(sc, reg) bus_read_2(sc->wb_res, reg)
#define CSR_READ_1(sc, reg) bus_read_1(sc->wb_res, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_barrier(sc->wb_res, reg, length, flags)
+
#define WB_TIMEOUT 1000
/*
diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c
index e09e434..b774e7f 100644
--- a/sys/dev/xl/if_xl.c
+++ b/sys/dev/xl/if_xl.c
@@ -127,6 +127,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>
@@ -160,7 +161,7 @@ MODULE_DEPEND(xl, miibus, 1, 1, 1);
/*
* Various supported device vendors/types and their names.
*/
-static const struct xl_type xl_devs[] = {
+static const struct xl_type const xl_devs[] = {
{ TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT,
"3Com 3c900-TPO Etherlink XL" },
{ TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO,
@@ -258,10 +259,6 @@ static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static int xl_eeprom_wait(struct xl_softc *);
static int xl_read_eeprom(struct xl_softc *, caddr_t, int, int, int);
-static void xl_mii_sync(struct xl_softc *);
-static void xl_mii_send(struct xl_softc *, u_int32_t, int);
-static int xl_mii_readreg(struct xl_softc *, struct xl_mii_frame *);
-static int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *);
static void xl_rxfilter(struct xl_softc *);
static void xl_rxfilter_90x(struct xl_softc *);
@@ -286,6 +283,24 @@ static int xl_miibus_writereg(device_t, int, int, int);
static void xl_miibus_statchg(device_t);
static void xl_miibus_mediainit(device_t);
+/*
+ * MII bit-bang glue
+ */
+static uint32_t xl_mii_bitbang_read(device_t);
+static void xl_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops xl_mii_bitbang_ops = {
+ xl_mii_bitbang_read,
+ xl_mii_bitbang_write,
+ {
+ XL_MII_DATA, /* MII_BIT_MDO */
+ XL_MII_DATA, /* MII_BIT_MDI */
+ XL_MII_CLK, /* MII_BIT_MDC */
+ XL_MII_DIR, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static device_method_t xl_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, xl_probe),
@@ -359,194 +374,66 @@ xl_wait(struct xl_softc *sc)
* some chips/CPUs/processor speeds/bus speeds/etc but not
* with others.
*/
-#define MII_SET(x) \
- CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \
- CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x))
-
-#define MII_CLR(x) \
- CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \
- CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x))
-
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-xl_mii_sync(struct xl_softc *sc)
-{
- register int i;
-
- XL_SEL_WIN(4);
- MII_SET(XL_MII_DIR|XL_MII_DATA);
-
- for (i = 0; i < 32; i++) {
- MII_SET(XL_MII_CLK);
- MII_SET(XL_MII_DATA);
- MII_SET(XL_MII_DATA);
- MII_CLR(XL_MII_CLK);
- MII_SET(XL_MII_DATA);
- MII_SET(XL_MII_DATA);
- }
-}
/*
- * Clock a series of bits through the MII.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static void
-xl_mii_send(struct xl_softc *sc, u_int32_t bits, int cnt)
+static uint32_t
+xl_mii_bitbang_read(device_t dev)
{
- int i;
-
- XL_SEL_WIN(4);
- MII_CLR(XL_MII_CLK);
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
- if (bits & i) {
- MII_SET(XL_MII_DATA);
- } else {
- MII_CLR(XL_MII_DATA);
- }
- MII_CLR(XL_MII_CLK);
- MII_SET(XL_MII_CLK);
- }
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-xl_mii_readreg(struct xl_softc *sc, struct xl_mii_frame *frame)
-{
- int i, ack;
-
- /* Set up frame for RX. */
- frame->mii_stdelim = XL_MII_STARTDELIM;
- frame->mii_opcode = XL_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- /* Select register window 4. */
- XL_SEL_WIN(4);
-
- CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0);
- /* Turn on data xmit. */
- MII_SET(XL_MII_DIR);
-
- xl_mii_sync(sc);
-
- /* Send command/address info. */
- xl_mii_send(sc, frame->mii_stdelim, 2);
- xl_mii_send(sc, frame->mii_opcode, 2);
- xl_mii_send(sc, frame->mii_phyaddr, 5);
- xl_mii_send(sc, frame->mii_regaddr, 5);
-
- /* Idle bit */
- MII_CLR((XL_MII_CLK|XL_MII_DATA));
- MII_SET(XL_MII_CLK);
-
- /* Turn off xmit. */
- MII_CLR(XL_MII_DIR);
-
- /* Check for ack */
- MII_CLR(XL_MII_CLK);
- ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA;
- MII_SET(XL_MII_CLK);
-
- /*
- * 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(XL_MII_CLK);
- MII_SET(XL_MII_CLK);
- }
- goto fail;
- }
+ struct xl_softc *sc;
+ uint32_t val;
- for (i = 0x8000; i; i >>= 1) {
- MII_CLR(XL_MII_CLK);
- if (!ack) {
- if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)
- frame->mii_data |= i;
- }
- MII_SET(XL_MII_CLK);
- }
+ sc = device_get_softc(dev);
-fail:
- MII_CLR(XL_MII_CLK);
- MII_SET(XL_MII_CLK);
+ /* We're already in window 4. */
+ val = CSR_READ_2(sc, XL_W4_PHY_MGMT);
+ CSR_BARRIER(sc, XL_W4_PHY_MGMT, 2,
+ 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
-xl_mii_writereg(struct xl_softc *sc, struct xl_mii_frame *frame)
+static void
+xl_mii_bitbang_write(device_t dev, uint32_t val)
{
+ struct xl_softc *sc;
- /* Set up frame for TX. */
- frame->mii_stdelim = XL_MII_STARTDELIM;
- frame->mii_opcode = XL_MII_WRITEOP;
- frame->mii_turnaround = XL_MII_TURNAROUND;
-
- /* Select the window 4. */
- XL_SEL_WIN(4);
-
- /* Turn on data output. */
- MII_SET(XL_MII_DIR);
-
- xl_mii_sync(sc);
-
- xl_mii_send(sc, frame->mii_stdelim, 2);
- xl_mii_send(sc, frame->mii_opcode, 2);
- xl_mii_send(sc, frame->mii_phyaddr, 5);
- xl_mii_send(sc, frame->mii_regaddr, 5);
- xl_mii_send(sc, frame->mii_turnaround, 2);
- xl_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- MII_SET(XL_MII_CLK);
- MII_CLR(XL_MII_CLK);
-
- /* Turn off xmit. */
- MII_CLR(XL_MII_DIR);
+ sc = device_get_softc(dev);
- return (0);
+ /* We're already in window 4. */
+ CSR_WRITE_2(sc, XL_W4_PHY_MGMT, val);
+ CSR_BARRIER(sc, XL_W4_PHY_MGMT, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
static int
xl_miibus_readreg(device_t dev, int phy, int reg)
{
struct xl_softc *sc;
- struct xl_mii_frame frame;
sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
-
- xl_mii_readreg(sc, &frame);
+ /* Select the window 4. */
+ XL_SEL_WIN(4);
- return (frame.mii_data);
+ return (mii_bitbang_readreg(dev, &xl_mii_bitbang_ops, phy, reg));
}
static int
xl_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct xl_softc *sc;
- struct xl_mii_frame frame;
sc = device_get_softc(dev);
- bzero((char *)&frame, sizeof(frame));
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
+ /* Select the window 4. */
+ XL_SEL_WIN(4);
- xl_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &xl_mii_bitbang_ops, phy, reg, data);
return (0);
}
diff --git a/sys/dev/xl/if_xlreg.h b/sys/dev/xl/if_xlreg.h
index f5494f5..b27e038 100644
--- a/sys/dev/xl/if_xlreg.h
+++ b/sys/dev/xl/if_xlreg.h
@@ -556,27 +556,10 @@ struct xl_chain_data {
struct xl_type {
u_int16_t xl_vid;
u_int16_t xl_did;
- char *xl_name;
-};
-
-struct xl_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
+ const char *xl_name;
};
/*
- * MII constants
- */
-#define XL_MII_STARTDELIM 0x01
-#define XL_MII_READOP 0x02
-#define XL_MII_WRITEOP 0x01
-#define XL_MII_TURNAROUND 0x02
-
-/*
* The 3C905B adapters implement a few features that we want to
* take advantage of, namely the multicast hash filter. With older
* chips, you only have the option of turning on reception of all
@@ -680,8 +663,17 @@ struct xl_stats {
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->xl_btag, sc->xl_bhandle, reg)
-#define XL_SEL_WIN(x) \
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_WINSEL | x)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_space_barrier(sc->xl_btag, sc->xl_bhandle, reg, length, flags)
+
+#define XL_SEL_WIN(x) do { \
+ CSR_BARRIER(sc, XL_COMMAND, 2, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_WINSEL | x); \
+ CSR_BARRIER(sc, XL_COMMAND, 2, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \
+} while (0)
+
#define XL_TIMEOUT 1000
/*
diff --git a/sys/modules/mii/Makefile b/sys/modules/mii/Makefile
index b0cfc12..68b01e2 100644
--- a/sys/modules/mii/Makefile
+++ b/sys/modules/mii/Makefile
@@ -5,14 +5,17 @@
KMOD= miibus
SRCS= acphy.c amphy.c atphy.c axphy.c bmtphy.c brgphy.c bus_if.h
SRCS+= ciphy.c device_if.h
-SRCS+= e1000phy.c gentbi.c icsphy.c ip1000phy.c jmphy.c
-SRCS+= lxtphy.c miibus_if.c miibus_if.h mii.c miidevs.h mii_physubr.c
+SRCS+= e1000phy.c gentbi.c icsphy.c ip1000phy.c jmphy.c lxtphy.c
+SRCS+= miibus_if.c miibus_if.h mii.c miidevs.h mii_bitbang.c mii_physubr.c
SRCS+= mlphy.c nsgphy.c nsphy.c nsphyter.c pci_if.h pnaphy.c qsphy.c
SRCS+= rdcphy.c rgephy.c rlphy.c tdkphy.c tlphy.c truephy.c
SRCS+= ukphy.c ukphy_subr.c
SRCS+= xmphy.c
EXPORT_SYMS= mii_attach \
+ mii_bitbang_readreg \
+ mii_bitbang_sync \
+ mii_bitbang_writereg \
mii_mediachg \
mii_pollstat \
mii_tick
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