[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