try to align attach/detach/init/stop routines with what freebsd and
linux are doing.

one important part of this diff is disabling Energy Efficient
Ethernet (EEE) and setting the low/high watermarks. this reduces
the amount of RXHDR_DROP_ERRs, but could maybe be tweaked (improved).

---
 dev/usb/if_axen.c    | 145 +++++++++++++++++++++++++++----------------
 dev/usb/if_axenreg.h |  20 +++++-
 2 files changed, 110 insertions(+), 55 deletions(-)

diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 088f40f..817cad8 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -433,13 +433,16 @@ axen_iff(struct axen_softc *sc)
 void
 axen_reset(struct axen_softc *sc)
 {
+       DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
+
        if (usbd_is_dying(sc->axen_udev))
                return;
-       
-       axen_ax88179_init(sc);
 
        /* Wait a little while for the chip to get its brains in order. */
        DELAY(1000);
+
+       axen_ax88179_init(sc);
+
        return;
 }
 
@@ -510,63 +513,65 @@ axen_ax88179_init(struct axen_softc *sc)
                    sc->axen_dev.dv_xname, ctl);
        }
 
-       /* Set MAC address. */
-       axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
-           AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
-
        /*
         * set buffer high/low watermark to pause/resume.
         * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
-        * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
-        * watermark parameters.
+        * XXX: what is the best value?
+        * - defaults (datasheet): 0x24-0x42 as LOW-HIGH watermark parameters.
+        * - OSX driver uses 0x3c-0x4c as LOW-HIGH watermark parameters.(?)
+        * - FreeBSD driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
+        * - Linux driver uses 0x34-0x52 as LOW-HIGH watermark parameters.
         */
-       val = 0x34;
+       val = 0x24;
        axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
-       val = 0x52;
+       val = 0x42;
        axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
 
        /* Set RX/TX configuration. */
-       /* Offloadng enable */
 #ifdef AXEN_TOE
-       val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
-             AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
+       /* enable offloading */
+       val = AXEN_RXCOE_IPv4 |
+             AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 | AXEN_RXCOE_ICMPv4 |
+             AXEN_RXCOE_IGMP |
+             AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6 | AXEN_RXCOE_ICMPv6;
 #else
        val = AXEN_RXCOE_OFF;
 #endif
        axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
 
 #ifdef AXEN_TOE
-       val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
-             AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
+       val = AXEN_TXCOE_IPv4 |
+             AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |AXEN_TXCOE_ICMPv4 |
+             AXEN_TXCOE_IGMP |
+             AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6 | AXEN_TXCOE_ICMPv6;
 #else
        val = AXEN_TXCOE_OFF;
 #endif
        axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
 
-       /* Set RX control register */
-       ctl = AXEN_RXCTL_DROPCRCERR;
-       ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
-       ctl |= AXEN_RXCTL_START;
-       USETW(wval, ctl);
-       axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
-
-       /* set monitor mode (enable) */
-       val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
+       /* set monitor mode (XXX enable) */
+       /* AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; */
+       val = 0;
        axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
+#ifdef AXEN_DEBUG
        axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
        DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
+#endif
 
        /* set medium type */
-       ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE |
-             AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN;
-       ctl |= AXEN_MEDIUM_RECV_EN;
+       ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX |
+             AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
+             AXEN_MEDIUM_RECV_EN;
        USETW(wval, ctl);
        DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval)));
        axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
-       usbd_delay_ms(sc->axen_udev, 100);
 
+#ifdef AXEN_DEBUG
+       usbd_delay_ms(sc->axen_udev, 100);
        axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
        DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval)));
+#endif
+
        axen_unlock_mii(sc);
 
 #if 0 /* XXX: TBD.... */
@@ -580,7 +585,15 @@ axen_ax88179_init(struct axen_softc *sc)
            0x002c);
 #endif
 
