Call for axe(4) testers.

Pyun YongHyeon pyunyh at gmail.com
Wed Dec 31 00:31:26 UTC 2008


On Tue, Dec 30, 2008 at 10:48:47PM +0900, Norikatsu Shigemura wrote:
 > Hi pyun!
 > 
 > On Sat, 20 Dec 2008 12:29:08 +0900
 > Pyun YongHyeon <pyunyh at gmail.com> wrote:
 > > How about this one?
 > > http://people.freebsd.org/~yongari/axe.88178.patch4
 > 
 > 	It's perfect!  I confirmed following devices:
 > 
 > 	Planex GT-1000T     (AX88178 with Cicada PHY)
 > 	Buffalo LUA-U2-KTX  (AX88172 with Realtek PHY)
 > 	Planex UE-200TX-G   (AX88772 with own PHY)
 > 

Great!
I've made a patch for USB2 too. axe(4) under USB2 seem to work
really well and you could get 4~5 times faster performance numbers.
(I never dreamed I could get more than 200Mbps with USB
controllers.)
Since Linux still does not work with GU-1000T I couldn't get the
performance numbers on Linux but I guess the performance number
would be the same.
Hans already committed the patch to p4 so I guess you would get
the updated axe(4) in near future. Alternatively you can try
attached patch for USB2.

-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
--- if_axe2.c.orig	2008-12-30 11:56:29.000000000 +0900
+++ if_axe2.c	2008-12-30 15:59:24.000000000 +0900
@@ -186,6 +186,7 @@
 		    void *);
 static void	axe_cfg_ax88178_init(struct axe_softc *);
 static void	axe_cfg_ax88772_init(struct axe_softc *);
+static int	axe_get_phyno(struct axe_softc *, int);
 
 static const struct usb2_config axe_config[AXE_ENDPT_MAX] = {
 
@@ -335,34 +336,26 @@
 		do_unlock = 1;
 	}
 
-#if 0
-	/*
-	 * The chip tells us the MII address of any supported
-	 * PHYs attached to the chip, so only read from those.
-	 */
-
-	if ((sc->sc_phyaddrs[0] != AXE_NOPHY) && (phy != sc->sc_phyaddrs[0])) {
-		val = 0;
-		goto done;
-	}
-	if ((sc->sc_phyaddrs[1] != AXE_NOPHY) && (phy != sc->sc_phyaddrs[1])) {
-		val = 0;
-		goto done;
-	}
-#endif
-	if ((sc->sc_phyaddrs[0] != 0xFF) && (sc->sc_phyaddrs[0] != phy)) {
+	if (sc->sc_phyno != phy) {
 		val = 0;
 		goto done;
 	}
+
 	axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
 	axe_cfg_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val);
 	axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
 
 	val = le16toh(val);
-
-	if (val && (val != 0xffff)) {
-		sc->sc_phyaddrs[0] = phy;
+	if ((sc->sc_flags & AXE_FLAG_772) != 0 && reg == MII_BMSR) {
+		/*
+		 * BMSR of AX88772 indicates that it supports extended
+		 * capability but the extended status register is
+		 * revered for embedded ethernet PHY. So clear the
+		 * extended capability bit of BMSR.
+		 */
+		val &= ~BMSR_EXTCAP;
 	}
+
 done:
 	if (do_unlock) {
 		mtx_unlock(&sc->sc_mtx);
@@ -386,10 +379,14 @@
 		do_unlock = 1;
 	}
 
+	if (sc->sc_phyno != phy)
+		goto done;
+
 	axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
 	axe_cfg_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val);
 	axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
 
+done:
 	if (do_unlock) {
 		mtx_unlock(&sc->sc_mtx);
 	}
@@ -401,6 +398,7 @@
 {
 	struct axe_softc *sc = device_get_softc(dev);
 	struct mii_data *mii = GET_MII(sc);
+	struct ifnet *ifp;
 	uint16_t val;
 	uint8_t do_unlock;
 
@@ -412,15 +410,40 @@
 		do_unlock = 1;
 	}
 
-	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
-		val = AXE_MEDIA_FULL_DUPLEX;
-	else
-		val = 0;
+	ifp = sc->sc_ifp;
+	if (mii == NULL || ifp == NULL ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		goto done;
 
-	if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) {
+	sc->sc_flags &= ~AXE_FLAG_LINK;
+	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->sc_flags |= AXE_FLAG_LINK;
+			break;
+		case IFM_1000_T:
+			if ((sc->sc_flags & AXE_FLAG_178) == 0)
+				break;
+			sc->sc_flags |= AXE_FLAG_LINK;
+			break;
+		default:
+			break;
+		}
+	}
 
-		val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC);
+	/* Lost link, do nothing. */
+	if ((sc->sc_flags & AXE_FLAG_LINK) == 0)
+		goto done;
 
+	val = 0;
+	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
+		val |= AXE_MEDIA_FULL_DUPLEX;
+	if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) {
+		val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC;
+		if ((sc->sc_flags & AXE_FLAG_178) != 0)
+			val |= AXE_178_MEDIA_ENCK;
 		switch (IFM_SUBTYPE(mii->mii_media_active)) {
 		case IFM_1000_T:
 			val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
@@ -434,6 +457,7 @@
 		}
 	}
 	axe_cfg_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
+done:
 	if (do_unlock) {
 		mtx_unlock(&sc->sc_mtx);
 	}
