summaryrefslogtreecommitdiffstats
path: root/sys/dev/wb
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2011-11-01 16:13:59 +0000
committermarius <marius@FreeBSD.org>2011-11-01 16:13:59 +0000
commitb4610d98b0096971fd87d53d90c40f4da7db34e2 (patch)
treead9ba266ea9f21e3bb8157cdc1c2c7c8b1a6b9a3 /sys/dev/wb
parentd08a02f709c03ad61dd57d1fa39412d6de62189d (diff)
downloadFreeBSD-src-b4610d98b0096971fd87d53d90c40f4da7db34e2.zip
FreeBSD-src-b4610d98b0096971fd87d53d90c40f4da7db34e2.tar.gz
- Import the common MII bitbang'ing code from NetBSD and convert drivers to
take advantage of it instead of duplicating it. This reduces the size of the i386 GENERIC kernel by about 4k. The only potential in-tree user left unconverted is xe(4), which generally should be changed to use miibus(4) instead of implementing PHY handling on its own, as otherwise it makes not much sense to add a dependency on miibus(4)/mii_bitbang(4) to xe(4) just for the MII bitbang'ing code. The common MII bitbang'ing code also is useful in the embedded space for using GPIO pins to implement MII access. - Based on lessons learnt with dc(4) (see r185750), add bus barriers to the MII bitbang read and write functions of the other drivers converted in order to ensure the intended ordering. Given that register access via an index register as well as register bank/window switching is subject to the same problem, also add bus barriers to the respective functions of smc(4), tl(4) and xl(4). - Sprinkle some const. Thanks to the following testers: Andrew Bliznak (nge(4)), nwhitehorn@ (bm(4)), yongari@ (sis(4) and ste(4)) Thanks to Hans-Joerg Sirtl for supplying hardware to test stge(4). Reviewed by: yongari (subset of drivers) Obtained from: NetBSD (partially)
Diffstat (limited to 'sys/dev/wb')
-rw-r--r--sys/dev/wb/if_wb.c272
-rw-r--r--sys/dev/wb/if_wbreg.h22
2 files changed, 45 insertions, 249 deletions
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
/*
OpenPOWER on IntegriCloud