summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/net/if_axge.c
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2014-05-21 08:09:44 +0000
committerkevlo <kevlo@FreeBSD.org>2014-05-21 08:09:44 +0000
commit3592ecaa7e5926e236020e3ebeccd810bd2b551e (patch)
treeb66fae8a199522169b000ceaa6984ffa98ed4d4b /sys/dev/usb/net/if_axge.c
parent36856340953d62ec74d475c1579b1d3bd6a8e2d9 (diff)
downloadFreeBSD-src-3592ecaa7e5926e236020e3ebeccd810bd2b551e.zip
FreeBSD-src-3592ecaa7e5926e236020e3ebeccd810bd2b551e.tar.gz
- Configure Rx bulk
- Announce flow control capability to PHY drivers
Diffstat (limited to 'sys/dev/usb/net/if_axge.c')
-rw-r--r--sys/dev/usb/net/if_axge.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/sys/dev/usb/net/if_axge.c b/sys/dev/usb/net/if_axge.c
index caadb60..764adf1 100644
--- a/sys/dev/usb/net/if_axge.c
+++ b/sys/dev/usb/net/if_axge.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013 Kevin Lo
+ * Copyright (c) 2013-2014 Kevin Lo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,12 +71,16 @@ static const STRUCT_USB_HOST_ID axge_devs[] = {
};
static const struct {
- unsigned char ctrl, timer_l, timer_h, size, ifg;
-} AX88179_BULKIN_SIZE[] = {
- {7, 0x4f, 0, 0x12, 0xff},
- {7, 0x20, 3, 0x16, 0xff},
- {7, 0xae, 7, 0x18, 0xff},
- {7, 0xcc, 0x4c, 0x18, 8},
+ uint8_t ctrl;
+ uint8_t timer_l;
+ uint8_t timer_h;
+ uint8_t size;
+ uint8_t ifg;
+} axge_bulk_size[] = {
+ { 7, 0x4f, 0x00, 0x12, 0xff },
+ { 7, 0x20, 0x03, 0x16, 0xff },
+ { 7, 0xae, 0x07, 0x18, 0xff },
+ { 7, 0xcc, 0x4c, 0x18, 0x08 }
};
/* prototypes */
@@ -104,6 +108,8 @@ static int axge_read_mem(struct axge_softc *, uint8_t, uint16_t,
uint16_t, void *, int);
static void axge_write_mem(struct axge_softc *, uint8_t, uint16_t,
uint16_t, void *, int);
+static uint8_t axge_read_cmd_1(struct axge_softc *, uint8_t, uint16_t,
+ uint16_t);
static uint16_t axge_read_cmd_2(struct axge_softc *, uint8_t, uint16_t,
uint16_t);
static void axge_write_cmd_1(struct axge_softc *, uint8_t, uint16_t,
@@ -233,6 +239,16 @@ axge_write_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index,
}
}
+static uint8_t
+axge_read_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+ uint16_t reg)
+{
+ uint8_t val;
+
+ axge_read_mem(sc, cmd, index, reg, &val, 1);
+ return (val);
+}
+
static uint16_t
axge_read_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index,
uint16_t reg)
@@ -307,6 +323,7 @@ axge_miibus_statchg(device_t dev)
struct axge_softc *sc;
struct mii_data *mii;
struct ifnet *ifp;
+ uint8_t link_status, tmp[5];
uint16_t val;
int locked;
@@ -339,6 +356,8 @@ axge_miibus_statchg(device_t dev)
if ((sc->sc_flags & AXGE_FLAG_LINK) == 0)
goto done;
+ link_status = axge_read_cmd_1(sc, AXGE_ACCESS_MAC, 1, AXGE_LINK_STATUS);
+
val = 0;
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
val |= AXGE_MEDIUM_FULL_DUPLEX;
@@ -347,18 +366,32 @@ axge_miibus_statchg(device_t dev)
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
val |= AXGE_MEDIUM_RXFLOW_CTRLEN;
}
- val |= AXGE_MEDIUM_RECEIVE_EN | AXGE_MEDIUM_ALWAYS_ONE;
+ val |= AXGE_MEDIUM_RECEIVE_EN;
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_1000_T:
- val |= AXGE_MEDIUM_GIGAMODE;
+ val |= AXGE_MEDIUM_GIGAMODE | AXGE_MEDIUM_EN_125MHZ;
+ if (link_status & AXGE_LINK_STATUS_USB_SS)
+ memcpy(tmp, &axge_bulk_size[0], 5);
+ else if (link_status & AXGE_LINK_STATUS_USB_HS)
+ memcpy(tmp, &axge_bulk_size[1], 5);
+ else
+ memcpy(tmp, &axge_bulk_size[3], 5);
+ break;
case IFM_100_TX:
val |= AXGE_MEDIUM_PS;
+ if (link_status &
+ (AXGE_LINK_STATUS_USB_SS | AXGE_LINK_STATUS_USB_HS))
+ memcpy(tmp, &axge_bulk_size[2], 5);
+ else
+ memcpy(tmp, &axge_bulk_size[3], 5);
+ break;
case IFM_10_T:
- /* Doesn't need to be handled. */
+ memcpy(tmp, &axge_bulk_size[3], 5);
break;
}
+ /* Rx bulk configuration. */
+ axge_write_mem(sc, AXGE_ACCESS_MAC, 5, AXGE_RX_BULKIN_QCTRL, tmp, 5);
axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_MEDIUM_STATUS_MODE, val);
-
done:
if (!locked)
AXGE_UNLOCK(sc);
@@ -401,16 +434,12 @@ static void
axge_attach_post(struct usb_ether *ue)
{
struct axge_softc *sc;
- uint8_t tmp[5];
sc = uether_getsc(ue);
sc->sc_phyno = 3;
/* Initialize controller and get station address. */
axge_chip_init(sc);
-
- memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
- axge_read_mem(sc, AXGE_ACCESS_MAC, 5, AXGE_RX_BULKIN_QCTRL, tmp, 5);
axge_read_mem(sc, AXGE_ACCESS_MAC, ETHER_ADDR_LEN, AXGE_NODE_ID,
ue->ue_eaddr, ETHER_ADDR_LEN);
}
@@ -439,7 +468,7 @@ axge_attach_post_sub(struct usb_ether *ue)
mtx_lock(&Giant);
error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
- BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0);
+ BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, MIIF_DOPAUSE);
mtx_unlock(&Giant);
return (error);
OpenPOWER on IntegriCloud