svn commit: r186139 - in stable/6/sys: . pci
Marius Strobl
marius at FreeBSD.org
Mon Dec 15 13:39:31 PST 2008
Author: marius
Date: Mon Dec 15 21:39:31 2008
New Revision: 186139
URL: http://svn.freebsd.org/changeset/base/186139
Log:
- According to the corresponding Linux, NetBSD and OpenSolaris
drivers, there should be a 1us delay after every write when
bit-banging the MII. Also insert barriers in order to ensure
the intended ordering. These changes hopefully will solve the
bus wedging occasionally experienced with DM9102A since r182461.
- Deobfuscate dc_mii_readreg() a bit.
Modified:
stable/6/sys/ (props changed)
stable/6/sys/pci/if_dc.c
stable/6/sys/pci/if_dcreg.h
Modified: stable/6/sys/pci/if_dc.c
==============================================================================
--- stable/6/sys/pci/if_dc.c Mon Dec 15 21:37:40 2008 (r186138)
+++ stable/6/sys/pci/if_dc.c Mon Dec 15 21:39:31 2008 (r186139)
@@ -616,15 +616,22 @@ dc_read_eeprom(struct dc_softc *sc, cadd
static void
dc_mii_writebit(struct dc_softc *sc, int bit)
{
+ uint32_t reg;
- if (bit)
- CSR_WRITE_4(sc, DC_SIO,
- DC_SIO_ROMCTL_WRITE | DC_SIO_MII_DATAOUT);
- else
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
-
- DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
+ 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);
+
+ 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);
}
/*
@@ -633,11 +640,22 @@ dc_mii_writebit(struct dc_softc *sc, int
static int
dc_mii_readbit(struct dc_softc *sc)
{
+ uint32_t reg;
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR);
- CSR_READ_4(sc, DC_SIO);
- DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
+ 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);
@@ -653,6 +671,9 @@ dc_mii_sync(struct dc_softc *sc)
int i;
CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
+ 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);
@@ -676,15 +697,13 @@ dc_mii_send(struct dc_softc *sc, u_int32
static int
dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
- int i, ack;
+ int i;
/*
* Set up frame for RX.
*/
frame->mii_stdelim = DC_MII_STARTDELIM;
frame->mii_opcode = DC_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
/*
* Sync the PHYs.
@@ -699,38 +718,28 @@ dc_mii_readreg(struct dc_softc *sc, stru
dc_mii_send(sc, frame->mii_phyaddr, 5);
dc_mii_send(sc, frame->mii_regaddr, 5);
-#ifdef notdef
- /* Idle bit */
- dc_mii_writebit(sc, 1);
- dc_mii_writebit(sc, 0);
-#endif
-
- /* Check for ack. */
- ack = dc_mii_readbit(sc);
-
/*
- * Now try reading data bits. If the ack failed, we still
+ * Now try reading data bits. If the turnaround failed, we still
* need to clock through 16 cycles to keep the PHY(s) in sync.
*/
- if (ack) {
+ 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 (!ack) {
- if (dc_mii_readbit(sc))
- frame->mii_data |= i;
- }
+ 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 (ack)
+ if (frame->mii_turnaround != 0)
return (1);
return (0);
}
@@ -745,7 +754,6 @@ dc_mii_writereg(struct dc_softc *sc, str
/*
* Set up frame for TX.
*/
-
frame->mii_stdelim = DC_MII_STARTDELIM;
frame->mii_opcode = DC_MII_WRITEOP;
frame->mii_turnaround = DC_MII_TURNAROUND;
@@ -762,7 +770,7 @@ dc_mii_writereg(struct dc_softc *sc, str
dc_mii_send(sc, frame->mii_turnaround, 2);
dc_mii_send(sc, frame->mii_data, 16);
- /* Idle bit. */
+ /* Clock the idle bits. */
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
Modified: stable/6/sys/pci/if_dcreg.h
==============================================================================
--- stable/6/sys/pci/if_dcreg.h Mon Dec 15 21:37:40 2008 (r186138)
+++ stable/6/sys/pci/if_dcreg.h Mon Dec 15 21:39:31 2008 (r186139)
@@ -794,6 +794,9 @@ 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) \
+ bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
+
#define DC_TIMEOUT 1000
#define ETHER_ALIGN 2
More information about the svn-src-stable
mailing list