set bulk buffers according to link and bus speed. values are taken
from freebsd and linux drivers.
while here, only enable full duplex if link is also full duplex.
---
dev/usb/if_axen.c | 119 +++++++++++++++++++++++--------------------
dev/usb/if_axenreg.h | 13 +++--
2 files changed, 72 insertions(+), 60 deletions(-)
diff --git a/dev/usb/if_axen.c b/dev/usb/if_axen.c
index 909c04f..dfdcecf 100644
--- a/dev/usb/if_axen.c
+++ b/dev/usb/if_axen.c
@@ -120,6 +120,13 @@ void axen_unlock_mii(struct axen_softc *sc);
void axen_ax88179_init(struct axen_softc *);
+struct axen_qctrl axen_bulk_size[] = {
+ { 7, 0x4f, 0x00, AXEN_BUFSZ_SS, 0xff },
+ { 7, 0x20, 0x03, AXEN_BUFSZ_HS, 0xff },
+ { 7, 0xae, 0x07, AXEN_BUFSZ_LS, 0xff },
+ { 7, 0xcc, 0x4c, AXEN_BUFSZ_LS, 0x08 }
+};
+
/* Get exclusive access to the MII registers */
void
axen_lock_mii(struct axen_softc *sc)
@@ -235,13 +242,17 @@ axen_miibus_statchg(struct device *dev)
struct mii_data *mii = GET_MII(sc);
struct ifnet *ifp;
int err;
+ uint8_t link_status;
uint16_t val;
uWord wval;
+ struct axen_qctrl *qctrl;
+
+ axen_lock_mii(sc);
ifp = GET_IFP(sc);
if (mii == NULL || ifp == NULL ||
(ifp->if_flags & IFF_RUNNING) == 0)
- return;
+ goto done;
sc->axen_link = 0;
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
@@ -249,10 +260,8 @@ axen_miibus_statchg(struct device *dev)
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
case IFM_100_TX:
- sc->axen_link++;
- break;
case IFM_1000_T:
- sc->axen_link++;
+ sc->axen_link = 1;
break;
default:
break;
@@ -261,36 +270,68 @@ axen_miibus_statchg(struct device *dev)
/* Lost link, do nothing. */
if (sc->axen_link == 0)
- return;
+ goto done;
- val = 0;
- if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
- val |= AXEN_MEDIUM_FDX;
+ err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS,
+ &link_status);
+ if (err)
+ goto error;
- val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE);
- val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN);
+ /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE,
+ * but 6.2.2.10 of the datasheet (p40) sets it to 1 */
+ val = AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE;
+
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ val |= AXEN_MEDIUM_FDX;
+ val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN;
+ }
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_1000_T:
- val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
+ val |= AXEN_MEDIUM_GIGA;
+ if (link_status & AXEN_USB_SS)
+ qctrl = &axen_bulk_size[0];
+ else if (link_status & AXEN_USB_HS)
+ qctrl = &axen_bulk_size[1];
+ else
+ qctrl = &axen_bulk_size[3];
break;
case IFM_100_TX:
- val |= AXEN_MEDIUM_PS;
+ val |= AXEN_MEDIUM_PORTSPEED_100;
+ if (link_status & (AXEN_USB_SS | AXEN_USB_HS))
+ qctrl = &axen_bulk_size[2];
+ else
+ qctrl = &axen_bulk_size[3];
break;
case IFM_10_T:
- /* doesn't need to be handled */
+ qctrl = &axen_bulk_size[3];
break;
+ default:
+ printf("%s: unknown uplink bus: 0x%02x\n",
+ sc->axen_dev.dv_xname, link_status);
+ goto error;
}
+ /* XXX change buffer size here */
+
+ /* RX bulk configuration. */
+ err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+ qctrl);
+ if (err)
+ goto error;
- DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
+ DPRINTF(("%s: %s: val=0x%x\n", sc->axen_dev.dv_xname, __func__,val));
USETW(wval, val);
- axen_lock_mii(sc);
err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
+ if (err)
+ goto error;
+
+ goto done;
+
+error:
+ printf("%s: media change failed (err: 0x%x)\n", sc->axen_dev.dv_xname,
+ err);
+done:
axen_unlock_mii(sc);
- if (err) {
- printf("%s: media change failed\n", sc->axen_dev.dv_xname);
- return;
- }
}
/*
@@ -407,7 +448,6 @@ axen_ax88179_init(struct axen_softc *sc)
uWord wval;
uByte val;
u_int16_t ctl, temp;
- struct axen_qctrl qctrl;
axen_lock_mii(sc);
@@ -439,6 +479,10 @@ axen_ax88179_init(struct axen_softc *sc)
axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
usbd_delay_ms(sc->axen_udev, 100);
+ /* RX bulk configuration */
+ axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL,
+ &axen_bulk_size[0]);
+
/* set monitor mode (disable) */
val = AXEN_MONITOR_NONE;
axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
@@ -465,41 +509,6 @@ axen_ax88179_init(struct axen_softc *sc)
sc->axen_dev.dv_xname, ctl);
}
- /* bulkin queue setting */
- axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
- switch (val) {
- case AXEN_USB_FS:
- DPRINTF(("uplink: USB1.1\n"));
- qctrl.ctrl = 0x07;
- qctrl.timer_low = 0xcc;
- qctrl.timer_high= 0x4c;
- qctrl.bufsize = AXEN_BUFSZ_LS - 1;
- qctrl.ifg = 0x08;
- break;
- case AXEN_USB_HS:
- DPRINTF(("uplink: USB2.0\n"));
- qctrl.ctrl = 0x07;
- qctrl.timer_low = 0x02;
- qctrl.timer_high= 0xa0;
- qctrl.bufsize = AXEN_BUFSZ_HS - 1;
- qctrl.ifg = 0xff;
- break;
- case AXEN_USB_SS:
- DPRINTF(("uplink: USB3.0\n"));
- qctrl.ctrl = 0x07;
- qctrl.timer_low = 0x4f;
- qctrl.timer_high= 0x00;
- qctrl.bufsize = AXEN_BUFSZ_SS - 1;
- qctrl.ifg = 0xff;
- break;
- default:
- printf("%s: unknown uplink bus:0x%02x\n",
- sc->axen_dev.dv_xname, val);
- axen_unlock_mii(sc);
- return;
- }
- axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl);
-
/* Set MAC address. */
axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN,
AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr);
diff --git a/dev/usb/if_axenreg.h b/dev/usb/if_axenreg.h
index bbfb035..336727f 100644
--- a/dev/usb/if_axenreg.h
+++ b/dev/usb/if_axenreg.h
@@ -12,9 +12,9 @@
#define AXEN_PHY_ID 0x0003
#define AXEN_MCAST_FILTER_SIZE 8
/* unit: KB */
-#define AXEN_BUFSZ_LS 8
-#define AXEN_BUFSZ_HS 16
-#define AXEN_BUFSZ_SS 24
+#define AXEN_BUFSZ_LS 0x18
+#define AXEN_BUFSZ_HS 0x16
+#define AXEN_BUFSZ_SS 0x12
#define AXEN_REV_UA1 0
#define AXEN_REV_UA2 1
@@ -92,10 +92,13 @@
#define AXEN_CMD_MAC_READ 0x1001
#define AXEN_CMD_MAC_WRITE 0x1101
-#define AXEN_USB_UPLINK 0x02
+#define AXEN_PHYSICAL_LINK_STATUS 0x02
#define AXEN_USB_FS 0x01
#define AXEN_USB_HS 0x02
#define AXEN_USB_SS 0x04
+#define AXEN_EPHY_10 0x10
+#define AXEN_EPHY_100 0x20
+#define AXEN_EPHY_1000 0x40
#define AXEN_GENERAL_STATUS 0x03
#define AXEN_GENERAL_STATUS_MASK 0x4
#define AXEN_REV0 0x0
@@ -170,7 +173,7 @@
#define AXEN_MEDIUM_RXFLOW_CTRL_EN 0x0010
#define AXEN_MEDIUM_TXFLOW_CTRL_EN 0x0020
#define AXEN_MEDIUM_RECV_EN 0x0100
-#define AXEN_MEDIUM_PS 0x0200
+#define AXEN_MEDIUM_PORTSPEED_100 0x0200
#define AXEN_MEDIUM_JUMBO_EN 0x8040
#define AXEN_PHYPWR_RSTCTL 0x26
#define AXEN_PHYPWR_RSTCTL_BZ 0x0010
--
2.20.1