Hello :)

After posting about a problem i had with my Linksys USB300M axe(4) adapter
(AX88772 based, phy not working correctly, cannot send anything)
    http://marc.info/?l=openbsd-misc&m=128050785229742&w=2
and reading from another similar problem
(adapter detected but not working)
    http://marc.info/?l=openbsd-misc&m=126869721215023&w=2
i adapted the FreeBSD patch linked by jsg@
    http://people.freebsd.org/~yongari/axe.88178.patch4
to OpenBSD.

It makes my adapter work, so thanks jsg@ for your post :)
Here it is, hope it can help someone else.
But it is very probable that i did not made things correctly,
so if someone has time to correct me, i'd be happy.

Index: if_axe.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_axe.c,v
retrieving revision 1.96
diff -u -r1.96 if_axe.c
--- if_axe.c    9 Jan 2010 05:33:08 -0000       1.96
+++ if_axe.c    29 Aug 2010 00:11:53 -0000
@@ -272,6 +272,7 @@
        struct axe_softc        *sc = (void *)dev;
        usbd_status             err;
        uWord                   val;
+       int                     ival;
 
        if (sc->axe_dying) {
                DPRINTF(("axe: dying\n"));
@@ -292,7 +293,7 @@
        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)
+       if (sc->axe_phyno != phy)
                return (0);
 
        USETW(val, 0);
@@ -310,10 +311,18 @@
        DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
            phy, reg, UGETW(val)));
 
-       if (UGETW(val) && UGETW(val) != 0xffff)
-               sc->axe_phyaddrs[0] = phy;
+       ival = UGETW(val);
+       if ((sc->axe_flags & AX772) != 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.
+               */
+              ival &= ~BMSR_EXTCAP;
+       }
 
-       return (UGETW(val));
+       return (ival);
 }
 
 void
@@ -325,6 +334,8 @@
 
        if (sc->axe_dying)
                return;
+       if (sc->axe_phyno != phy)
+               return;
 
        USETW(uval, val);
 
@@ -345,6 +356,7 @@
 {
        struct axe_softc        *sc = (void *)dev;
        struct mii_data         *mii = GET_MII(sc);
+       struct ifnet            *ifp;
        int                     val, err;
 
        if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
@@ -352,8 +364,41 @@
        else
                val = 0;
 
+       ifp = GET_IFP(sc);
+       if (mii == NULL || ifp == NULL ||
+           (ifp->if_flags & IFF_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 || sc->axe_flags & 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:
@@ -385,7 +430,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)
@@ -530,7 +574,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 the embedded PHY */
                axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
                usbd_delay_ms(sc->axe_udev, 10);
@@ -564,6 +608,30 @@
        axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
 }
 
+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.
  */
@@ -663,6 +731,16 @@
        DPRINTF((" phyaddrs[0]: %x phyaddrs[1]: %x\n",
            sc->axe_phyaddrs[0], sc->axe_phyaddrs[1]));
 
+       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) {
+               printf(" no valid PHY address found, assuming PHY address 0\n");
+               sc->axe_phyno = 0;
+       }
+
+       DPRINTF((" get_phyno %d\n", sc->axe_phyno));
+
        if (sc->axe_flags & AX178) {
                axe_ax88178_init(sc);
                printf(" AX88178");
@@ -686,12 +764,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;
-
-       /*
         * An ASIX chip was detected. Inform the world.
         */
        printf(", address %s\n", ether_sprintf(eaddr));
@@ -1122,15 +1194,8 @@
        s = splnet();
 
        mii_tick(mii);
-       if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE &&
-           IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
-               DPRINTF(("%s: %s: got link\n",
-                        sc->axe_dev.dv_xname, __func__));
-               sc->axe_link++;
-               if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-                          axe_start(ifp);
-       }
-
+       if (sc->axe_link == 0)
+               axe_miibus_statchg(&sc->axe_dev);
        timeout_add_sec(&sc->axe_stat_ch, 1);
 
        splx(s);
@@ -1330,6 +1395,7 @@
                usbd_transfer(c->axe_xfer);
        }
 
+       sc->axe_link = 0;
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
 
Index: if_axereg.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_axereg.h,v
retrieving revision 1.18
diff -u -r1.18 if_axereg.h
--- if_axereg.h 10 Jun 2007 10:15:35 -0000      1.18
+++ if_axereg.h 29 Aug 2010 00:11:53 -0000
@@ -131,8 +131,23 @@
 #define AXE_RXCMD_ENABLE                       0x0080
 #define AXE_178_RXCMD_MFB                      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_PHY_NO_AX772_EPHY   0x10    /* Embedded 10/100 PHY of 
AX88772 */
 
 #define AXE_TIMEOUT            1000
 #define AXE_172_BUFSZ          1536
@@ -222,6 +237,7 @@
        int                     axe_link;
        unsigned char           axe_ipgs[3];
        unsigned char           axe_phyaddrs[2];
+       int                     axe_phyno;
        struct timeval          axe_rx_notice;
        u_int                   axe_bufsz;
 };


Here is also a one line diff, because i found it strange to silently
say that we detected an adapter model with no clue.

--- if_axe.c.bak        Sun Aug 29 04:13:31 2010
+++ if_axe.c    Sun Aug 29 04:14:07 2010
@@ -748,7 +748,7 @@
                axe_ax88772_init(sc);
                printf(" AX88772");
        } else
-               printf(" AX88172");
+               printf(" unknown, assuming AX88172");
 
        /*
         * Get station address.


laurent

Reply via email to