-#if 1 /* XXX: phy hack ? */
+       /* disable eee */
+       axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+           AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3);
+       axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+           AXEN_MII_PHYADDR, 0x3246);
+       axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno,
+           AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0);
+
+#if 0 /* XXX: phy hack ? */
        axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
        axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
        val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001);
@@ -631,16 +644,17 @@ axen_attach(struct device *parent, struct device *self, 
void *aux)
 
        id = usbd_get_interface_descriptor(sc->axen_iface);
 
-       /* decide on what our bufsize will be */
+       /*
+        * our bufsize is determined by the usb speed and link speed
+        * so set it to the biggest buffer (slowest speed) available
+        * this will be updated once the link state changes
+        */
        switch (sc->axen_udev->speed) {
        case USB_SPEED_FULL:
-               sc->axen_bufsz = AXEN_BUFSZ_LS * 1024; 
-               break;
        case USB_SPEED_HIGH:
-               sc->axen_bufsz = AXEN_BUFSZ_HS * 1024; 
-               break;
        case USB_SPEED_SUPER:
-               sc->axen_bufsz = AXEN_BUFSZ_SS * 1024; 
+               /* linux adds 2 to the buffer size (why?) */
+               sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024;
                break;
        default:
                printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
@@ -742,6 +756,8 @@ axen_detach(struct device *self, int flags)
        struct axen_softc       *sc = (struct axen_softc *)self;
        int                     s;
        struct ifnet            *ifp = GET_IFP(sc);
+       uWord                   wval;
+       u_int16_t               ctl;
 
        DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
 
@@ -769,9 +785,26 @@ axen_detach(struct device *self, int flags)
                usb_detach_wait(&sc->axen_dev);
        }
 
-       if (ifp->if_flags & IFF_RUNNING)
+       if (ifp->if_flags & IFF_RUNNING) {
                axen_stop(sc);
 
+               /* force bulk-in to return a zero-length USB packet */
+               axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+               ctl = UGETW(wval);
+               ctl |= AXEN_PHYPWR_RSTCTL_BZ | AXEN_PHYPWR_RSTCTL_IPRL;
+               ctl &= ~AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS;
+               USETW(wval, ctl);
+               axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
+
+               /* set clock to zero */
+               axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, 0);
+
+               /* disable MAC */
+               ctl = AXEN_RXCTL_STOP;
+               USETW(wval, ctl);
+               axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
+       }
+
        mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
        if (ifp->if_softc != NULL) {
@@ -1269,7 +1302,6 @@ axen_init(void *xsc)
        struct axen_chain       *c;
        usbd_status             err;
        int                     i, s;
-       uByte                   bval;
        uWord                   wval;
        uint16_t                rxmode;
 
@@ -1278,12 +1310,23 @@ axen_init(void *xsc)
        /*
         * Cancel pending I/O and free all RX/TX buffers.
         */
+       axen_stop(sc);
        axen_reset(sc);
 
-       /* XXX: ? */
-       bval = 0x01;
+       /* Set MAC address. */
+       axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
+           AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
+
+       /* Program promiscuous mode and multicast filters. */
+       axen_iff(sc);
+
+       /* Enable receiver, set RX mode */
        axen_lock_mii(sc);
-       axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
+       axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
+       rxmode = UGETW(wval);
+       rxmode |= AXEN_RXCTL_START;
+       USETW(wval, rxmode);
+       axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
        axen_unlock_mii(sc);
 
        /* Init RX ring. */
@@ -1300,18 +1343,6 @@ axen_init(void *xsc)
                return;
        }
 
-       /* Program promiscuous mode and multicast filters. */
-       axen_iff(sc);
-
-       /* Enable receiver, set RX mode */
-       axen_lock_mii(sc);
-       axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
-       rxmode = UGETW(wval);
-       rxmode |= AXEN_RXCTL_START;
-       USETW(wval, rxmode);
-       axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
-       axen_unlock_mii(sc);
-
        /* Open RX and TX pipes. */
        err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX],
            USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]);
