merged changes from 8.2 FreeBSD release for ale, alc and ae drivers
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42317 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c0535fa096
commit
aaebe6a96f
@ -28,7 +28,7 @@
|
||||
/* Driver for Atheros AR8121/AR8113/AR8114 PCIe Ethernet. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/ale/if_ale.c,v 1.3 2008/12/03 09:01:12 yongari Exp $");
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -78,9 +78,6 @@ __FBSDID("$FreeBSD: src/sys/dev/ale/if_ale.c,v 1.3 2008/12/03 09:01:12 yongari E
|
||||
|
||||
/* For more information about Tx checksum offload issues see ale_encap(). */
|
||||
#define ALE_CSUM_FEATURES (CSUM_TCP | CSUM_UDP)
|
||||
#ifndef IFCAP_VLAN_HWTSO
|
||||
#define IFCAP_VLAN_HWTSO 0
|
||||
#endif
|
||||
|
||||
MODULE_DEPEND(ale, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(ale, ether, 1, 1, 1);
|
||||
@ -211,9 +208,6 @@ ale_miibus_readreg(device_t dev, int phy, int reg)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (phy != sc->ale_phyaddr)
|
||||
return (0);
|
||||
|
||||
CSR_WRITE_4(sc, ALE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
|
||||
MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
|
||||
for (i = ALE_PHY_TIMEOUT; i > 0; i--) {
|
||||
@ -240,9 +234,6 @@ ale_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (phy != sc->ale_phyaddr)
|
||||
return (0);
|
||||
|
||||
CSR_WRITE_4(sc, ALE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
|
||||
(val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
|
||||
MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
|
||||
@ -610,18 +601,28 @@ ale_attach(device_t dev)
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
|
||||
/* Set up MII bus. */
|
||||
if ((error = mii_phy_probe(dev, &sc->ale_miibus, ale_mediachange,
|
||||
ale_mediastatus)) != 0) {
|
||||
device_printf(dev, "no PHY found!\n");
|
||||
error = mii_attach(dev, &sc->ale_miibus, ifp, ale_mediachange,
|
||||
ale_mediastatus, BMSR_DEFCAPMASK, sc->ale_phyaddr, MII_OFFSET_ANY,
|
||||
0);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "attaching PHYs failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ether_ifattach(ifp, sc->ale_eaddr);
|
||||
|
||||
/* VLAN capability setup. */
|
||||
ifp->if_capabilities |= IFCAP_VLAN_MTU;
|
||||
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM;
|
||||
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
|
||||
IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO;
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
/*
|
||||
* Even though controllers supported by ale(3) have Rx checksum
|
||||
* offload bug the workaround for fragmented frames seemed to
|
||||
* work so far. However it seems Rx checksum offload does not
|
||||
* work under certain conditions. So disable Rx checksum offload
|
||||
* until I find more clue about it but allow users to override it.
|
||||
*/
|
||||
ifp->if_capenable &= ~IFCAP_RXCSUM;
|
||||
|
||||
/* Tell the upper layer(s) we support long frames. */
|
||||
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
|
||||
@ -1549,20 +1550,11 @@ ale_resume(device_t dev)
|
||||
struct ale_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int pmc;
|
||||
uint16_t cmd, pmstat;
|
||||
uint16_t pmstat;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
ALE_LOCK(sc);
|
||||
/*
|
||||
* Clear INTx emulation disable for hardwares that
|
||||
* is set in resume event. From Linux.
|
||||
*/
|
||||
cmd = pci_read_config(sc->ale_dev, PCIR_COMMAND, 2);
|
||||
if ((cmd & 0x0400) != 0) {
|
||||
cmd &= ~0x0400;
|
||||
pci_write_config(sc->ale_dev, PCIR_COMMAND, cmd, 2);
|
||||
}
|
||||
if (pci_find_extcap(sc->ale_dev, PCIY_PMG, &pmc) == 0) {
|
||||
/* Disable PME and clear PME status. */
|
||||
pmstat = pci_read_config(sc->ale_dev,
|
||||
@ -1595,7 +1587,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
|
||||
struct tcphdr *tcp;
|
||||
bus_dma_segment_t txsegs[ALE_MAXTXSEGS];
|
||||
bus_dmamap_t map;
|
||||
uint32_t cflags, ip_off, poff, vtag;
|
||||
uint32_t cflags, hdrlen, ip_off, poff, vtag;
|
||||
int error, i, nsegs, prod, si;
|
||||
|
||||
ALE_LOCK_ASSERT(sc);
|
||||
@ -1687,7 +1679,13 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
|
||||
*m_head = NULL;
|
||||
return (ENOBUFS);
|
||||
}
|
||||
ip = (struct ip *)(mtod(m, char *) + ip_off);
|
||||
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
|
||||
m = m_pullup(m, poff + (tcp->th_off << 2));
|
||||
if (m == NULL) {
|
||||
*m_head = NULL;
|
||||
return (ENOBUFS);
|
||||
}
|
||||
/*
|
||||
* AR81xx requires IP/TCP header size and offset as
|
||||
* well as TCP pseudo checksum which complicates
|
||||
@ -1740,15 +1738,21 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
|
||||
}
|
||||
|
||||
/* Check descriptor overrun. */
|
||||
if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 2) {
|
||||
if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 3) {
|
||||
bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, map);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
bus_dmamap_sync(sc->ale_cdata.ale_tx_tag, map, BUS_DMASYNC_PREWRITE);
|
||||
|
||||
m = *m_head;
|
||||
/* Configure Tx checksum offload. */
|
||||
if ((m->m_pkthdr.csum_flags & ALE_CSUM_FEATURES) != 0) {
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
/* Request TSO and set MSS. */
|
||||
cflags |= ALE_TD_TSO;
|
||||
cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << ALE_TD_MSS_SHIFT);
|
||||
/* Set IP/TCP header size. */
|
||||
cflags |= ip->ip_hl << ALE_TD_IPHDR_LEN_SHIFT;
|
||||
cflags |= tcp->th_off << ALE_TD_TCPHDR_LEN_SHIFT;
|
||||
} else if ((m->m_pkthdr.csum_flags & ALE_CSUM_FEATURES) != 0) {
|
||||
/*
|
||||
* AR81xx supports Tx custom checksum offload feature
|
||||
* that offloads single 16bit checksum computation.
|
||||
@ -1779,15 +1783,6 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
|
||||
ALE_TD_CSUM_XSUMOFFSET_SHIFT);
|
||||
}
|
||||
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
/* Request TSO and set MSS. */
|
||||
cflags |= ALE_TD_TSO;
|
||||
cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << ALE_TD_MSS_SHIFT);
|
||||
/* Set IP/TCP header size. */
|
||||
cflags |= ip->ip_hl << ALE_TD_IPHDR_LEN_SHIFT;
|
||||
cflags |= tcp->th_off << ALE_TD_TCPHDR_LEN_SHIFT;
|
||||
}
|
||||
|
||||
/* Configure VLAN hardware tag insertion. */
|
||||
if ((m->m_flags & M_VLANTAG) != 0) {
|
||||
vtag = ALE_TX_VLAN_TAG(m->m_pkthdr.ether_vtag);
|
||||
@ -1795,8 +1790,32 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
|
||||
cflags |= ALE_TD_INSERT_VLAN_TAG;
|
||||
}
|
||||
|
||||
desc = NULL;
|
||||
for (i = 0; i < nsegs; i++) {
|
||||
i = 0;
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
/*
|
||||
* Make sure the first fragment contains
|
||||
* only ethernet and IP/TCP header with options.
|
||||
*/
|
||||
hdrlen = poff + (tcp->th_off << 2);
|
||||
desc = &sc->ale_cdata.ale_tx_ring[prod];
|
||||
desc->addr = htole64(txsegs[i].ds_addr);
|
||||
desc->len = htole32(ALE_TX_BYTES(hdrlen) | vtag);
|
||||
desc->flags = htole32(cflags);
|
||||
sc->ale_cdata.ale_tx_cnt++;
|
||||
ALE_DESC_INC(prod, ALE_TX_RING_CNT);
|
||||
if (m->m_len - hdrlen > 0) {
|
||||
/* Handle remaining payload of the first fragment. */
|
||||
desc = &sc->ale_cdata.ale_tx_ring[prod];
|
||||
desc->addr = htole64(txsegs[i].ds_addr + hdrlen);
|
||||
desc->len = htole32(ALE_TX_BYTES(m->m_len - hdrlen) |
|
||||
vtag);
|
||||
desc->flags = htole32(cflags);
|
||||
sc->ale_cdata.ale_tx_cnt++;
|
||||
ALE_DESC_INC(prod, ALE_TX_RING_CNT);
|
||||
}
|
||||
i = 1;
|
||||
}
|
||||
for (; i < nsegs; i++) {
|
||||
desc = &sc->ale_cdata.ale_tx_ring[prod];
|
||||
desc->addr = htole64(txsegs[i].ds_addr);
|
||||
desc->len = htole32(ALE_TX_BYTES(txsegs[i].ds_len) | vtag);
|
||||
@ -2003,6 +2022,7 @@ ale_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
else
|
||||
ifp->if_hwassist &= ~CSUM_TSO;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WOL
|
||||
if ((mask & IFCAP_WOL_MCAST) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_WOL_MCAST) != 0)
|
||||
@ -2011,28 +2031,19 @@ ale_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
(ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0)
|
||||
ifp->if_capenable ^= IFCAP_WOL_MAGIC;
|
||||
#endif
|
||||
if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) {
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
|
||||
ale_rxvlan(sc);
|
||||
}
|
||||
if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
|
||||
if ((mask & IFCAP_VLAN_HWTSO) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0)
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
|
||||
/*
|
||||
* VLAN hardware tagging is required to do checksum
|
||||
* offload or TSO on VLAN interface. Checksum offload
|
||||
* on VLAN interface also requires hardware checksum
|
||||
* offload of parent interface.
|
||||
*/
|
||||
if ((ifp->if_capenable & IFCAP_TXCSUM) == 0)
|
||||
ifp->if_capenable &= ~IFCAP_VLAN_HWCSUM;
|
||||
if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) {
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
|
||||
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
|
||||
ifp->if_capenable &=
|
||||
~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM);
|
||||
ifp->if_capenable &= ~IFCAP_VLAN_HWTSO;
|
||||
ale_rxvlan(sc);
|
||||
}
|
||||
ALE_UNLOCK(sc);
|
||||
VLAN_CAPABILITIES(ifp);
|
||||
break;
|
||||
@ -3063,15 +3074,15 @@ ale_rxfilter(struct ale_softc *sc)
|
||||
/* Program new filter. */
|
||||
bzero(mchash, sizeof(mchash));
|
||||
|
||||
IF_ADDR_LOCK(ifp);
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &sc->ale_ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
|
||||
crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
||||
ifma->ifma_addr), ETHER_ADDR_LEN);
|
||||
mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
if_maddr_runlock(ifp);
|
||||
|
||||
CSR_WRITE_4(sc, ALE_MAR0, mchash[0]);
|
||||
CSR_WRITE_4(sc, ALE_MAR1, mchash[1]);
|
||||
|
@ -24,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMATE.
|
||||
*
|
||||
* $FreeBSD: src/sys/dev/ale/if_alereg.h,v 1.1.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IF_ALEREG_H
|
||||
|
@ -24,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/dev/ale/if_alevar.h,v 1.1.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IF_ALEVAR_H
|
||||
|
@ -25,7 +25,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Driver for Atheros AR8131/AR8132 PCIe Ethernet. */
|
||||
/* Driver for Atheros AR813x/AR815x PCIe Ethernet. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
@ -84,9 +84,6 @@ __FBSDID("$FreeBSD$");
|
||||
#else
|
||||
#define ALC_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
|
||||
#endif
|
||||
#ifndef IFCAP_VLAN_HWTSO
|
||||
#define IFCAP_VLAN_HWTSO 0
|
||||
#endif
|
||||
|
||||
MODULE_DEPEND(alc, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(alc, ether, 1, 1, 1);
|
||||
@ -101,18 +98,23 @@ TUNABLE_INT("hw.alc.msix_disable", &msix_disable);
|
||||
/*
|
||||
* Devices supported by this driver.
|
||||
*/
|
||||
static struct alc_dev {
|
||||
uint16_t alc_vendorid;
|
||||
uint16_t alc_deviceid;
|
||||
const char *alc_name;
|
||||
} alc_devs[] = {
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8131,
|
||||
static struct alc_ident alc_ident_table[] = {
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8131, 9 * 1024,
|
||||
"Atheros AR8131 PCIe Gigabit Ethernet" },
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8132,
|
||||
"Atheros AR8132 PCIe Fast Ethernet" }
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8132, 9 * 1024,
|
||||
"Atheros AR8132 PCIe Fast Ethernet" },
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8151, 6 * 1024,
|
||||
"Atheros AR8151 v1.0 PCIe Gigabit Ethernet" },
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8151_V2, 6 * 1024,
|
||||
"Atheros AR8151 v2.0 PCIe Gigabit Ethernet" },
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8152_B, 6 * 1024,
|
||||
"Atheros AR8152 v1.1 PCIe Fast Ethernet" },
|
||||
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8152_B2, 6 * 1024,
|
||||
"Atheros AR8152 v2.0 PCIe Fast Ethernet" },
|
||||
{ 0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static void alc_aspm(struct alc_softc *);
|
||||
static void alc_aspm(struct alc_softc *, int);
|
||||
static int alc_attach(device_t);
|
||||
static int alc_check_boundary(struct alc_softc *);
|
||||
static int alc_detach(device_t);
|
||||
@ -121,6 +123,8 @@ static int alc_dma_alloc(struct alc_softc *);
|
||||
static void alc_dma_free(struct alc_softc *);
|
||||
static void alc_dmamap_cb(void *, bus_dma_segment_t *, int, int);
|
||||
static int alc_encap(struct alc_softc *, struct mbuf **);
|
||||
static struct alc_ident *
|
||||
alc_find_ident(device_t);
|
||||
#ifndef __NO_STRICT_ALIGNMENT
|
||||
static struct mbuf *
|
||||
alc_fixup_rx(struct ifnet *, struct mbuf *);
|
||||
@ -231,7 +235,14 @@ alc_miibus_readreg(device_t dev, int phy, int reg)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (phy != sc->alc_phyaddr)
|
||||
/*
|
||||
* For AR8132 fast ethernet controller, do not report 1000baseT
|
||||
* capability to mii(4). Even though AR8132 uses the same
|
||||
* model/revision number of F1 gigabit PHY, the PHY has no
|
||||
* ability to establish 1000baseT link.
|
||||
*/
|
||||
if ((sc->alc_flags & ALC_FLAG_FASTETHER) != 0 &&
|
||||
reg == MII_EXTSR)
|
||||
return (0);
|
||||
|
||||
CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
|
||||
@ -260,9 +271,6 @@ alc_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (phy != sc->alc_phyaddr)
|
||||
return (0);
|
||||
|
||||
CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
|
||||
(val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
|
||||
MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
|
||||
@ -323,8 +331,8 @@ alc_miibus_statchg(device_t dev)
|
||||
reg = CSR_READ_4(sc, ALC_MAC_CFG);
|
||||
reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
|
||||
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
|
||||
alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active));
|
||||
}
|
||||
alc_aspm(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -368,23 +376,31 @@ alc_mediachange(struct ifnet *ifp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
alc_probe(device_t dev)
|
||||
static struct alc_ident *
|
||||
alc_find_ident(device_t dev)
|
||||
{
|
||||
struct alc_dev *sp;
|
||||
int i;
|
||||
struct alc_ident *ident;
|
||||
uint16_t vendor, devid;
|
||||
|
||||
vendor = pci_get_vendor(dev);
|
||||
devid = pci_get_device(dev);
|
||||
sp = alc_devs;
|
||||
for (i = 0; i < sizeof(alc_devs) / sizeof(alc_devs[0]); i++) {
|
||||
if (vendor == sp->alc_vendorid &&
|
||||
devid == sp->alc_deviceid) {
|
||||
device_set_desc(dev, sp->alc_name);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
for (ident = alc_ident_table; ident->name != NULL; ident++) {
|
||||
if (vendor == ident->vendorid && devid == ident->deviceid)
|
||||
return (ident);
|
||||
}
|
||||
sp++;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
alc_probe(device_t dev)
|
||||
{
|
||||
struct alc_ident *ident;
|
||||
|
||||
ident = alc_find_ident(dev);
|
||||
if (ident != NULL) {
|
||||
device_set_desc(dev, ident->name);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
@ -394,20 +410,53 @@ static void
|
||||
alc_get_macaddr(struct alc_softc *sc)
|
||||
{
|
||||
uint32_t ea[2], opt;
|
||||
int i;
|
||||
uint16_t val;
|
||||
int eeprom, i;
|
||||
|
||||
eeprom = 0;
|
||||
opt = CSR_READ_4(sc, ALC_OPT_CFG);
|
||||
if ((CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
|
||||
if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_OTP_SEL) != 0 &&
|
||||
(CSR_READ_4(sc, ALC_TWSI_DEBUG) & TWSI_DEBUG_DEV_EXIST) != 0) {
|
||||
/*
|
||||
* EEPROM found, let TWSI reload EEPROM configuration.
|
||||
* This will set ethernet address of controller.
|
||||
*/
|
||||
eeprom++;
|
||||
switch (sc->alc_ident->deviceid) {
|
||||
case DEVICEID_ATHEROS_AR8131:
|
||||
case DEVICEID_ATHEROS_AR8132:
|
||||
if ((opt & OPT_CFG_CLK_ENB) == 0) {
|
||||
opt |= OPT_CFG_CLK_ENB;
|
||||
CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
|
||||
CSR_READ_4(sc, ALC_OPT_CFG);
|
||||
DELAY(1000);
|
||||
}
|
||||
break;
|
||||
case DEVICEID_ATHEROS_AR8151:
|
||||
case DEVICEID_ATHEROS_AR8151_V2:
|
||||
case DEVICEID_ATHEROS_AR8152_B:
|
||||
case DEVICEID_ATHEROS_AR8152_B2:
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x00);
|
||||
val = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, val & 0xFF7F);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x3B);
|
||||
val = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, val | 0x0008);
|
||||
DELAY(20);
|
||||
break;
|
||||
}
|
||||
|
||||
CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
|
||||
CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
|
||||
CSR_WRITE_4(sc, ALC_WOL_CFG, 0);
|
||||
CSR_READ_4(sc, ALC_WOL_CFG);
|
||||
|
||||
CSR_WRITE_4(sc, ALC_TWSI_CFG, CSR_READ_4(sc, ALC_TWSI_CFG) |
|
||||
TWSI_CFG_SW_LD_START);
|
||||
for (i = 100; i > 0; i--) {
|
||||
@ -423,12 +472,37 @@ alc_get_macaddr(struct alc_softc *sc)
|
||||
if (bootverbose)
|
||||
device_printf(sc->alc_dev, "EEPROM not found!\n");
|
||||
}
|
||||
if (eeprom != 0) {
|
||||
switch (sc->alc_ident->deviceid) {
|
||||
case DEVICEID_ATHEROS_AR8131:
|
||||
case DEVICEID_ATHEROS_AR8132:
|
||||
if ((opt & OPT_CFG_CLK_ENB) != 0) {
|
||||
opt &= ~OPT_CFG_CLK_ENB;
|
||||
CSR_WRITE_4(sc, ALC_OPT_CFG, opt);
|
||||
CSR_READ_4(sc, ALC_OPT_CFG);
|
||||
DELAY(1000);
|
||||
}
|
||||
break;
|
||||
case DEVICEID_ATHEROS_AR8151:
|
||||
case DEVICEID_ATHEROS_AR8151_V2:
|
||||
case DEVICEID_ATHEROS_AR8152_B:
|
||||
case DEVICEID_ATHEROS_AR8152_B2:
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x00);
|
||||
val = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, val | 0x0080);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x3B);
|
||||
val = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, val & 0xFFF7);
|
||||
DELAY(20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ea[0] = CSR_READ_4(sc, ALC_PAR0);
|
||||
ea[1] = CSR_READ_4(sc, ALC_PAR1);
|
||||
@ -472,6 +546,43 @@ alc_phy_reset(struct alc_softc *sc)
|
||||
CSR_READ_2(sc, ALC_GPHY_CFG);
|
||||
DELAY(10 * 1000);
|
||||
|
||||
/* DSP fixup, Vendor magic. */
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B) {
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x000A);
|
||||
data = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, data & 0xDFFF);
|
||||
}
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2) {
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x003B);
|
||||
data = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, data & 0xFFF7);
|
||||
DELAY(20 * 1000);
|
||||
}
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151) {
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x0029);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, 0x929D);
|
||||
}
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8131 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8132 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2) {
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_ADDR, 0x0029);
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
ALC_MII_DBG_DATA, 0xB6DD);
|
||||
}
|
||||
|
||||
/* Load DSP codes, vendor magic. */
|
||||
data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
|
||||
((1 << ANA_INTERVAL_SEL_TIMER_SHIFT) & ANA_INTERVAL_SEL_TIMER_MASK);
|
||||
@ -521,36 +632,117 @@ static void
|
||||
alc_phy_down(struct alc_softc *sc)
|
||||
{
|
||||
|
||||
switch (sc->alc_ident->deviceid) {
|
||||
case DEVICEID_ATHEROS_AR8151:
|
||||
case DEVICEID_ATHEROS_AR8151_V2:
|
||||
/*
|
||||
* GPHY power down caused more problems on AR8151 v2.0.
|
||||
* When driver is reloaded after GPHY power down,
|
||||
* accesses to PHY/MAC registers hung the system. Only
|
||||
* cold boot recovered from it. I'm not sure whether
|
||||
* AR8151 v1.0 also requires this one though. I don't
|
||||
* have AR8151 v1.0 controller in hand.
|
||||
* The only option left is to isolate the PHY and
|
||||
* initiates power down the PHY which in turn saves
|
||||
* more power when driver is unloaded.
|
||||
*/
|
||||
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
|
||||
MII_BMCR, BMCR_ISO | BMCR_PDOWN);
|
||||
break;
|
||||
default:
|
||||
/* Force PHY down. */
|
||||
CSR_WRITE_2(sc, ALC_GPHY_CFG,
|
||||
GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
|
||||
GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW);
|
||||
GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ |
|
||||
GPHY_CFG_PWDOWN_HW);
|
||||
DELAY(1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
alc_aspm(struct alc_softc *sc)
|
||||
alc_aspm(struct alc_softc *sc, int media)
|
||||
{
|
||||
uint32_t pmcfg;
|
||||
uint16_t linkcfg;
|
||||
|
||||
ALC_LOCK_ASSERT(sc);
|
||||
|
||||
pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
|
||||
if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
|
||||
(ALC_FLAG_APS | ALC_FLAG_PCIE))
|
||||
linkcfg = CSR_READ_2(sc, sc->alc_expcap +
|
||||
PCIR_EXPRESS_LINK_CTL);
|
||||
else
|
||||
linkcfg = 0;
|
||||
pmcfg &= ~PM_CFG_SERDES_PD_EX_L1;
|
||||
pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB;
|
||||
pmcfg |= PM_CFG_SERDES_L1_ENB;
|
||||
pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
|
||||
pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_LCKDET_TIMER_MASK);
|
||||
pmcfg |= PM_CFG_MAC_ASPM_CHK;
|
||||
pmcfg |= PM_CFG_SERDES_ENB | PM_CFG_RBER_ENB;
|
||||
pmcfg &= ~(PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
|
||||
|
||||
if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
|
||||
/* Disable extended sync except AR8152 B v1.0 */
|
||||
linkcfg &= ~0x80;
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B &&
|
||||
sc->alc_rev == ATHEROS_AR8152_B_V10)
|
||||
linkcfg |= 0x80;
|
||||
CSR_WRITE_2(sc, sc->alc_expcap + PCIR_EXPRESS_LINK_CTL,
|
||||
linkcfg);
|
||||
pmcfg &= ~(PM_CFG_EN_BUFS_RX_L0S | PM_CFG_SA_DLY_ENB |
|
||||
PM_CFG_HOTRST);
|
||||
pmcfg |= (PM_CFG_L1_ENTRY_TIMER_DEFAULT <<
|
||||
PM_CFG_L1_ENTRY_TIMER_SHIFT);
|
||||
pmcfg &= ~PM_CFG_PM_REQ_TIMER_MASK;
|
||||
pmcfg |= (PM_CFG_PM_REQ_TIMER_DEFAULT <<
|
||||
PM_CFG_PM_REQ_TIMER_SHIFT);
|
||||
pmcfg |= PM_CFG_SERDES_PD_EX_L1 | PM_CFG_PCIE_RECV;
|
||||
}
|
||||
|
||||
if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
|
||||
pmcfg |= PM_CFG_SERDES_PLL_L1_ENB;
|
||||
pmcfg &= ~PM_CFG_CLK_SWH_L1;
|
||||
pmcfg &= ~PM_CFG_ASPM_L1_ENB;
|
||||
if ((sc->alc_flags & ALC_FLAG_L0S) != 0)
|
||||
pmcfg |= PM_CFG_ASPM_L0S_ENB;
|
||||
if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
|
||||
pmcfg |= PM_CFG_ASPM_L1_ENB;
|
||||
if ((sc->alc_flags & ALC_FLAG_APS) != 0) {
|
||||
if (sc->alc_ident->deviceid ==
|
||||
DEVICEID_ATHEROS_AR8152_B)
|
||||
pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
|
||||
} else {
|
||||
pmcfg &= ~PM_CFG_SERDES_PLL_L1_ENB;
|
||||
pmcfg &= ~(PM_CFG_SERDES_L1_ENB |
|
||||
PM_CFG_SERDES_PLL_L1_ENB |
|
||||
PM_CFG_SERDES_BUDS_RX_L1_ENB);
|
||||
pmcfg |= PM_CFG_CLK_SWH_L1;
|
||||
pmcfg &= ~PM_CFG_ASPM_L1_ENB;
|
||||
pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
|
||||
if (media == IFM_100_TX || media == IFM_1000_T) {
|
||||
pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
|
||||
switch (sc->alc_ident->deviceid) {
|
||||
case DEVICEID_ATHEROS_AR8152_B:
|
||||
pmcfg |= (7 <<
|
||||
PM_CFG_L1_ENTRY_TIMER_SHIFT);
|
||||
break;
|
||||
case DEVICEID_ATHEROS_AR8152_B2:
|
||||
case DEVICEID_ATHEROS_AR8151_V2:
|
||||
pmcfg |= (4 <<
|
||||
PM_CFG_L1_ENTRY_TIMER_SHIFT);
|
||||
break;
|
||||
default:
|
||||
pmcfg |= (15 <<
|
||||
PM_CFG_L1_ENTRY_TIMER_SHIFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pmcfg |= PM_CFG_SERDES_L1_ENB |
|
||||
PM_CFG_SERDES_PLL_L1_ENB |
|
||||
PM_CFG_SERDES_BUDS_RX_L1_ENB;
|
||||
pmcfg &= ~(PM_CFG_CLK_SWH_L1 |
|
||||
PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB);
|
||||
}
|
||||
} else {
|
||||
pmcfg &= ~(PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SERDES_L1_ENB |
|
||||
PM_CFG_SERDES_PLL_L1_ENB);
|
||||
pmcfg |= PM_CFG_CLK_SWH_L1;
|
||||
if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
|
||||
pmcfg |= PM_CFG_ASPM_L1_ENB;
|
||||
}
|
||||
CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
|
||||
}
|
||||
@ -560,9 +752,9 @@ alc_attach(device_t dev)
|
||||
{
|
||||
struct alc_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/l1" };
|
||||
char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
|
||||
uint16_t burst;
|
||||
int base, error, i, msic, msixc, pmc, state;
|
||||
int base, error, i, msic, msixc, state;
|
||||
uint32_t cap, ctl, val;
|
||||
|
||||
error = 0;
|
||||
@ -573,6 +765,7 @@ alc_attach(device_t dev)
|
||||
MTX_DEF);
|
||||
callout_init_mtx(&sc->alc_tick_ch, &sc->alc_mtx, 0);
|
||||
TASK_INIT(&sc->alc_int_task, 0, alc_int_task, sc);
|
||||
sc->alc_ident = alc_find_ident(dev);
|
||||
|
||||
/* Map the device. */
|
||||
pci_enable_busmaster(dev);
|
||||
@ -593,6 +786,7 @@ alc_attach(device_t dev)
|
||||
sc->alc_rcb = DMA_CFG_RCB_64;
|
||||
if (pci_find_extcap(dev, PCIY_EXPRESS, &base) == 0) {
|
||||
sc->alc_flags |= ALC_FLAG_PCIE;
|
||||
sc->alc_expcap = base;
|
||||
burst = CSR_READ_2(sc, base + PCIR_EXPRESS_DEVICE_CTL);
|
||||
sc->alc_dma_rd_burst =
|
||||
(burst & PCIM_EXP_CTL_MAX_READ_REQUEST) >> 12;
|
||||
@ -603,10 +797,28 @@ alc_attach(device_t dev)
|
||||
device_printf(dev, "TLP payload size : %u bytes.\n",
|
||||
alc_dma_burst[sc->alc_dma_wr_burst]);
|
||||
}
|
||||
if (alc_dma_burst[sc->alc_dma_rd_burst] > 1024)
|
||||
sc->alc_dma_rd_burst = 3;
|
||||
if (alc_dma_burst[sc->alc_dma_wr_burst] > 1024)
|
||||
sc->alc_dma_wr_burst = 3;
|
||||
/* Clear data link and flow-control protocol error. */
|
||||
val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
|
||||
val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
|
||||
CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
|
||||
CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
|
||||
CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
|
||||
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
|
||||
CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
|
||||
PCIE_PHYMISC_FORCE_RCV_DET);
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B &&
|
||||
sc->alc_rev == ATHEROS_AR8152_B_V10) {
|
||||
val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
|
||||
val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
|
||||
PCIE_PHYMISC2_SERDES_TH_MASK);
|
||||
val |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
|
||||
val |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
|
||||
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
|
||||
}
|
||||
/* Disable ASPM L0S and L1. */
|
||||
cap = CSR_READ_2(sc, base + PCIR_EXPRESS_LINK_CAP);
|
||||
if ((cap & PCIM_LINK_CAP_ASPM) != 0) {
|
||||
@ -617,12 +829,19 @@ alc_attach(device_t dev)
|
||||
device_printf(dev, "RCB %u bytes\n",
|
||||
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
|
||||
state = ctl & 0x03;
|
||||
if (state & 0x01)
|
||||
sc->alc_flags |= ALC_FLAG_L0S;
|
||||
if (state & 0x02)
|
||||
sc->alc_flags |= ALC_FLAG_L1S;
|
||||
if (bootverbose)
|
||||
device_printf(sc->alc_dev, "ASPM %s %s\n",
|
||||
aspm_state[state],
|
||||
state == 0 ? "disabled" : "enabled");
|
||||
if (state != 0)
|
||||
alc_disable_l0s_l1(sc);
|
||||
} else {
|
||||
if (bootverbose)
|
||||
device_printf(sc->alc_dev,
|
||||
"no ASPM support\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -639,12 +858,25 @@ alc_attach(device_t dev)
|
||||
* used in AR8132 can't establish gigabit link even if it
|
||||
* shows the same PHY model/revision number of AR8131.
|
||||
*/
|
||||
if (pci_get_device(dev) == DEVICEID_ATHEROS_AR8132)
|
||||
sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_JUMBO;
|
||||
else
|
||||
sc->alc_flags |= ALC_FLAG_JUMBO | ALC_FLAG_ASPM_MON;
|
||||
switch (sc->alc_ident->deviceid) {
|
||||
case DEVICEID_ATHEROS_AR8152_B:
|
||||
case DEVICEID_ATHEROS_AR8152_B2:
|
||||
sc->alc_flags |= ALC_FLAG_APS;
|
||||
/* FALLTHROUGH */
|
||||
case DEVICEID_ATHEROS_AR8132:
|
||||
sc->alc_flags |= ALC_FLAG_FASTETHER;
|
||||
break;
|
||||
case DEVICEID_ATHEROS_AR8151:
|
||||
case DEVICEID_ATHEROS_AR8151_V2:
|
||||
sc->alc_flags |= ALC_FLAG_APS;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
|
||||
|
||||
/*
|
||||
* It seems that AR8131/AR8132 has silicon bug for SMB. In
|
||||
* It seems that AR813x/AR815x has silicon bug for SMB. In
|
||||
* addition, Atheros said that enabling SMB wouldn't improve
|
||||
* performance. However I think it's bad to access lots of
|
||||
* registers to extract MAC statistics.
|
||||
@ -732,22 +964,27 @@ alc_attach(device_t dev)
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_TSO4;
|
||||
ifp->if_hwassist = ALC_CSUM_FEATURES | CSUM_TSO;
|
||||
if (pci_find_extcap(dev, PCIY_PMG, &pmc) == 0)
|
||||
if (pci_find_extcap(dev, PCIY_PMG, &base) == 0) {
|
||||
ifp->if_capabilities |= IFCAP_WOL_MAGIC | IFCAP_WOL_MCAST;
|
||||
sc->alc_flags |= ALC_FLAG_PM;
|
||||
sc->alc_pmcap = base;
|
||||
}
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
|
||||
/* Set up MII bus. */
|
||||
if ((error = mii_phy_probe(dev, &sc->alc_miibus, alc_mediachange,
|
||||
alc_mediastatus)) != 0) {
|
||||
device_printf(dev, "no PHY found!\n");
|
||||
error = mii_attach(dev, &sc->alc_miibus, ifp, alc_mediachange,
|
||||
alc_mediastatus, BMSR_DEFCAPMASK, sc->alc_phyaddr, MII_OFFSET_ANY,
|
||||
MIIF_DOPAUSE);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "attaching PHYs failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ether_ifattach(ifp, sc->alc_eaddr);
|
||||
|
||||
/* VLAN capability setup. */
|
||||
ifp->if_capabilities |= IFCAP_VLAN_MTU;
|
||||
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM;
|
||||
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
|
||||
IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO;
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
/*
|
||||
* XXX
|
||||
@ -1354,7 +1591,7 @@ again:
|
||||
|
||||
/*
|
||||
* Create Tx buffer parent tag.
|
||||
* AR8131/AR8132 allows 64bit DMA addressing of Tx/Rx buffers
|
||||
* AR813x/AR815x allows 64bit DMA addressing of Tx/Rx buffers
|
||||
* so it needs separate parent DMA tag as parent DMA address
|
||||
* space could be restricted to be within 32bit address space
|
||||
* by 4GB boundary crossing.
|
||||
@ -1662,20 +1899,14 @@ static void
|
||||
alc_setwol(struct alc_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
uint32_t cap, reg, pmcs;
|
||||
uint32_t reg, pmcs;
|
||||
uint16_t pmstat;
|
||||
int base, pmc;
|
||||
|
||||
ALC_LOCK_ASSERT(sc);
|
||||
|
||||
if (pci_find_extcap(sc->alc_dev, PCIY_EXPRESS, &base) == 0) {
|
||||
cap = CSR_READ_2(sc, base + PCIR_EXPRESS_LINK_CAP);
|
||||
if ((cap & PCIM_LINK_CAP_ASPM) != 0) {
|
||||
cap = CSR_READ_2(sc, base + PCIR_EXPRESS_LINK_CTL);
|
||||
alc_disable_l0s_l1(sc);
|
||||
}
|
||||
}
|
||||
if (pci_find_extcap(sc->alc_dev, PCIY_PMG, &pmc) != 0) {
|
||||
ifp = sc->alc_ifp;
|
||||
if ((sc->alc_flags & ALC_FLAG_PM) == 0) {
|
||||
/* Disable WOL. */
|
||||
CSR_WRITE_4(sc, ALC_WOL_CFG, 0);
|
||||
reg = CSR_READ_4(sc, ALC_PCIE_PHYMISC);
|
||||
@ -1683,16 +1914,16 @@ alc_setwol(struct alc_softc *sc)
|
||||
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC, reg);
|
||||
/* Force PHY power down. */
|
||||
alc_phy_down(sc);
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG,
|
||||
CSR_READ_4(sc, ALC_MASTER_CFG) | MASTER_CLK_SEL_DIS);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp = sc->alc_ifp;
|
||||
if ((ifp->if_capenable & IFCAP_WOL) != 0) {
|
||||
if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0)
|
||||
alc_setlinkspeed(sc);
|
||||
reg = CSR_READ_4(sc, ALC_MASTER_CFG);
|
||||
reg &= ~MASTER_CLK_SEL_DIS;
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG,
|
||||
CSR_READ_4(sc, ALC_MASTER_CFG) & ~MASTER_CLK_SEL_DIS);
|
||||
}
|
||||
|
||||
pmcs = 0;
|
||||
@ -1714,13 +1945,17 @@ alc_setwol(struct alc_softc *sc)
|
||||
if ((ifp->if_capenable & IFCAP_WOL) == 0) {
|
||||
/* WOL disabled, PHY power down. */
|
||||
alc_phy_down(sc);
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG,
|
||||
CSR_READ_4(sc, ALC_MASTER_CFG) | MASTER_CLK_SEL_DIS);
|
||||
}
|
||||
/* Request PME. */
|
||||
pmstat = pci_read_config(sc->alc_dev, pmc + PCIR_POWER_STATUS, 2);
|
||||
pmstat = pci_read_config(sc->alc_dev,
|
||||
sc->alc_pmcap + PCIR_POWER_STATUS, 2);
|
||||
pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
|
||||
if ((ifp->if_capenable & IFCAP_WOL) != 0)
|
||||
pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
|
||||
pci_write_config(sc->alc_dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
|
||||
pci_write_config(sc->alc_dev,
|
||||
sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1743,20 +1978,19 @@ alc_resume(device_t dev)
|
||||
{
|
||||
struct alc_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int pmc;
|
||||
uint16_t pmstat;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
ALC_LOCK(sc);
|
||||
if (pci_find_extcap(sc->alc_dev, PCIY_PMG, &pmc) == 0) {
|
||||
if ((sc->alc_flags & ALC_FLAG_PM) != 0) {
|
||||
/* Disable PME and clear PME status. */
|
||||
pmstat = pci_read_config(sc->alc_dev,
|
||||
pmc + PCIR_POWER_STATUS, 2);
|
||||
sc->alc_pmcap + PCIR_POWER_STATUS, 2);
|
||||
if ((pmstat & PCIM_PSTAT_PMEENABLE) != 0) {
|
||||
pmstat &= ~PCIM_PSTAT_PMEENABLE;
|
||||
pci_write_config(sc->alc_dev,
|
||||
pmc + PCIR_POWER_STATUS, pmstat, 2);
|
||||
sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2);
|
||||
}
|
||||
}
|
||||
/* Reset PHY. */
|
||||
@ -1794,7 +2028,7 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
|
||||
ip_off = poff = 0;
|
||||
if ((m->m_pkthdr.csum_flags & (ALC_CSUM_FEATURES | CSUM_TSO)) != 0) {
|
||||
/*
|
||||
* AR8131/AR8132 requires offset of TCP/UDP header in its
|
||||
* AR813x/AR815x requires offset of TCP/UDP header in its
|
||||
* Tx descriptor to perform Tx checksum offloading. TSO
|
||||
* also requires TCP header offset and modification of
|
||||
* IP/TCP header. This kind of operation takes many CPU
|
||||
@ -1866,6 +2100,8 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
|
||||
* Reset IP checksum and recompute TCP pseudo
|
||||
* checksum as NDIS specification said.
|
||||
*/
|
||||
ip = (struct ip *)(mtod(m, char *) + ip_off);
|
||||
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
|
||||
ip->ip_sum = 0;
|
||||
tcp->th_sum = in_pseudo(ip->ip_src.s_addr,
|
||||
ip->ip_dst.s_addr, htons(IPPROTO_TCP));
|
||||
@ -1921,28 +2157,7 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
|
||||
vtag = (vtag << TD_VLAN_SHIFT) & TD_VLAN_MASK;
|
||||
cflags |= TD_INS_VLAN_TAG;
|
||||
}
|
||||
/* Configure Tx checksum offload. */
|
||||
if ((m->m_pkthdr.csum_flags & ALC_CSUM_FEATURES) != 0) {
|
||||
#ifdef ALC_USE_CUSTOM_CSUM
|
||||
cflags |= TD_CUSTOM_CSUM;
|
||||
/* Set checksum start offset. */
|
||||
cflags |= ((poff >> 1) << TD_PLOAD_OFFSET_SHIFT) &
|
||||
TD_PLOAD_OFFSET_MASK;
|
||||
/* Set checksum insertion position of TCP/UDP. */
|
||||
cflags |= (((poff + m->m_pkthdr.csum_data) >> 1) <<
|
||||
TD_CUSTOM_CSUM_OFFSET_SHIFT) & TD_CUSTOM_CSUM_OFFSET_MASK;
|
||||
#else
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
|
||||
cflags |= TD_IPCSUM;
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
|
||||
cflags |= TD_TCPCSUM;
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
|
||||
cflags |= TD_UDPCSUM;
|
||||
/* Set TCP/UDP header offset. */
|
||||
cflags |= (poff << TD_L4HDR_OFFSET_SHIFT) &
|
||||
TD_L4HDR_OFFSET_MASK;
|
||||
#endif
|
||||
} else if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
|
||||
/* Request TSO and set MSS. */
|
||||
cflags |= TD_TSO | TD_TSO_DESCV1;
|
||||
cflags |= ((uint32_t)m->m_pkthdr.tso_segsz << TD_MSS_SHIFT) &
|
||||
@ -1951,7 +2166,7 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
|
||||
cflags |= (poff << TD_TCPHDR_OFFSET_SHIFT) &
|
||||
TD_TCPHDR_OFFSET_MASK;
|
||||
/*
|
||||
* AR8131/AR8132 requires the first buffer should
|
||||
* AR813x/AR815x requires the first buffer should
|
||||
* only hold IP/TCP header data. Payload should
|
||||
* be handled in other descriptors.
|
||||
*/
|
||||
@ -1974,6 +2189,27 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
|
||||
}
|
||||
/* Handle remaining fragments. */
|
||||
idx = 1;
|
||||
} else if ((m->m_pkthdr.csum_flags & ALC_CSUM_FEATURES) != 0) {
|
||||
/* Configure Tx checksum offload. */
|
||||
#ifdef ALC_USE_CUSTOM_CSUM
|
||||
cflags |= TD_CUSTOM_CSUM;
|
||||
/* Set checksum start offset. */
|
||||
cflags |= ((poff >> 1) << TD_PLOAD_OFFSET_SHIFT) &
|
||||
TD_PLOAD_OFFSET_MASK;
|
||||
/* Set checksum insertion position of TCP/UDP. */
|
||||
cflags |= (((poff + m->m_pkthdr.csum_data) >> 1) <<
|
||||
TD_CUSTOM_CSUM_OFFSET_SHIFT) & TD_CUSTOM_CSUM_OFFSET_MASK;
|
||||
#else
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
|
||||
cflags |= TD_IPCSUM;
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
|
||||
cflags |= TD_TCPCSUM;
|
||||
if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
|
||||
cflags |= TD_UDPCSUM;
|
||||
/* Set TCP/UDP header offset. */
|
||||
cflags |= (poff << TD_L4HDR_OFFSET_SHIFT) &
|
||||
TD_L4HDR_OFFSET_MASK;
|
||||
#endif
|
||||
}
|
||||
for (; idx < nsegs; idx++) {
|
||||
desc = &sc->alc_rdata.alc_tx_ring[prod];
|
||||
@ -2111,18 +2347,21 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
error = 0;
|
||||
switch (cmd) {
|
||||
case SIOCSIFMTU:
|
||||
if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ALC_JUMBO_MTU ||
|
||||
if (ifr->ifr_mtu < ETHERMIN ||
|
||||
ifr->ifr_mtu > (sc->alc_ident->max_framelen -
|
||||
sizeof(struct ether_vlan_header) - ETHER_CRC_LEN) ||
|
||||
((sc->alc_flags & ALC_FLAG_JUMBO) == 0 &&
|
||||
ifr->ifr_mtu > ETHERMTU))
|
||||
error = EINVAL;
|
||||
else if (ifp->if_mtu != ifr->ifr_mtu) {
|
||||
ALC_LOCK(sc);
|
||||
ifp->if_mtu = ifr->ifr_mtu;
|
||||
/* AR8131/AR8132 has 13 bits MSS field. */
|
||||
/* AR813x/AR815x has 13 bits MSS field. */
|
||||
if (ifp->if_mtu > ALC_TSO_MTU &&
|
||||
(ifp->if_capenable & IFCAP_TSO4) != 0) {
|
||||
ifp->if_capenable &= ~IFCAP_TSO4;
|
||||
ifp->if_hwassist &= ~CSUM_TSO;
|
||||
VLAN_CAPABILITIES(ifp);
|
||||
}
|
||||
ALC_UNLOCK(sc);
|
||||
}
|
||||
@ -2168,7 +2407,7 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
(ifp->if_capabilities & IFCAP_TSO4) != 0) {
|
||||
ifp->if_capenable ^= IFCAP_TSO4;
|
||||
if ((ifp->if_capenable & IFCAP_TSO4) != 0) {
|
||||
/* AR8131/AR8132 has 13 bits MSS field. */
|
||||
/* AR813x/AR815x has 13 bits MSS field. */
|
||||
if (ifp->if_mtu > ALC_TSO_MTU) {
|
||||
ifp->if_capenable &= ~IFCAP_TSO4;
|
||||
ifp->if_hwassist &= ~CSUM_TSO;
|
||||
@ -2194,14 +2433,6 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
if ((mask & IFCAP_VLAN_HWTSO) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0)
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
|
||||
/*
|
||||
* VLAN hardware tagging is required to do checksum
|
||||
* offload or TSO on VLAN interface. Checksum offload
|
||||
* on VLAN interface also requires hardware checksum
|
||||
* offload of parent interface.
|
||||
*/
|
||||
if ((ifp->if_capenable & IFCAP_TXCSUM) == 0)
|
||||
ifp->if_capenable &= ~IFCAP_VLAN_HWCSUM;
|
||||
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
|
||||
ifp->if_capenable &=
|
||||
~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM);
|
||||
@ -2228,6 +2459,10 @@ alc_mac_config(struct alc_softc *sc)
|
||||
reg = CSR_READ_4(sc, ALC_MAC_CFG);
|
||||
reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC |
|
||||
MAC_CFG_SPEED_MASK);
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
|
||||
reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
|
||||
/* Reprogram MAC with resolved speed/duplex. */
|
||||
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
||||
case IFM_10_T:
|
||||
@ -2240,12 +2475,10 @@ alc_mac_config(struct alc_softc *sc)
|
||||
}
|
||||
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
|
||||
reg |= MAC_CFG_FULL_DUPLEX;
|
||||
#ifdef notyet
|
||||
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
|
||||
reg |= MAC_CFG_TX_FC;
|
||||
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
|
||||
reg |= MAC_CFG_RX_FC;
|
||||
#endif
|
||||
}
|
||||
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
|
||||
}
|
||||
@ -2729,8 +2962,8 @@ alc_rxeof(struct alc_softc *sc, struct rx_rdesc *rrd)
|
||||
* errored frames.
|
||||
*/
|
||||
status |= RRD_TCP_UDPCSUM_NOK | RRD_IPCSUM_NOK;
|
||||
if ((RRD_ERR_CRC | RRD_ERR_ALIGN | RRD_ERR_TRUNC |
|
||||
RRD_ERR_RUNT) != 0)
|
||||
if ((status & (RRD_ERR_CRC | RRD_ERR_ALIGN |
|
||||
RRD_ERR_TRUNC | RRD_ERR_RUNT)) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2849,7 +3082,9 @@ alc_reset(struct alc_softc *sc)
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG, MASTER_RESET);
|
||||
reg = CSR_READ_4(sc, ALC_MASTER_CFG) & 0xFFFF;
|
||||
reg |= MASTER_OOB_DIS_OFF | MASTER_RESET;
|
||||
CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
|
||||
for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
|
||||
DELAY(10);
|
||||
if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_RESET) == 0)
|
||||
@ -2980,6 +3215,18 @@ alc_init_locked(struct alc_softc *sc)
|
||||
CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_HI, ALC_ADDR_HI(paddr));
|
||||
CSR_WRITE_4(sc, ALC_SMB_BASE_ADDR_LO, ALC_ADDR_LO(paddr));
|
||||
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B) {
|
||||
/* Reconfigure SRAM - Vendor magic. */
|
||||
CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_LEN, 0x000002A0);
|
||||
CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_LEN, 0x00000100);
|
||||
CSR_WRITE_4(sc, ALC_SRAM_RX_FIFO_ADDR, 0x029F0000);
|
||||
CSR_WRITE_4(sc, ALC_SRAM_RD0_ADDR, 0x02BF02A0);
|
||||
CSR_WRITE_4(sc, ALC_SRAM_TX_FIFO_ADDR, 0x03BF02C0);
|
||||
CSR_WRITE_4(sc, ALC_SRAM_TD_ADDR, 0x03DF03C0);
|
||||
CSR_WRITE_4(sc, ALC_TXF_WATER_MARK, 0x00000000);
|
||||
CSR_WRITE_4(sc, ALC_RD_DMA_CFG, 0x00000000);
|
||||
}
|
||||
|
||||
/* Tell hardware that we're ready to load DMA blocks. */
|
||||
CSR_WRITE_4(sc, ALC_DMA_BLOCK, DMA_BLOCK_LOAD);
|
||||
|
||||
@ -2987,14 +3234,11 @@ alc_init_locked(struct alc_softc *sc)
|
||||
reg = ALC_USECS(sc->alc_int_rx_mod) << IM_TIMER_RX_SHIFT;
|
||||
reg |= ALC_USECS(sc->alc_int_tx_mod) << IM_TIMER_TX_SHIFT;
|
||||
CSR_WRITE_4(sc, ALC_IM_TIMER, reg);
|
||||
reg = CSR_READ_4(sc, ALC_MASTER_CFG);
|
||||
reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
|
||||
/*
|
||||
* We don't want to automatic interrupt clear as task queue
|
||||
* for the interrupt should know interrupt status.
|
||||
*/
|
||||
reg &= ~MASTER_INTR_RD_CLR;
|
||||
reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
|
||||
reg = MASTER_SA_TIMER_ENB;
|
||||
if (ALC_USECS(sc->alc_int_rx_mod) != 0)
|
||||
reg |= MASTER_IM_RX_TIMER_ENB;
|
||||
if (ALC_USECS(sc->alc_int_tx_mod) != 0)
|
||||
@ -3006,10 +3250,10 @@ alc_init_locked(struct alc_softc *sc)
|
||||
*/
|
||||
CSR_WRITE_4(sc, ALC_INTR_RETRIG_TIMER, ALC_USECS(0));
|
||||
/* Configure CMB. */
|
||||
if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
|
||||
CSR_WRITE_4(sc, ALC_CMB_TD_THRESH, 4);
|
||||
if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0)
|
||||
CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(5000));
|
||||
else
|
||||
} else
|
||||
CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(0));
|
||||
/*
|
||||
* Hardware can be configured to issue SMB interrupt based
|
||||
@ -3035,7 +3279,7 @@ alc_init_locked(struct alc_softc *sc)
|
||||
* Be conservative in what you do, be liberal in what you
|
||||
* accept from others - RFC 793.
|
||||
*/
|
||||
CSR_WRITE_4(sc, ALC_FRAME_SIZE, ALC_JUMBO_FRAMELEN);
|
||||
CSR_WRITE_4(sc, ALC_FRAME_SIZE, sc->alc_ident->max_framelen);
|
||||
|
||||
/* Disable header split(?) */
|
||||
CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
|
||||
@ -3062,11 +3306,14 @@ alc_init_locked(struct alc_softc *sc)
|
||||
* TSO/checksum offloading.
|
||||
*/
|
||||
CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH,
|
||||
(ALC_JUMBO_FRAMELEN >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
|
||||
(sc->alc_ident->max_framelen >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
|
||||
TSO_OFFLOAD_THRESH_MASK);
|
||||
/* Configure TxQ. */
|
||||
reg = (alc_dma_burst[sc->alc_dma_rd_burst] <<
|
||||
TXQ_CFG_TX_FIFO_BURST_SHIFT) & TXQ_CFG_TX_FIFO_BURST_MASK;
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
|
||||
reg >>= 1;
|
||||
reg |= (TXQ_CFG_TD_BURST_DEFAULT << TXQ_CFG_TD_BURST_SHIFT) &
|
||||
TXQ_CFG_TD_BURST_MASK;
|
||||
CSR_WRITE_4(sc, ALC_TXQ_CFG, reg | TXQ_CFG_ENHANCED_MODE);
|
||||
@ -3083,14 +3330,23 @@ alc_init_locked(struct alc_softc *sc)
|
||||
* XON : 80% of Rx FIFO
|
||||
* XOFF : 30% of Rx FIFO
|
||||
*/
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8131 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8132) {
|
||||
reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
|
||||
rxf_hi = (reg * 8) / 10;
|
||||
rxf_lo = (reg * 3)/ 10;
|
||||
rxf_lo = (reg * 3) / 10;
|
||||
CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
|
||||
((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
|
||||
RX_FIFO_PAUSE_THRESH_LO_MASK) |
|
||||
((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
|
||||
RX_FIFO_PAUSE_THRESH_HI_MASK));
|
||||
}
|
||||
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2)
|
||||
CSR_WRITE_4(sc, ALC_SERDES_LOCK,
|
||||
CSR_READ_4(sc, ALC_SERDES_LOCK) | SERDES_MAC_CLK_SLOWDOWN |
|
||||
SERDES_PHY_CLK_SLOWDOWN);
|
||||
|
||||
/* Disable RSS until I understand L1C/L2C's RSS logic. */
|
||||
CSR_WRITE_4(sc, ALC_RSS_IDT_TABLE0, 0);
|
||||
@ -3101,15 +3357,9 @@ alc_init_locked(struct alc_softc *sc)
|
||||
RXQ_CFG_RD_BURST_MASK;
|
||||
reg |= RXQ_CFG_RSS_MODE_DIS;
|
||||
if ((sc->alc_flags & ALC_FLAG_ASPM_MON) != 0)
|
||||
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_100M;
|
||||
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
|
||||
CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
|
||||
|
||||
/* Configure Rx DMAW request thresold. */
|
||||
CSR_WRITE_4(sc, ALC_RD_DMA_CFG,
|
||||
((RD_DMA_CFG_THRESH_DEFAULT << RD_DMA_CFG_THRESH_SHIFT) &
|
||||
RD_DMA_CFG_THRESH_MASK) |
|
||||
((ALC_RD_DMA_CFG_USECS(0) << RD_DMA_CFG_TIMER_SHIFT) &
|
||||
RD_DMA_CFG_TIMER_MASK));
|
||||
/* Configure DMA parameters. */
|
||||
reg = DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI;
|
||||
reg |= sc->alc_rcb;
|
||||
@ -3135,7 +3385,7 @@ alc_init_locked(struct alc_softc *sc)
|
||||
* - Enable CRC generation.
|
||||
* Actual reconfiguration of MAC for resolved speed/duplex
|
||||
* is followed after detection of link establishment.
|
||||
* AR8131/AR8132 always does checksum computation regardless
|
||||
* AR813x/AR815x always does checksum computation regardless
|
||||
* of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
|
||||
* have bug in protocol field in Rx return structure so
|
||||
* these controllers can't handle fragmented frames. Disable
|
||||
@ -3145,6 +3395,10 @@ alc_init_locked(struct alc_softc *sc)
|
||||
reg = MAC_CFG_TX_CRC_ENB | MAC_CFG_TX_AUTO_PAD | MAC_CFG_FULL_DUPLEX |
|
||||
((MAC_CFG_PREAMBLE_DEFAULT << MAC_CFG_PREAMBLE_SHIFT) &
|
||||
MAC_CFG_PREAMBLE_MASK);
|
||||
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
|
||||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
|
||||
reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
|
||||
if ((sc->alc_flags & ALC_FLAG_FASTETHER) != 0)
|
||||
reg |= MAC_CFG_SPEED_10_100;
|
||||
else
|
||||
@ -3246,7 +3500,7 @@ alc_stop_mac(struct alc_softc *sc)
|
||||
/* Disable Rx/Tx MAC. */
|
||||
reg = CSR_READ_4(sc, ALC_MAC_CFG);
|
||||
if ((reg & (MAC_CFG_TX_ENB | MAC_CFG_RX_ENB)) != 0) {
|
||||
reg &= ~MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
|
||||
reg &= ~(MAC_CFG_TX_ENB | MAC_CFG_RX_ENB);
|
||||
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
|
||||
}
|
||||
for (i = ALC_TIMEOUT; i > 0; i--) {
|
||||
@ -3466,7 +3720,7 @@ alc_rxfilter(struct alc_softc *sc)
|
||||
TAILQ_FOREACH(ifma, &sc->alc_ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
|
||||
crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
||||
ifma->ifma_addr), ETHER_ADDR_LEN);
|
||||
mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
|
||||
}
|
||||
|
@ -36,10 +36,17 @@
|
||||
#define VENDORID_ATHEROS 0x1969
|
||||
|
||||
/*
|
||||
* Atheros AR8131/AR8132 device ID
|
||||
* Atheros AR813x/AR815x device ID
|
||||
*/
|
||||
#define DEVICEID_ATHEROS_AR8131 0x1063 /* L1C */
|
||||
#define DEVICEID_ATHEROS_AR8132 0x1062 /* L2C */
|
||||
#define DEVICEID_ATHEROS_AR8151 0x1073 /* L1D V1.0 */
|
||||
#define DEVICEID_ATHEROS_AR8151_V2 0x1083 /* L1D V2.0 */
|
||||
#define DEVICEID_ATHEROS_AR8152_B 0x2060 /* L2C V1.1 */
|
||||
#define DEVICEID_ATHEROS_AR8152_B2 0x2062 /* L2C V2.0 */
|
||||
|
||||
#define ATHEROS_AR8152_B_V10 0xC0
|
||||
#define ATHEROS_AR8152_B_V11 0xC1
|
||||
|
||||
/* 0x0000 - 0x02FF : PCIe configuration space */
|
||||
|
||||
@ -64,6 +71,12 @@
|
||||
#define ALC_PCIE_PHYMISC 0x1000
|
||||
#define PCIE_PHYMISC_FORCE_RCV_DET 0x00000004
|
||||
|
||||
#define ALC_PCIE_PHYMISC2 0x1004
|
||||
#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x00030000
|
||||
#define PCIE_PHYMISC2_SERDES_TH_MASK 0x000C0000
|
||||
#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
|
||||
#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
|
||||
|
||||
#define ALC_TWSI_DEBUG 0x1108
|
||||
#define TWSI_DEBUG_DEV_EXIST 0x20000000
|
||||
|
||||
@ -97,6 +110,8 @@
|
||||
#define PM_CFG_L1_ENTRY_TIMER_MASK 0x000F0000
|
||||
#define PM_CFG_PM_REQ_TIMER_MASK 0x00F00000
|
||||
#define PM_CFG_LCKDET_TIMER_MASK 0x3F000000
|
||||
#define PM_CFG_EN_BUFS_RX_L0S 0x10000000
|
||||
#define PM_CFG_SA_DLY_ENB 0x20000000
|
||||
#define PM_CFG_MAC_ASPM_CHK 0x40000000
|
||||
#define PM_CFG_HOTRST 0x80000000
|
||||
#define PM_CFG_L0S_ENTRY_TIMER_SHIFT 8
|
||||
@ -104,10 +119,19 @@
|
||||
#define PM_CFG_PM_REQ_TIMER_SHIFT 20
|
||||
#define PM_CFG_LCKDET_TIMER_SHIFT 24
|
||||
|
||||
#define PM_CFG_L0S_ENTRY_TIMER_DEFAULT 6
|
||||
#define PM_CFG_L1_ENTRY_TIMER_DEFAULT 12
|
||||
#define PM_CFG_PM_REQ_TIMER_DEFAULT 1
|
||||
|
||||
#define ALC_LTSSM_ID_CFG 0x12FC
|
||||
#define LTSSM_ID_WRO_ENB 0x00001000
|
||||
|
||||
#define ALC_MASTER_CFG 0x1400
|
||||
#define MASTER_RESET 0x00000001
|
||||
#define MASTER_TEST_MODE_MASK 0x0000000C
|
||||
#define MASTER_BERT_START 0x00000010
|
||||
#define MASTER_TEST_MODE_MASK 0x000000C0
|
||||
#define MASTER_OOB_DIS_OFF 0x00000040
|
||||
#define MASTER_SA_TIMER_ENB 0x00000080
|
||||
#define MASTER_MTIMER_ENB 0x00000100
|
||||
#define MASTER_MANUAL_INTR_ENB 0x00000200
|
||||
#define MASTER_IM_TX_TIMER_ENB 0x00000400
|
||||
@ -122,7 +146,7 @@
|
||||
#define MASTER_CHIP_REV_SHIFT 16
|
||||
#define MASTER_CHIP_ID_SHIFT 24
|
||||
|
||||
/* Number of ticks per usec for AR8131/AR8132. */
|
||||
/* Number of ticks per usec for AR813x/AR815x. */
|
||||
#define ALC_TICK_USECS 2
|
||||
#define ALC_USECS(x) ((x) / ALC_TICK_USECS)
|
||||
|
||||
@ -144,7 +168,7 @@
|
||||
* alc(4) does not rely on Tx completion interrupts, so set it
|
||||
* somewhat large value to reduce Tx completion interrupts.
|
||||
*/
|
||||
#define ALC_IM_TX_TIMER_DEFAULT 50000 /* 50ms */
|
||||
#define ALC_IM_TX_TIMER_DEFAULT 1000 /* 1ms */
|
||||
|
||||
#define ALC_GPHY_CFG 0x140C /* 16bits */
|
||||
#define GPHY_CFG_EXT_RESET 0x0001
|
||||
@ -220,6 +244,8 @@
|
||||
#define ALC_SERDES_LOCK 0x1424
|
||||
#define SERDES_LOCK_DET 0x00000001
|
||||
#define SERDES_LOCK_DET_ENB 0x00000002
|
||||
#define SERDES_MAC_CLK_SLOWDOWN 0x00020000
|
||||
#define SERDES_PHY_CLK_SLOWDOWN 0x00040000
|
||||
|
||||
#define ALC_MAC_CFG 0x1480
|
||||
#define MAC_CFG_TX_ENB 0x00000001
|
||||
@ -249,6 +275,8 @@
|
||||
#define MAC_CFG_BCAST 0x04000000
|
||||
#define MAC_CFG_DBG 0x08000000
|
||||
#define MAC_CFG_SINGLE_PAUSE_ENB 0x10000000
|
||||
#define MAC_CFG_HASH_ALG_CRC32 0x20000000
|
||||
#define MAC_CFG_SPEED_MODE_SW 0x40000000
|
||||
#define MAC_CFG_PREAMBLE_SHIFT 10
|
||||
#define MAC_CFG_PREAMBLE_DEFAULT 7
|
||||
|
||||
@ -691,7 +719,7 @@
|
||||
#define HDS_CFG_BACKFILLSIZE_SHIFT 8
|
||||
#define HDS_CFG_MAX_HDRSIZE_SHIFT 20
|
||||
|
||||
/* AR8131/AR8132 registers for MAC statistics */
|
||||
/* AR813x/AR815x registers for MAC statistics */
|
||||
#define ALC_RX_MIB_BASE 0x1700
|
||||
|
||||
#define ALC_TX_MIB_BASE 0x1760
|
||||
|
@ -68,13 +68,8 @@
|
||||
#define ALC_PROC_MAX (ALC_RX_RING_CNT - 1)
|
||||
#define ALC_PROC_DEFAULT (ALC_RX_RING_CNT / 4)
|
||||
|
||||
#define ALC_JUMBO_FRAMELEN (9 * 1024)
|
||||
#define ALC_JUMBO_MTU \
|
||||
(ALC_JUMBO_FRAMELEN - sizeof(struct ether_vlan_header) - ETHER_CRC_LEN)
|
||||
#define ALC_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
|
||||
|
||||
/*
|
||||
* The number of bits reserved for MSS in AR8121/AR8132 controllers
|
||||
* The number of bits reserved for MSS in AR813x/AR815x controllers
|
||||
* are 13 bits. This limits the maximum interface MTU size in TSO
|
||||
* case(8191 + sizeof(struct ip) + sizeof(struct tcphdr)) as upper
|
||||
* stack should not generate TCP segments with MSS greater than the
|
||||
@ -192,6 +187,13 @@ struct alc_hw_stats {
|
||||
uint64_t tx_mcast_bytes;
|
||||
};
|
||||
|
||||
struct alc_ident {
|
||||
uint16_t vendorid;
|
||||
uint16_t deviceid;
|
||||
uint32_t max_framelen;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/*
|
||||
* Software state per device.
|
||||
*/
|
||||
@ -204,6 +206,7 @@ struct alc_softc {
|
||||
struct resource *alc_irq[ALC_MSI_MESSAGES];
|
||||
struct resource_spec *alc_irq_spec;
|
||||
void *alc_intrhand[ALC_MSI_MESSAGES];
|
||||
struct alc_ident *alc_ident;
|
||||
int alc_rev;
|
||||
int alc_chip_rev;
|
||||
int alc_phyaddr;
|
||||
@ -211,16 +214,22 @@ struct alc_softc {
|
||||
uint32_t alc_dma_rd_burst;
|
||||
uint32_t alc_dma_wr_burst;
|
||||
uint32_t alc_rcb;
|
||||
int alc_expcap;
|
||||
int alc_pmcap;
|
||||
int alc_flags;
|
||||
#define ALC_FLAG_PCIE 0x0001
|
||||
#define ALC_FLAG_PCIX 0x0002
|
||||
#define ALC_FLAG_MSI 0x0004
|
||||
#define ALC_FLAG_MSIX 0x0008
|
||||
#define ALC_FLAG_PM 0x0010
|
||||
#define ALC_FLAG_FASTETHER 0x0020
|
||||
#define ALC_FLAG_JUMBO 0x0040
|
||||
#define ALC_FLAG_ASPM_MON 0x0080
|
||||
#define ALC_FLAG_CMB_BUG 0x0100
|
||||
#define ALC_FLAG_SMB_BUG 0x0200
|
||||
#define ALC_FLAG_L0S 0x0400
|
||||
#define ALC_FLAG_L1S 0x0800
|
||||
#define ALC_FLAG_APS 0x1000
|
||||
#define ALC_FLAG_DETACH 0x4000
|
||||
#define ALC_FLAG_LINK 0x8000
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/ae/if_ae.c,v 1.1.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $");
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -105,7 +105,7 @@ static void ae_phy_init(ae_softc_t *sc);
|
||||
static int ae_reset(ae_softc_t *sc);
|
||||
static void ae_init(void *arg);
|
||||
static int ae_init_locked(ae_softc_t *sc);
|
||||
static unsigned int ae_detach(device_t dev);
|
||||
static int ae_detach(device_t dev);
|
||||
static int ae_miibus_readreg(device_t dev, int phy, int reg);
|
||||
static int ae_miibus_writereg(device_t dev, int phy, int reg, int val);
|
||||
static void ae_miibus_statchg(device_t dev);
|
||||
@ -360,13 +360,11 @@ ae_attach(device_t dev)
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
|
||||
/* Set default PHY address. */
|
||||
sc->phyaddr = AE_PHYADDR_DEFAULT;
|
||||
|
||||
ifp = sc->ifp = if_alloc(IFT_ETHER);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "could not allocate ifnet structure.\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ifp->if_softc = sc;
|
||||
@ -377,20 +375,23 @@ ae_attach(device_t dev)
|
||||
ifp->if_init = ae_init;
|
||||
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
|
||||
ifp->if_hwassist = 0;
|
||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
if (pci_find_extcap(dev, PCIY_PMG, &pmc) == 0)
|
||||
if (pci_find_extcap(dev, PCIY_PMG, &pmc) == 0) {
|
||||
ifp->if_capabilities |= IFCAP_WOL_MAGIC;
|
||||
sc->flags |= AE_FLAG_PMG;
|
||||
}
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
|
||||
/*
|
||||
* Configure and attach MII bus.
|
||||
*/
|
||||
error = mii_phy_probe(dev, &sc->miibus, ae_mediachange,
|
||||
ae_mediastatus);
|
||||
error = mii_attach(dev, &sc->miibus, ifp, ae_mediachange,
|
||||
ae_mediastatus, BMSR_DEFCAPMASK, AE_PHYADDR_DEFAULT,
|
||||
MII_OFFSET_ANY, 0);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "no PHY found.\n");
|
||||
device_printf(dev, "attaching PHYs failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -562,6 +563,8 @@ ae_init_locked(ae_softc_t *sc)
|
||||
AE_LOCK_ASSERT(sc);
|
||||
|
||||
ifp = sc->ifp;
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
|
||||
return (0);
|
||||
mii = device_get_softc(sc->miibus);
|
||||
|
||||
ae_stop(sc);
|
||||
@ -744,7 +747,7 @@ ae_init_locked(ae_softc_t *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
static int
|
||||
ae_detach(device_t dev)
|
||||
{
|
||||
struct ae_softc *sc;
|
||||
@ -808,9 +811,6 @@ ae_miibus_readreg(device_t dev, int phy, int reg)
|
||||
* Locking is done in upper layers.
|
||||
*/
|
||||
|
||||
if (phy != sc->phyaddr)
|
||||
return (0);
|
||||
|
||||
val = ((reg << AE_MDIO_REGADDR_SHIFT) & AE_MDIO_REGADDR_MASK) |
|
||||
AE_MDIO_START | AE_MDIO_READ | AE_MDIO_SUP_PREAMBLE |
|
||||
((AE_MDIO_CLK_25_4 << AE_MDIO_CLK_SHIFT) & AE_MDIO_CLK_MASK);
|
||||
@ -846,9 +846,6 @@ ae_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
* Locking is done in upper layers.
|
||||
*/
|
||||
|
||||
if (phy != sc->phyaddr)
|
||||
return (0);
|
||||
|
||||
aereg = ((reg << AE_MDIO_REGADDR_SHIFT) & AE_MDIO_REGADDR_MASK) |
|
||||
AE_MDIO_START | AE_MDIO_SUP_PREAMBLE |
|
||||
((AE_MDIO_CLK_25_4 << AE_MDIO_CLK_SHIFT) & AE_MDIO_CLK_MASK) |
|
||||
@ -1045,7 +1042,7 @@ ae_get_reg_eaddr(ae_softc_t *sc, uint32_t *eaddr)
|
||||
if (AE_CHECK_EADDR_VALID(eaddr) != 0) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev,
|
||||
"Ethetnet address registers are invalid.\n");
|
||||
"Ethernet address registers are invalid.\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
@ -1107,12 +1104,9 @@ ae_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
static int
|
||||
ae_alloc_rings(ae_softc_t *sc)
|
||||
{
|
||||
bus_dma_tag_t bustag;
|
||||
bus_addr_t busaddr;
|
||||
int error;
|
||||
|
||||
bustag = bus_get_dma_tag(sc->dev);
|
||||
|
||||
/*
|
||||
* Create parent DMA tag.
|
||||
*/
|
||||
@ -1336,6 +1330,7 @@ ae_pm_init(ae_softc_t *sc)
|
||||
struct ifnet *ifp;
|
||||
uint32_t val;
|
||||
uint16_t pmstat;
|
||||
struct mii_data *mii;
|
||||
int pmc;
|
||||
|
||||
AE_LOCK_ASSERT(sc);
|
||||
@ -1347,7 +1342,40 @@ ae_pm_init(ae_softc_t *sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure WOL if enabled.
|
||||
*/
|
||||
if ((ifp->if_capenable & IFCAP_WOL) != 0) {
|
||||
mii = device_get_softc(sc->miibus);
|
||||
mii_pollstat(mii);
|
||||
if ((mii->mii_media_status & IFM_AVALID) != 0 &&
|
||||
(mii->mii_media_status & IFM_ACTIVE) != 0) {
|
||||
AE_WRITE_4(sc, AE_WOL_REG, AE_WOL_MAGIC | \
|
||||
AE_WOL_MAGIC_PME);
|
||||
|
||||
/*
|
||||
* Configure MAC.
|
||||
*/
|
||||
val = AE_MAC_RX_EN | AE_MAC_CLK_PHY | \
|
||||
AE_MAC_TX_CRC_EN | AE_MAC_TX_AUTOPAD | \
|
||||
((AE_HALFBUF_DEFAULT << AE_HALFBUF_SHIFT) & \
|
||||
AE_HALFBUF_MASK) | \
|
||||
((AE_MAC_PREAMBLE_DEFAULT << \
|
||||
AE_MAC_PREAMBLE_SHIFT) & AE_MAC_PREAMBLE_MASK) | \
|
||||
AE_MAC_BCAST_EN | AE_MAC_MCAST_EN;
|
||||
if ((IFM_OPTIONS(mii->mii_media_active) & \
|
||||
IFM_FDX) != 0)
|
||||
val |= AE_MAC_FULL_DUPLEX;
|
||||
AE_WRITE_4(sc, AE_MAC_REG, val);
|
||||
|
||||
} else { /* No link. */
|
||||
AE_WRITE_4(sc, AE_WOL_REG, AE_WOL_LNKCHG | \
|
||||
AE_WOL_LNKCHG_PME);
|
||||
AE_WRITE_4(sc, AE_MAC_REG, 0);
|
||||
}
|
||||
} else {
|
||||
ae_powersave_enable(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* PCIE hacks. Magic numbers.
|
||||
@ -1365,6 +1393,8 @@ ae_pm_init(ae_softc_t *sc)
|
||||
pci_find_extcap(sc->dev, PCIY_PMG, &pmc);
|
||||
pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2);
|
||||
pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
|
||||
if ((ifp->if_capenable & IFCAP_WOL) != 0)
|
||||
pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
|
||||
pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
|
||||
}
|
||||
|
||||
@ -1754,7 +1784,10 @@ ae_int_task(void *arg, int pending)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
|
||||
if ((val & (AE_ISR_DMAR_TIMEOUT | AE_ISR_DMAW_TIMEOUT |
|
||||
AE_ISR_PHY_LINKDOWN)) != 0) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
ae_init_locked(sc);
|
||||
AE_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if ((val & AE_ISR_TX_EVENT) != 0)
|
||||
ae_tx_intr(sc);
|
||||
@ -1869,8 +1902,8 @@ ae_rxeof(ae_softc_t *sc, ae_rxd_t *rxd)
|
||||
if_printf(ifp, "Rx interrupt occuried.\n");
|
||||
#endif
|
||||
size = le16toh(rxd->len) - ETHER_CRC_LEN;
|
||||
if (size < 0) {
|
||||
if_printf(ifp, "Negative length packet received.");
|
||||
if (size < (ETHER_MIN_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)) {
|
||||
if_printf(ifp, "Runt frame received.");
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
@ -1965,6 +1998,7 @@ ae_watchdog(ae_softc_t *sc)
|
||||
if_printf(ifp, "watchdog timeout - resetting.\n");
|
||||
|
||||
ifp->if_oerrors++;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
ae_init_locked(sc);
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
taskqueue_enqueue(sc->tq, &sc->tx_task);
|
||||
@ -2042,15 +2076,15 @@ ae_rxfilter(ae_softc_t *sc)
|
||||
* Load multicast tables.
|
||||
*/
|
||||
bzero(mchash, sizeof(mchash));
|
||||
IF_ADDR_LOCK(ifp);
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
|
||||
crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
||||
ifma->ifma_addr), ETHER_ADDR_LEN);
|
||||
mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
if_maddr_runlock(ifp);
|
||||
AE_WRITE_4(sc, AE_REG_MHT0, mchash[0]);
|
||||
AE_WRITE_4(sc, AE_REG_MHT1, mchash[1]);
|
||||
AE_WRITE_4(sc, AE_MAC_REG, rxcfg);
|
||||
@ -2075,8 +2109,10 @@ ae_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
else if (ifp->if_mtu != ifr->ifr_mtu) {
|
||||
AE_LOCK(sc);
|
||||
ifp->if_mtu = ifr->ifr_mtu;
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
ae_init_locked(sc);
|
||||
}
|
||||
AE_UNLOCK(sc);
|
||||
}
|
||||
break;
|
||||
|
@ -22,7 +22,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/dev/ae/if_aereg.h,v 1.1.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -22,7 +22,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/dev/ae/if_aevar.h,v 1.1.2.1.2.1 2008/11/25 02:59:29 kensmith Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef IF_AEVAR_H
|
||||
@ -111,7 +111,6 @@ typedef struct ae_softc {
|
||||
|
||||
struct mtx mtx;
|
||||
|
||||
int phyaddr;
|
||||
uint8_t eaddr[ETHER_ADDR_LEN];
|
||||
uint8_t flags;
|
||||
int if_flags;
|
||||
|
Loading…
Reference in New Issue
Block a user