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