@@ -1438,8 +1469,9 @@ axen_stop(struct axen_softc *sc)
        usbd_status             err;
        struct ifnet            *ifp;
        int                     i;
+       u_int16_t               ctl;
+       uWord                   wval;
 
-       axen_reset(sc);
 
        ifp = &sc->arpcom.ac_if;
        ifp->if_timer = 0;
@@ -1448,6 +1480,13 @@ axen_stop(struct axen_softc *sc)
 
        timeout_del(&sc->axen_stat_ch);
 
+       /* disable receive */
+       axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
+       ctl = UGETW(wval);
+       ctl &= ~AXEN_MEDIUM_RECV_EN;
+       USETW(wval, ctl);
+       axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
+
        /* Stop transfers. */
        if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
                usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_RX]);
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index 766c89e..bc594a0 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -15,6 +15,7 @@
 #define AXEN_BUFSZ_LS          0x18
 #define AXEN_BUFSZ_HS          0x16
 #define AXEN_BUFSZ_SS          0x12
+#define AXEN_BUFSZ_MAX         AXEN_BUFSZ_LS
 
 #define AXEN_REV_UA1           0
 #define AXEN_REV_UA2           1
@@ -129,7 +130,7 @@
 #define            AXEN_RXCOE_IPv4                       0x01
 #define            AXEN_RXCOE_TCPv4                      0x02
 #define            AXEN_RXCOE_UDPv4                      0x04
-#define            AXEN_RXCOE_ICMP                       0x08
+#define            AXEN_RXCOE_ICMPv4                     0x08
 #define            AXEN_RXCOE_IGMP                       0x10
 #define            AXEN_RXCOE_TCPv6                      0x20
 #define            AXEN_RXCOE_UDPv6                      0x40
@@ -139,7 +140,7 @@
 #define            AXEN_TXCOE_IPv4                       0x01
 #define            AXEN_TXCOE_TCPv4                      0x02
 #define            AXEN_TXCOE_UDPv4                      0x04
-#define            AXEN_TXCOE_ICMP                       0x08
+#define            AXEN_TXCOE_ICMPv4                     0x08
 #define            AXEN_TXCOE_IGMP                       0x10
 #define            AXEN_TXCOE_TCPv6                      0x20
 #define            AXEN_TXCOE_UDPv6                      0x40
@@ -176,6 +177,7 @@
 #define            AXEN_MEDIUM_PORTSPEED_100             0x0200
 #define            AXEN_MEDIUM_JUMBO_EN                  0x8040
 #define   AXEN_PHYPWR_RSTCTL                   0x26
+#define     AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS          0x0004
 #define     AXEN_PHYPWR_RSTCTL_BZ                0x0010
 #define     AXEN_PHYPWR_RSTCTL_IPRL              0x0020
 #define     AXEN_PHYPWR_RSTCTL_AUTODETACH        0x1000
@@ -220,6 +222,20 @@
 #define AXEN_TX_LIST_CNT               1
 
 
+/* ---GMII--- */
+#define AXEN_GMII_PHYPAGE                      0x1e
+#define AXEN_GMII_PHY_PAGE_SELECT              0x1f
+#define AXEN_GMII_PHY_PGSEL_EXT                          0x0007
+#define AXEN_GMII_PHY_PGSEL_PAGE0                0x0000
+#define AXEN_GMII_PHY_PGSEL_PAGE3                0x0003
+#define AXEN_GMII_PHY_PGSEL_PAGE5                0x0005
+#define AXEN_GMII_PHY_PGSEL_PAGE5                0x0005
+
+#define AXEN_MII_PHYADDR                       0x19
+#define AXEN_MII_PHYADDR_EEE_DIS                 0x3246
+#define AXEN_MII_PHYADDR_EEE_EN1                 0x3247
+#define AXEN_MII_PHYADDR_EEE_EN2                 0x0680
+
 /*
  * The interrupt endpoint is currently unused
  * by the ASIX part.
-- 
2.20.1

Reply via email to