diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 0b154cc257c4..55b15fa35339 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.29 1997/02/22 09:44:05 peter Exp $ + * $Id: if_fxp.c,v 1.30 1997/03/17 11:08:14 davidg Exp $ */ /* @@ -962,12 +962,39 @@ fxp_init(xsc) /* * Toggle a few bits in the DP83840 PHY. */ - if (sc->phy_primary_device == FXP_PHY_DP83840) { + if (sc->phy_primary_device == FXP_PHY_DP83840 || + sc->phy_primary_device == FXP_PHY_DP83840A) { fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR, fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR) | FXP_DP83840_PCR_LED4_MODE | /* LED4 always indicates duplex */ FXP_DP83840_PCR_F_CONNECT | /* force link disconnect bypass */ FXP_DP83840_PCR_BIT10); /* XXX I have no idea */ + /* + * If link0 is set, disable auto-negotiation and then: + * If link1 is unset = 10Mbps + * If link1 is set = 100Mbps + * If link2 is unset = half duplex + * If link2 is set = full duplex + */ + if (ifp->if_flags & IFF_LINK0) { + int flags; + + flags = (ifp->if_flags & IFF_LINK1) ? + FXP_DP83840_BMCR_SPEED_100M : 0; + flags |= (ifp->if_flags & IFF_LINK2) ? + FXP_DP83840_BMCR_FULLDUPLEX : 0; + fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR, + (fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR) & + ~(FXP_DP83840_BMCR_AUTOEN | FXP_DP83840_BMCR_SPEED_100M | + FXP_DP83840_BMCR_FULLDUPLEX)) | flags); + } else { + fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR, + (fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR) | + FXP_DP83840_BMCR_AUTOEN)); + } + } else { + printf("fxp%d: warning: unsupported PHY, type = %d, addr = %d\n", + ifp->if_unit, sc->phy_primary_device, sc->phy_primary_addr); } ifp->if_flags |= IFF_RUNNING; @@ -1042,23 +1069,24 @@ fxp_add_rfabuf(sc, oldm) return (m == oldm); } -static int +static volatile int fxp_mdi_read(csr, phy, reg) struct fxp_csr *csr; int phy; int reg; { int count = 10000; + int value; csr->mdi_control = (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21); - while ((csr->mdi_control & 0x10000000) == 0 && count--) - DELAY(1); + while (((value = csr->mdi_control) & 0x10000000) == 0 && count--) + DELAY(10); if (count <= 0) printf("fxp_mdi_read: timed out\n"); - return (csr->mdi_control & 0xffff); + return (value & 0xffff); } static void @@ -1073,8 +1101,8 @@ fxp_mdi_write(csr, phy, reg, value) csr->mdi_control = (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) | (value & 0xffff); - while ((csr->mdi_control & 10000000) == 0 && count--) - DELAY(1); + while ((csr->mdi_control & 0x10000000) == 0 && count--) + DELAY(10); if (count <= 0) printf("fxp_mdi_write: timed out\n"); diff --git a/sys/dev/fxp/if_fxpreg.h b/sys/dev/fxp/if_fxpreg.h index b6005d7322ab..693e2436766d 100644 --- a/sys/dev/fxp/if_fxpreg.h +++ b/sys/dev/fxp/if_fxpreg.h @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxpreg.h,v 1.6 1997/02/22 09:44:06 peter Exp $ + * $Id: if_fxpreg.h,v 1.7 1997/03/17 11:08:16 davidg Exp $ */ #define FXP_VENDORID_INTEL 0x8086 @@ -292,6 +292,15 @@ struct fxp_stats { #define FXP_PHY_DP83840 4 #define FXP_PHY_80C240 5 #define FXP_PHY_80C24 6 +#define FXP_PHY_DP83840A 10 + +/* + * DP84830 PHY, BMCR Basic Mode Control Register + */ +#define FXP_DP83840_BMCR 0x0 +#define FXP_DP83840_BMCR_FULLDUPLEX 0x0100 +#define FXP_DP83840_BMCR_AUTOEN 0x1000 +#define FXP_DP83840_BMCR_SPEED_100M 0x2000 /* * DP84830 PHY, PCS Configuration Register diff --git a/sys/pci/if_fxp.c b/sys/pci/if_fxp.c index 0b154cc257c4..55b15fa35339 100644 --- a/sys/pci/if_fxp.c +++ b/sys/pci/if_fxp.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.29 1997/02/22 09:44:05 peter Exp $ + * $Id: if_fxp.c,v 1.30 1997/03/17 11:08:14 davidg Exp $ */ /* @@ -962,12 +962,39 @@ fxp_init(xsc) /* * Toggle a few bits in the DP83840 PHY. */ - if (sc->phy_primary_device == FXP_PHY_DP83840) { + if (sc->phy_primary_device == FXP_PHY_DP83840 || + sc->phy_primary_device == FXP_PHY_DP83840A) { fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR, fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_PCR) | FXP_DP83840_PCR_LED4_MODE | /* LED4 always indicates duplex */ FXP_DP83840_PCR_F_CONNECT | /* force link disconnect bypass */ FXP_DP83840_PCR_BIT10); /* XXX I have no idea */ + /* + * If link0 is set, disable auto-negotiation and then: + * If link1 is unset = 10Mbps + * If link1 is set = 100Mbps + * If link2 is unset = half duplex + * If link2 is set = full duplex + */ + if (ifp->if_flags & IFF_LINK0) { + int flags; + + flags = (ifp->if_flags & IFF_LINK1) ? + FXP_DP83840_BMCR_SPEED_100M : 0; + flags |= (ifp->if_flags & IFF_LINK2) ? + FXP_DP83840_BMCR_FULLDUPLEX : 0; + fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR, + (fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR) & + ~(FXP_DP83840_BMCR_AUTOEN | FXP_DP83840_BMCR_SPEED_100M | + FXP_DP83840_BMCR_FULLDUPLEX)) | flags); + } else { + fxp_mdi_write(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR, + (fxp_mdi_read(sc->csr, sc->phy_primary_addr, FXP_DP83840_BMCR) | + FXP_DP83840_BMCR_AUTOEN)); + } + } else { + printf("fxp%d: warning: unsupported PHY, type = %d, addr = %d\n", + ifp->if_unit, sc->phy_primary_device, sc->phy_primary_addr); } ifp->if_flags |= IFF_RUNNING; @@ -1042,23 +1069,24 @@ fxp_add_rfabuf(sc, oldm) return (m == oldm); } -static int +static volatile int fxp_mdi_read(csr, phy, reg) struct fxp_csr *csr; int phy; int reg; { int count = 10000; + int value; csr->mdi_control = (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21); - while ((csr->mdi_control & 0x10000000) == 0 && count--) - DELAY(1); + while (((value = csr->mdi_control) & 0x10000000) == 0 && count--) + DELAY(10); if (count <= 0) printf("fxp_mdi_read: timed out\n"); - return (csr->mdi_control & 0xffff); + return (value & 0xffff); } static void @@ -1073,8 +1101,8 @@ fxp_mdi_write(csr, phy, reg, value) csr->mdi_control = (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) | (value & 0xffff); - while ((csr->mdi_control & 10000000) == 0 && count--) - DELAY(1); + while ((csr->mdi_control & 0x10000000) == 0 && count--) + DELAY(10); if (count <= 0) printf("fxp_mdi_write: timed out\n"); diff --git a/sys/pci/if_fxpreg.h b/sys/pci/if_fxpreg.h index b6005d7322ab..693e2436766d 100644 --- a/sys/pci/if_fxpreg.h +++ b/sys/pci/if_fxpreg.h @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxpreg.h,v 1.6 1997/02/22 09:44:06 peter Exp $ + * $Id: if_fxpreg.h,v 1.7 1997/03/17 11:08:16 davidg Exp $ */ #define FXP_VENDORID_INTEL 0x8086 @@ -292,6 +292,15 @@ struct fxp_stats { #define FXP_PHY_DP83840 4 #define FXP_PHY_80C240 5 #define FXP_PHY_80C24 6 +#define FXP_PHY_DP83840A 10 + +/* + * DP84830 PHY, BMCR Basic Mode Control Register + */ +#define FXP_DP83840_BMCR 0x0 +#define FXP_DP83840_BMCR_FULLDUPLEX 0x0100 +#define FXP_DP83840_BMCR_AUTOEN 0x1000 +#define FXP_DP83840_BMCR_SPEED_100M 0x2000 /* * DP84830 PHY, PCS Configuration Register