@@ -467,7 +491,6 @@
 		/* not ready */
 		return;
 	}
-	sc->sc_flags |= AXE_FLAG_WAIT_LINK;
 
 	if (mii->mii_instance) {
 		struct mii_softc *miisc;
@@ -550,6 +573,30 @@
 	err = usb2_config_td_sleep(&sc->sc_config_td, hz / 100);
 }
 
+static int
+axe_get_phyno(struct axe_softc *sc, int sel)
+{
+	int		phyno;
+
+	phyno = -1;
+	switch (AXE_PHY_TYPE(sc->sc_phyaddrs[sel])) {
+	case PHY_TYPE_100_HOME:
+	case PHY_TYPE_GIG:
+		phyno  = AXE_PHY_NO(sc->sc_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.
  */
@@ -617,8 +664,6 @@
 	}
 	mtx_lock(&sc->sc_mtx);
 
-	sc->sc_flags |= AXE_FLAG_WAIT_LINK;
-
 	/* start setup */
 
 	usb2_config_td_queue_command
@@ -687,6 +732,9 @@
 	axe_cfg_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
 	    AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
 	err = usb2_config_td_sleep(&sc->sc_config_td, hz / 4);
+	/* Enable MII/GMII/RGMII interface to work with external PHY. */
+	axe_cfg_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
+	err = usb2_config_td_sleep(&sc->sc_config_td, hz / 4);
 
 	axe_cfg_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
 }
@@ -701,7 +749,7 @@
 	axe_cfg_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
 	err = usb2_config_td_sleep(&sc->sc_config_td, hz / 16);
 
-	if (sc->sc_phyaddrs[1] == AXE_INTPHY) {
+	if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) {
 		/* ask for the embedded PHY */
 		axe_cfg_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
 		err = usb2_config_td_sleep(&sc->sc_config_td, hz / 64);
@@ -752,6 +800,18 @@
 	 * Load PHY indexes first. Needed by axe_xxx_init().
 	 */
 	axe_cfg_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, sc->sc_phyaddrs);
+#if 1
+	device_printf(sc->sc_dev, "PHYADDR 0x%02x:0x%02x\n",
+	    sc->sc_phyaddrs[0], sc->sc_phyaddrs[1]);
+#endif
+	sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI);
+	if (sc->sc_phyno == -1)
+		sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC);
+	if (sc->sc_phyno == -1) {
+		device_printf(sc->sc_dev,
+		 "no valid PHY address found, assuming PHY address 0\n");
+		sc->sc_phyno = 0;
+	}
 
 	if (sc->sc_flags & AXE_FLAG_178) {
 		axe_cfg_ax88178_init(sc);
@@ -771,12 +831,6 @@
 	 */
 	axe_cfg_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs);
 
-	/*
-	 * Work around broken adapters that appear to lie about
-	 * their PHY addresses.
-	 */
-	sc->sc_phyaddrs[0] = sc->sc_phyaddrs[1] = 0xFF;
-
 	mtx_unlock(&sc->sc_mtx);
 
 	ifp = if_alloc(IFT_ETHER);
@@ -1108,7 +1162,7 @@
 			usb2_transfer_start(sc->sc_xfer[2]);
 			goto done;
 		}
-		if (sc->sc_flags & AXE_FLAG_WAIT_LINK) {
+		if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
 			/*
 			 * don't send anything if there is no link !
 			 */
@@ -1204,19 +1258,17 @@
 		return;
 	}
 	mii_tick(mii);
-
-	mii_pollstat(mii);
-
-	if ((sc->sc_flags & AXE_FLAG_WAIT_LINK) &&
-	    (mii->mii_media_status & IFM_ACTIVE) &&
-	    (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) {
-		sc->sc_flags &= ~AXE_FLAG_WAIT_LINK;
-	}
 	sc->sc_media_active = mii->mii_media_active;
 	sc->sc_media_status = mii->mii_media_status;
-
+	if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
+		axe_cfg_miibus_statchg(sc->sc_dev);
+		/* XXX */
+		if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
+			sc->sc_media_active = IFM_ETHER | IFM_NONE;
+			sc->sc_media_status = IFM_AVALID;
+		}
+	}
 	/* start stopped transfers, if any */
-
 	axe_start_transfers(sc);
 }
 
@@ -1444,7 +1496,7 @@
 	sc->sc_flags &= ~(AXE_FLAG_HL_READY |
 	    AXE_FLAG_LL_READY);
 
-	sc->sc_flags |= AXE_FLAG_WAIT_LINK;
+	sc->sc_flags &= ~AXE_FLAG_LINK;
 
 	/*
 	 * stop all the transfers, if not already stopped:
--- if_axe2_reg.h.orig	2008-12-30 15:10:41.000000000 +0900
+++ if_axe2_reg.h	2008-12-30 15:35:18.000000000 +0900
@@ -135,8 +135,23 @@
 #define	AXE_178_RXCMD_MFB_8192			0x0200
 #define	AXE_178_RXCMD_MFB_16384			0x0300
 
-#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_772_PHY_NO_EPHY	0x10	/* Embedded 10/100 PHY of AX88772 */
 
 #define	AXE_BULK_BUF_SIZE	16384	/* bytes */
 
@@ -186,6 +201,7 @@
 
 	uint8_t	sc_ipgs[3];
 	uint8_t	sc_phyaddrs[2];
+	int	sc_phyno;
 
 	uint8_t	sc_name[16];
 };


More information about the freebsd-current mailing list