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