Date: Fri, 3 Oct 2008 14:47:56 +0900 From: Pyun YongHyeon <pyunyh@gmail.com> To: freebsd-current@FreeBSD.org Subject: Call for axe(4) testers. Message-ID: <20081003054756.GB71518@cdnetworks.co.kr>
next in thread | raw e-mail | index | archive | help
--LyciRD1jyfeSSjG0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, Attached file is fix for AX88178 USB Gigabit controller. The patch removed old hack to find the correct PHY address of controller and it will affect all axe(4) controllers. If you have axe(4) hardware please give it try and let me know how it goes. Thanks. -- Regards, Pyun YongHyeon --LyciRD1jyfeSSjG0 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="axe.88178.patch" Index: sys/dev/usb/if_axe.c =================================================================== --- sys/dev/usb/if_axe.c (revision 183560) +++ sys/dev/usb/if_axe.c (working copy) @@ -162,6 +162,7 @@ static miibus_writereg_t axe_miibus_writereg; static miibus_statchg_t axe_miibus_statchg; +static int axe_get_phyno(struct axe_softc *, int); static int axe_encap(struct axe_softc *, struct mbuf *, int); static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); @@ -248,21 +249,10 @@ return(0); AXE_SLEEPLOCKASSERT(sc); -#ifdef notdef - /* - * The chip tells us the MII address of any supported - * PHYs attached to the chip, so only read from those. - */ - if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0]) + if (sc->axe_phyno != phy) return (0); - if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1]) - return (0); -#endif - if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy) - return (0); - AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, (void *)&val); @@ -274,9 +264,6 @@ return(-1); } - if (val && val != 0xffff) - sc->axe_phyaddrs[0] = phy; - return (le16toh(val)); } @@ -290,6 +277,10 @@ return(0); AXE_SLEEPLOCKASSERT(sc); + + if (sc->axe_phyno != phy) + return (0); + AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); val = htole32(val); @@ -310,12 +301,43 @@ { struct axe_softc *sc = device_get_softc(dev); struct mii_data *mii = GET_MII(sc); + struct ifnet *ifp; int val, err; - val = (mii->mii_media_active & IFM_GMASK) == IFM_FDX ? - AXE_MEDIA_FULL_DUPLEX : 0; + ifp = sc->axe_ifp; + if (mii == NULL || ifp == NULL || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + + sc->axe_link = 0; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + sc->axe_link++; + break; + case IFM_1000_T: + if ((sc->axe_flags & AX178) == 0) + break; + sc->axe_link++; + break; + default: + break; + } + } + + /* Lost link, do nothing. */ + if (sc->axe_link == 0) + return; + + val = 0; + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) + val |= AXE_MEDIA_FULL_DUPLEX; if (sc->axe_flags & (AX178|AX772)) { val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC; + if (sc->axe_flags & AX178) + val |= AXE_178_MEDIA_ENCK; switch (IFM_SUBTYPE(mii->mii_media_active)) { case IFM_1000_T: @@ -343,7 +365,6 @@ struct axe_softc *sc = ifp->if_softc; struct mii_data *mii = GET_MII(sc); - sc->axe_link = 0; if (mii->mii_instance) { struct mii_softc *miisc; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) @@ -456,6 +477,9 @@ axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL); usbd_delay_ms(sc->axe_udev, 150); + /* Enable MII/GMII/RGMII interface to work with external PHY. */ + axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL); + usbd_delay_ms(sc->axe_udev, 150); axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); } @@ -465,7 +489,7 @@ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL); usbd_delay_ms(sc->axe_udev, 40); - if (sc->axe_phyaddrs[1] == AXE_INTPHY) { + if (sc->axe_phyno == AXE_PHY_NO_AX772_EPHY) { /* ask for embedded PHY */ axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL); usbd_delay_ms(sc->axe_udev, 10); @@ -516,6 +540,30 @@ return; } +static int +axe_get_phyno(struct axe_softc *sc, int sel) +{ + int phyno; + + phyno = -1; + switch (AXE_PHY_TYPE(sc->axe_phyaddrs[sel])) { + case PHY_TYPE_100_HOME: + case PHY_TYPE_GIG: + phyno = AXE_PHY_NO(sc->axe_phyaddrs[sel]); + break; + case PHY_TYPE_SPECIAL: + /* FALLTHROUGH */ + case PHY_TYPE_RSVD: + /* FALLTHROUGH */ + case PHY_TYPE_NON_SUP: + /* FALLTHROUGH */ + default: + break; + } + + return (phyno); +} + /* * Probe for a AX88172 chip. */ @@ -610,6 +658,14 @@ /* We need the PHYID for the init dance in some cases */ axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs); + sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI); + if (sc->axe_phyno == -1) + sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC); + if (sc->axe_phyno == -1) { + device_printf(sc->axe_dev, + "no valid PHY address found, assuming PHY address 0\n"); + sc->axe_phyno = 0; + } if (sc->axe_flags & AX178) axe_ax88178_init(sc); @@ -629,12 +685,6 @@ */ axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs); - /* - * Work around broken adapters that appear to lie about - * their PHY addresses. - */ - sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF; - ifp = sc->axe_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(sc->axe_dev, "can not if_alloc()\n"); @@ -999,12 +1049,8 @@ } mii_tick(mii); - if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->axe_link++; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - axe_start(ifp); - } + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + axe_start(ifp); sc->axe_stat_ch = timeout(axe_tick, sc, hz); @@ -1122,6 +1168,7 @@ { struct axe_softc *sc = xsc; struct ifnet *ifp = sc->axe_ifp; + struct mii_data *mii = GET_MII(sc); struct axe_chain *c; usbd_status err; int i; @@ -1223,6 +1270,9 @@ usbd_transfer(c->axe_xfer); } + sc->axe_link = 0; + mii_mediachg(mii); + ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; Index: sys/dev/usb/if_axereg.h =================================================================== --- sys/dev/usb/if_axereg.h (revision 183560) +++ sys/dev/usb/if_axereg.h (working copy) @@ -134,9 +134,24 @@ #define AXE_178_RXCMD_MFB_8192 0x0200 /* 8K max frame burst */ #define AXE_178_RXCMD_MFB_16384 0x0300 /* 16K max frame burst*/ -#define AXE_NOPHY 0xE0 -#define AXE_INTPHY 0x10 +#define AXE_PHY_SEL_PRI 1 +#define AXE_PHY_SEL_SEC 0 +#define AXE_PHY_TYPE_MASK 0xE0 +#define AXE_PHY_TYPE_SHIFT 5 +#define AXE_PHY_TYPE(x) \ + (((x) & AXE_PHY_TYPE_MASK) >> AXE_PHY_TYPE_SHIFT) +#define PHY_TYPE_100_HOME 0 /* 10/100 or 1M HOME PHY */ +#define PHY_TYPE_GIG 1 /* Gigabit PHY */ +#define PHY_TYPE_SPECIAL 4 /* Special case */ +#define PHY_TYPE_RSVD 5 /* Reserved */ +#define PHY_TYPE_NON_SUP 7 /* Non-supported PHY */ + +#define AXE_PHY_NO_MASK 0x1F +#define AXE_PHY_NO(x) ((x) & AXE_PHY_NO_MASK) + +#define AXE_PHY_NO_AX772_EPHY 0x10 /* Embedded 10/100 PHY of AX88772 */ + #define AXE_TIMEOUT 1000 #define AXE_172_BUFSZ 1536 #define AXE_178_MIN_BUFSZ 2048 @@ -236,6 +251,7 @@ int axe_link; unsigned char axe_ipgs[3]; unsigned char axe_phyaddrs[2]; + int axe_phyno; struct timeval axe_rx_notice; struct usb_task axe_tick_task; int axe_bufsz; --LyciRD1jyfeSSjG0--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20081003054756.GB71518>