Date: Mon, 15 Dec 2008 21:39:31 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org Subject: svn commit: r186139 - in stable/6/sys: . pci Message-ID: <200812152139.mBFLdV6Q017491@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812152139.mBFLdV6Q017491>