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