Skip site navigation (1)Skip section navigation (2)
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>