[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    [axen 4/7] init/stop/attach/detach
From:       Nils Frohberg <nilsf () tako ! de>
Date:       2019-02-26 14:03:29
Message-ID: 20190226140329.GF20855 () tako ! de
[Download RAW message or body]

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

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic