Update to actual AGE driver version. (Tested on real hardware - work fine)
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33158 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
#include <sys/bus.h>
|
#include <sys/bus.h>
|
||||||
|
|
||||||
|
|
||||||
HAIKU_FBSD_DRIVER_GLUE(attansic_l1, age, pci);
|
HAIKU_FBSD_DRIVER_GLUE(atl1, age, pci);
|
||||||
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_SWI_TASKQUEUE);
|
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_SWI_TASKQUEUE);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
/* Driver for Attansic Technology Corp. L1 Gigabit Ethernet. */
|
/* Driver for Attansic Technology Corp. L1 Gigabit Ethernet. */
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: src/sys/dev/age/if_age.c,v 1.6 2008/11/07 07:02:28 yongari Exp $");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
@@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
#include <machine/in_cksum.h>
|
#include <machine/in_cksum.h>
|
||||||
#include <machine/resource.h>
|
|
||||||
|
|
||||||
#include "if_agereg.h"
|
#include "if_agereg.h"
|
||||||
#include "if_agevar.h"
|
#include "if_agevar.h"
|
||||||
@@ -93,6 +92,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
|
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define AGE_CSUM_FEATURES (CSUM_TCP | CSUM_UDP)
|
||||||
|
|
||||||
MODULE_DEPEND(age, pci, 1, 1, 1);
|
MODULE_DEPEND(age, pci, 1, 1, 1);
|
||||||
MODULE_DEPEND(age, ether, 1, 1, 1);
|
MODULE_DEPEND(age, ether, 1, 1, 1);
|
||||||
MODULE_DEPEND(age, miibus, 1, 1, 1);
|
MODULE_DEPEND(age, miibus, 1, 1, 1);
|
||||||
@@ -120,8 +121,6 @@ static int age_miibus_writereg(device_t, int, int, int);
|
|||||||
static void age_miibus_statchg(device_t);
|
static void age_miibus_statchg(device_t);
|
||||||
static void age_mediastatus(struct ifnet *, struct ifmediareq *);
|
static void age_mediastatus(struct ifnet *, struct ifmediareq *);
|
||||||
static int age_mediachange(struct ifnet *);
|
static int age_mediachange(struct ifnet *);
|
||||||
static int age_read_vpd_word(struct age_softc *, uint32_t, uint32_t,
|
|
||||||
uint32_t *);
|
|
||||||
static int age_probe(device_t);
|
static int age_probe(device_t);
|
||||||
static void age_get_macaddr(struct age_softc *);
|
static void age_get_macaddr(struct age_softc *);
|
||||||
static void age_phy_reset(struct age_softc *);
|
static void age_phy_reset(struct age_softc *);
|
||||||
@@ -334,29 +333,6 @@ age_mediachange(struct ifnet *ifp)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
age_read_vpd_word(struct age_softc *sc, uint32_t vpdc, uint32_t offset,
|
|
||||||
uint32_t *word)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pci_write_config(sc->age_dev, vpdc + PCIR_VPD_ADDR, offset, 2);
|
|
||||||
for (i = AGE_TIMEOUT; i > 0; i--) {
|
|
||||||
DELAY(10);
|
|
||||||
if ((pci_read_config(sc->age_dev, vpdc + PCIR_VPD_ADDR, 2) &
|
|
||||||
0x8000) == 0x8000)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 0) {
|
|
||||||
device_printf(sc->age_dev, "VPD read timeout!\n");
|
|
||||||
*word = 0;
|
|
||||||
return (ETIMEDOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
*word = pci_read_config(sc->age_dev, vpdc + PCIR_VPD_DATA, 4);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
age_probe(device_t dev)
|
age_probe(device_t dev)
|
||||||
{
|
{
|
||||||
@@ -382,8 +358,8 @@ age_probe(device_t dev)
|
|||||||
static void
|
static void
|
||||||
age_get_macaddr(struct age_softc *sc)
|
age_get_macaddr(struct age_softc *sc)
|
||||||
{
|
{
|
||||||
uint32_t ea[2], off, reg, word;
|
uint32_t ea[2], reg;
|
||||||
int vpd_error, match, vpdc;
|
int i, vpdc;
|
||||||
|
|
||||||
reg = CSR_READ_4(sc, AGE_SPI_CTRL);
|
reg = CSR_READ_4(sc, AGE_SPI_CTRL);
|
||||||
if ((reg & SPI_VPD_ENB) != 0) {
|
if ((reg & SPI_VPD_ENB) != 0) {
|
||||||
@@ -392,130 +368,120 @@ age_get_macaddr(struct age_softc *sc)
|
|||||||
CSR_WRITE_4(sc, AGE_SPI_CTRL, reg);
|
CSR_WRITE_4(sc, AGE_SPI_CTRL, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
vpd_error = 0;
|
if (pci_find_extcap(sc->age_dev, PCIY_VPD, &vpdc) == 0) {
|
||||||
ea[0] = ea[1] = 0;
|
|
||||||
if ((vpd_error = pci_find_extcap(sc->age_dev, PCIY_VPD, &vpdc)) == 0) {
|
|
||||||
/*
|
/*
|
||||||
* PCI VPD capability exists, but it seems that it's
|
* PCI VPD capability found, let TWSI reload EEPROM.
|
||||||
* not in the standard form as stated in PCI VPD
|
* This will set ethernet address of controller.
|
||||||
* specification such that driver could not use
|
|
||||||
* pci_get_vpd_readonly(9) with keyword 'NA'.
|
|
||||||
* Search VPD data starting at address 0x0100. The data
|
|
||||||
* chwould be used as initializers to set AGE_PAR0,
|
|
||||||
* AGE_PAR1 register including other PCI configuration
|
|
||||||
* registers.
|
|
||||||
*/
|
*/
|
||||||
word = 0;
|
CSR_WRITE_4(sc, AGE_TWSI_CTRL, CSR_READ_4(sc, AGE_TWSI_CTRL) |
|
||||||
match = 0;
|
TWSI_CTRL_SW_LD_START);
|
||||||
reg = 0;
|
for (i = 100; i > 0; i--) {
|
||||||
for (off = AGE_VPD_REG_CONF_START; off < AGE_VPD_REG_CONF_END;
|
DELAY(1000);
|
||||||
off += sizeof(uint32_t)) {
|
reg = CSR_READ_4(sc, AGE_TWSI_CTRL);
|
||||||
vpd_error = age_read_vpd_word(sc, vpdc, off, &word);
|
if ((reg & TWSI_CTRL_SW_LD_START) == 0)
|
||||||
if (vpd_error != 0)
|
|
||||||
break;
|
|
||||||
if (match != 0) {
|
|
||||||
switch (reg) {
|
|
||||||
case AGE_PAR0:
|
|
||||||
ea[0] = word;
|
|
||||||
break;
|
|
||||||
case AGE_PAR1:
|
|
||||||
ea[1] = word;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
match = 0;
|
|
||||||
} else if ((word & 0xFF) == AGE_VPD_REG_CONF_SIG) {
|
|
||||||
match = 1;
|
|
||||||
reg = word >> 16;
|
|
||||||
} else
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (off >= AGE_VPD_REG_CONF_END)
|
if (i == 0)
|
||||||
vpd_error = ENOENT;
|
device_printf(sc->age_dev,
|
||||||
if (vpd_error == 0) {
|
"reloading EEPROM timeout!\n");
|
||||||
/*
|
|
||||||
* Don't blindly trust ethernet address obtained
|
|
||||||
* from VPD. Check whether ethernet address is
|
|
||||||
* valid one. Otherwise fall-back to reading
|
|
||||||
* PAR register.
|
|
||||||
*/
|
|
||||||
ea[1] &= 0xFFFF;
|
|
||||||
if ((ea[0] == 0 && ea[1] == 0) ||
|
|
||||||
(ea[0] == 0xFFFFFFFF && ea[1] == 0xFFFF)) {
|
|
||||||
if (1 || bootverbose)
|
|
||||||
device_printf(sc->age_dev,
|
|
||||||
"invalid ethernet address "
|
|
||||||
"returned from VPD.\n");
|
|
||||||
vpd_error = EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vpd_error != 0 && (1 || bootverbose))
|
|
||||||
device_printf(sc->age_dev, "VPD access failure!\n");
|
|
||||||
} else {
|
} else {
|
||||||
if (1 || bootverbose)
|
if (bootverbose)
|
||||||
device_printf(sc->age_dev,
|
device_printf(sc->age_dev,
|
||||||
"PCI VPD capability not found!\n");
|
"PCI VPD capability not found!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
ea[0] = CSR_READ_4(sc, AGE_PAR0);
|
||||||
* It seems that L1 also provides a way to extract ethernet
|
ea[1] = CSR_READ_4(sc, AGE_PAR1);
|
||||||
* address via SPI flash interface. Because SPI flash memory
|
sc->age_eaddr[0] = (ea[1] >> 8) & 0xFF;
|
||||||
* device of different vendors vary in their instruction
|
sc->age_eaddr[1] = (ea[1] >> 0) & 0xFF;
|
||||||
* codes for read ID instruction, it's very hard to get
|
sc->age_eaddr[2] = (ea[0] >> 24) & 0xFF;
|
||||||
* instructions codes without detailed information for the
|
sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
|
||||||
* flash memory device used on ethernet controller. To simplify
|
sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
|
||||||
* code, just read AGE_PAR0/AGE_PAR1 register to get ethernet
|
sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
|
||||||
* address which is supposed to be set by hardware during
|
|
||||||
* power on reset.
|
|
||||||
*/
|
|
||||||
if (vpd_error != 0) {
|
|
||||||
/*
|
|
||||||
* VPD is mapped to SPI flash memory or BIOS set it.
|
|
||||||
*/
|
|
||||||
ea[0] = CSR_READ_4(sc, AGE_PAR0);
|
|
||||||
ea[1] = CSR_READ_4(sc, AGE_PAR1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ea[1] &= 0xFFFF;
|
|
||||||
if ((ea[0] == 0 && ea[1] == 0) ||
|
|
||||||
(ea[0] == 0xFFFFFFFF && ea[1] == 0xFFFF)) {
|
|
||||||
device_printf(sc->age_dev,
|
|
||||||
"generating fake ethernet address.\n");
|
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
ea[0] = random();
|
|
||||||
#else
|
|
||||||
ea[0] = arc4random();
|
|
||||||
#endif
|
|
||||||
/* Set OUI to ASUSTek COMPUTER INC. */
|
|
||||||
sc->age_eaddr[0] = 0x00;
|
|
||||||
sc->age_eaddr[1] = 0x1B;
|
|
||||||
sc->age_eaddr[2] = 0xFC;
|
|
||||||
sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
|
|
||||||
sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
|
|
||||||
sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
|
|
||||||
} else {
|
|
||||||
sc->age_eaddr[0] = (ea[1] >> 8) & 0xFF;
|
|
||||||
sc->age_eaddr[1] = (ea[1] >> 0) & 0xFF;
|
|
||||||
sc->age_eaddr[2] = (ea[0] >> 24) & 0xFF;
|
|
||||||
sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
|
|
||||||
sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
|
|
||||||
sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
age_phy_reset(struct age_softc *sc)
|
age_phy_reset(struct age_softc *sc)
|
||||||
{
|
{
|
||||||
|
uint16_t reg, pn;
|
||||||
|
int i, linkup;
|
||||||
|
|
||||||
/* Reset PHY. */
|
/* Reset PHY. */
|
||||||
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_RST);
|
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_RST);
|
||||||
// pause("agephy", hz / 1000);
|
DELAY(2000);
|
||||||
DELAY(1000);
|
|
||||||
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_CLR);
|
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_CLR);
|
||||||
DELAY(1000);
|
DELAY(2000);
|
||||||
//pause("agephy", hz / 1000);
|
|
||||||
|
#define ATPHY_DBG_ADDR 0x1D
|
||||||
|
#define ATPHY_DBG_DATA 0x1E
|
||||||
|
#define ATPHY_CDTC 0x16
|
||||||
|
#define PHY_CDTC_ENB 0x0001
|
||||||
|
#define PHY_CDTC_POFF 8
|
||||||
|
#define ATPHY_CDTS 0x1C
|
||||||
|
#define PHY_CDTS_STAT_OK 0x0000
|
||||||
|
#define PHY_CDTS_STAT_SHORT 0x0100
|
||||||
|
#define PHY_CDTS_STAT_OPEN 0x0200
|
||||||
|
#define PHY_CDTS_STAT_INVAL 0x0300
|
||||||
|
#define PHY_CDTS_STAT_MASK 0x0300
|
||||||
|
|
||||||
|
/* Check power saving mode. Magic from Linux. */
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr, MII_BMCR, BMCR_RESET);
|
||||||
|
for (linkup = 0, pn = 0; pn < 4; pn++) {
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr, ATPHY_CDTC,
|
||||||
|
(pn << PHY_CDTC_POFF) | PHY_CDTC_ENB);
|
||||||
|
for (i = 200; i > 0; i--) {
|
||||||
|
DELAY(1000);
|
||||||
|
reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_CDTC);
|
||||||
|
if ((reg & PHY_CDTC_ENB) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DELAY(1000);
|
||||||
|
reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_CDTS);
|
||||||
|
if ((reg & PHY_CDTS_STAT_MASK) != PHY_CDTS_STAT_OPEN) {
|
||||||
|
#if 1
|
||||||
|
device_printf(sc->age_dev, "link found!\n");
|
||||||
|
#endif
|
||||||
|
linkup++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr, MII_BMCR,
|
||||||
|
BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
|
||||||
|
if (linkup == 0) {
|
||||||
|
#if 1
|
||||||
|
device_printf(sc->age_dev, "waking up PHY\n");
|
||||||
|
#endif
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_ADDR, 0);
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_DATA, 0x124E);
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_ADDR, 1);
|
||||||
|
reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_DATA);
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_DATA, reg | 0x03);
|
||||||
|
/* XXX */
|
||||||
|
DELAY(1500 * 1000);
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_ADDR, 0);
|
||||||
|
age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
|
||||||
|
ATPHY_DBG_DATA, 0x024E);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ATPHY_DBG_ADDR
|
||||||
|
#undef ATPHY_DBG_DATA
|
||||||
|
#undef ATPHY_CDTC
|
||||||
|
#undef PHY_CDTC_ENB
|
||||||
|
#undef PHY_CDTC_POFF
|
||||||
|
#undef ATPHY_CDTS
|
||||||
|
#undef PHY_CDTS_STAT_OK
|
||||||
|
#undef PHY_CDTS_STAT_SHORT
|
||||||
|
#undef PHY_CDTS_STAT_OPEN
|
||||||
|
#undef PHY_CDTS_STAT_INVAL
|
||||||
|
#undef PHY_CDTS_STAT_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -559,8 +525,9 @@ age_attach(device_t dev)
|
|||||||
sc->age_rev = pci_get_revid(dev);
|
sc->age_rev = pci_get_revid(dev);
|
||||||
sc->age_chip_rev = CSR_READ_4(sc, AGE_MASTER_CFG) >>
|
sc->age_chip_rev = CSR_READ_4(sc, AGE_MASTER_CFG) >>
|
||||||
MASTER_CHIP_REV_SHIFT;
|
MASTER_CHIP_REV_SHIFT;
|
||||||
if (1 || bootverbose) {
|
if (bootverbose) {
|
||||||
device_printf(dev, "PCI device revision : 0x%04x\n", sc->age_rev);
|
device_printf(dev, "PCI device revision : 0x%04x\n",
|
||||||
|
sc->age_rev);
|
||||||
device_printf(dev, "Chip id/revision : 0x%04x\n",
|
device_printf(dev, "Chip id/revision : 0x%04x\n",
|
||||||
sc->age_chip_rev);
|
sc->age_chip_rev);
|
||||||
}
|
}
|
||||||
@@ -586,7 +553,7 @@ age_attach(device_t dev)
|
|||||||
/* Allocate IRQ resources. */
|
/* Allocate IRQ resources. */
|
||||||
msixc = pci_msix_count(dev);
|
msixc = pci_msix_count(dev);
|
||||||
msic = pci_msi_count(dev);
|
msic = pci_msi_count(dev);
|
||||||
if (1 || bootverbose) {
|
if (bootverbose) {
|
||||||
device_printf(dev, "MSIX count : %d\n", msixc);
|
device_printf(dev, "MSIX count : %d\n", msixc);
|
||||||
device_printf(dev, "MSI count : %d\n", msic);
|
device_printf(dev, "MSI count : %d\n", msic);
|
||||||
}
|
}
|
||||||
@@ -633,7 +600,7 @@ age_attach(device_t dev)
|
|||||||
/* Max payload size. */
|
/* Max payload size. */
|
||||||
sc->age_dma_wr_burst = ((burst >> 5) & 0x07) <<
|
sc->age_dma_wr_burst = ((burst >> 5) & 0x07) <<
|
||||||
DMA_CFG_WR_BURST_SHIFT;
|
DMA_CFG_WR_BURST_SHIFT;
|
||||||
if (1 || bootverbose) {
|
if (bootverbose) {
|
||||||
device_printf(dev, "Read request size : %d bytes.\n",
|
device_printf(dev, "Read request size : %d bytes.\n",
|
||||||
128 << ((burst >> 12) & 0x07));
|
128 << ((burst >> 12) & 0x07));
|
||||||
device_printf(dev, "TLP payload size : %d bytes.\n",
|
device_printf(dev, "TLP payload size : %d bytes.\n",
|
||||||
@@ -1390,7 +1357,7 @@ age_setwol(struct age_softc *sc)
|
|||||||
|
|
||||||
AGE_LOCK_ASSERT(sc);
|
AGE_LOCK_ASSERT(sc);
|
||||||
|
|
||||||
if (pci_find_extcap(sc->age_dev, PCIY_PMG, &pmc) == 0) {
|
if (pci_find_extcap(sc->age_dev, PCIY_PMG, &pmc) != 0) {
|
||||||
CSR_WRITE_4(sc, AGE_WOL_CFG, 0);
|
CSR_WRITE_4(sc, AGE_WOL_CFG, 0);
|
||||||
/*
|
/*
|
||||||
* No PME capability, PHY power down.
|
* No PME capability, PHY power down.
|
||||||
@@ -1448,7 +1415,7 @@ age_setwol(struct age_softc *sc)
|
|||||||
MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
|
MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
|
||||||
DELAY(1000);
|
DELAY(1000);
|
||||||
if (aneg != 0) {
|
if (aneg != 0) {
|
||||||
/* Poll link state until jme(4) get a 10/100 link. */
|
/* Poll link state until age(4) get a 10/100 link. */
|
||||||
for (i = 0; i < MII_ANEGTICKS_GIGE; i++) {
|
for (i = 0; i < MII_ANEGTICKS_GIGE; i++) {
|
||||||
mii_pollstat(mii);
|
mii_pollstat(mii);
|
||||||
if ((mii->mii_media_status & IFM_AVALID) != 0) {
|
if ((mii->mii_media_status & IFM_AVALID) != 0) {
|
||||||
@@ -1463,8 +1430,11 @@ age_setwol(struct age_softc *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AGE_UNLOCK(sc);
|
AGE_UNLOCK(sc);
|
||||||
//pause("agelnk", hz);
|
#ifdef __HAIKU__
|
||||||
DELAY(1);
|
DELAY(1);
|
||||||
|
#else
|
||||||
|
pause("agelnk", hz);
|
||||||
|
#endif
|
||||||
AGE_LOCK(sc);
|
AGE_LOCK(sc);
|
||||||
}
|
}
|
||||||
if (i == MII_ANEGTICKS_GIGE)
|
if (i == MII_ANEGTICKS_GIGE)
|
||||||
@@ -1546,6 +1516,9 @@ age_resume(device_t dev)
|
|||||||
cmd &= ~0x0400;
|
cmd &= ~0x0400;
|
||||||
pci_write_config(sc->age_dev, PCIR_COMMAND, cmd, 2);
|
pci_write_config(sc->age_dev, PCIR_COMMAND, cmd, 2);
|
||||||
}
|
}
|
||||||
|
AGE_UNLOCK(sc);
|
||||||
|
age_phy_reset(sc);
|
||||||
|
AGE_LOCK(sc);
|
||||||
ifp = sc->age_ifp;
|
ifp = sc->age_ifp;
|
||||||
if ((ifp->if_flags & IFF_UP) != 0)
|
if ((ifp->if_flags & IFF_UP) != 0)
|
||||||
age_init_locked(sc);
|
age_init_locked(sc);
|
||||||
@@ -1579,12 +1552,13 @@ age_encap(struct age_softc *sc, struct mbuf **m_head)
|
|||||||
ip_off = poff = 0;
|
ip_off = poff = 0;
|
||||||
if ((m->m_pkthdr.csum_flags & (AGE_CSUM_FEATURES | CSUM_TSO)) != 0) {
|
if ((m->m_pkthdr.csum_flags & (AGE_CSUM_FEATURES | CSUM_TSO)) != 0) {
|
||||||
/*
|
/*
|
||||||
* L1 requires TCP/UDP payload offset in its Tx descriptor
|
* L1 requires offset of TCP/UDP payload in its Tx
|
||||||
* to perform hardware Tx checksum offload. Additionally
|
* descriptor to perform hardware Tx checksum offload.
|
||||||
* TSO requires IP/TCP header size and modification of
|
* Additionally, TSO requires IP/TCP header size and
|
||||||
* IP/TCP header in order to make TSO engine work. This
|
* modification of IP/TCP header in order to make TSO
|
||||||
* kind of operation takes many CPU cycles so fast host
|
* engine work. This kind of operation takes many CPU
|
||||||
* CPU is needed to get smooth TSO performance.
|
* cycles on FreeBSD so fast host CPU is needed to get
|
||||||
|
* smooth TSO performance.
|
||||||
*/
|
*/
|
||||||
struct ether_header *eh;
|
struct ether_header *eh;
|
||||||
|
|
||||||
@@ -1633,11 +1607,18 @@ age_encap(struct age_softc *sc, struct mbuf **m_head)
|
|||||||
}
|
}
|
||||||
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
|
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
|
||||||
/*
|
/*
|
||||||
* L1 requires IP/TCP header size and offset as well
|
* L1 requires IP/TCP header size and offset as
|
||||||
* as TCP pseudo checksum which all complicates TSO
|
* well as TCP pseudo checksum which complicates
|
||||||
* configuration. Hopefully this wouldn't be much
|
* TSO configuration. I guess this comes from the
|
||||||
* burden on modern CPUs.
|
* adherence to Microsoft NDIS Large Send
|
||||||
* Reset IP checksum and recompute TCP pseudo checksum.
|
* specification which requires insertion of
|
||||||
|
* pseudo checksum by upper stack. The pseudo
|
||||||
|
* checksum that NDIS refers to doesn't include
|
||||||
|
* TCP payload length so age(4) should recompute
|
||||||
|
* the pseudo checksum here. Hopefully this wouldn't
|
||||||
|
* be much burden on modern CPUs.
|
||||||
|
* Reset IP checksum and recompute TCP pseudo
|
||||||
|
* checksum as NDIS specification said.
|
||||||
*/
|
*/
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
if (poff + (tcp->th_off << 2) == m->m_pkthdr.len)
|
if (poff + (tcp->th_off << 2) == m->m_pkthdr.len)
|
||||||
@@ -2492,9 +2473,6 @@ age_rxintr(struct age_softc *sc, int rr_prod, int count)
|
|||||||
bus_dmamap_sync(sc->age_cdata.age_rr_ring_tag,
|
bus_dmamap_sync(sc->age_cdata.age_rr_ring_tag,
|
||||||
sc->age_cdata.age_rr_ring_map,
|
sc->age_cdata.age_rr_ring_map,
|
||||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
||||||
bus_dmamap_sync(sc->age_cdata.age_rx_ring_tag,
|
|
||||||
sc->age_cdata.age_rx_ring_map,
|
|
||||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
|
||||||
|
|
||||||
for (prog = 0; rr_cons != rr_prod; prog++) {
|
for (prog = 0; rr_cons != rr_prod; prog++) {
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
@@ -2527,9 +2505,6 @@ age_rxintr(struct age_softc *sc, int rr_prod, int count)
|
|||||||
sc->age_cdata.age_rr_cons = rr_cons;
|
sc->age_cdata.age_rr_cons = rr_cons;
|
||||||
|
|
||||||
/* Sync descriptors. */
|
/* Sync descriptors. */
|
||||||
bus_dmamap_sync(sc->age_cdata.age_rx_ring_tag,
|
|
||||||
sc->age_cdata.age_rx_ring_map,
|
|
||||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
|
||||||
bus_dmamap_sync(sc->age_cdata.age_rr_ring_tag,
|
bus_dmamap_sync(sc->age_cdata.age_rr_ring_tag,
|
||||||
sc->age_cdata.age_rr_ring_map,
|
sc->age_cdata.age_rr_ring_map,
|
||||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||||
@@ -2564,14 +2539,8 @@ age_reset(struct age_softc *sc)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
CSR_WRITE_4(sc, AGE_MASTER_CFG, MASTER_RESET);
|
CSR_WRITE_4(sc, AGE_MASTER_CFG, MASTER_RESET);
|
||||||
for (i = AGE_RESET_TIMEOUT; i > 0; i--) {
|
CSR_READ_4(sc, AGE_MASTER_CFG);
|
||||||
DELAY(1);
|
DELAY(1000);
|
||||||
if ((CSR_READ_4(sc, AGE_MASTER_CFG) & MASTER_RESET) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 0)
|
|
||||||
device_printf(sc->age_dev, "master reset timeout!\n");
|
|
||||||
|
|
||||||
for (i = AGE_RESET_TIMEOUT; i > 0; i--) {
|
for (i = AGE_RESET_TIMEOUT; i > 0; i--) {
|
||||||
if ((reg = CSR_READ_4(sc, AGE_IDLE_STATUS)) == 0)
|
if ((reg = CSR_READ_4(sc, AGE_IDLE_STATUS)) == 0)
|
||||||
break;
|
break;
|
||||||
@@ -2705,7 +2674,7 @@ age_init_locked(struct age_softc *sc)
|
|||||||
else
|
else
|
||||||
reg |= MASTER_ITIMER_ENB;
|
reg |= MASTER_ITIMER_ENB;
|
||||||
CSR_WRITE_4(sc, AGE_MASTER_CFG, reg);
|
CSR_WRITE_4(sc, AGE_MASTER_CFG, reg);
|
||||||
if (1 || bootverbose)
|
if (bootverbose)
|
||||||
device_printf(sc->age_dev, "interrupt moderation is %d us.\n",
|
device_printf(sc->age_dev, "interrupt moderation is %d us.\n",
|
||||||
sc->age_int_mod);
|
sc->age_int_mod);
|
||||||
CSR_WRITE_2(sc, AGE_INTR_CLR_TIMER, AGE_USECS(1000));
|
CSR_WRITE_2(sc, AGE_INTR_CLR_TIMER, AGE_USECS(1000));
|
||||||
@@ -3231,7 +3200,8 @@ sysctl_age_stats(SYSCTL_HANDLER_ARGS)
|
|||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
sc = (struct age_softc *)arg1;
|
sc = (struct age_softc *)arg1;
|
||||||
stats = &sc->age_stat; /*
|
stats = &sc->age_stat;
|
||||||
|
#if 0
|
||||||
printf("%s statistics:\n", device_get_nameunit(sc->age_dev));
|
printf("%s statistics:\n", device_get_nameunit(sc->age_dev));
|
||||||
printf("Transmit good frames : %ju\n",
|
printf("Transmit good frames : %ju\n",
|
||||||
(uintmax_t)stats->tx_frames);
|
(uintmax_t)stats->tx_frames);
|
||||||
@@ -3331,7 +3301,8 @@ sysctl_age_stats(SYSCTL_HANDLER_ARGS)
|
|||||||
printf("Receive frames with alignment errors : %u\n",
|
printf("Receive frames with alignment errors : %u\n",
|
||||||
stats->rx_alignerrs);
|
stats->rx_alignerrs);
|
||||||
printf("Receive frames dropped due to address filtering : %ju\n",
|
printf("Receive frames dropped due to address filtering : %ju\n",
|
||||||
(uint64_t)stats->rx_pkts_filtered);*/
|
(uint64_t)stats->rx_pkts_filtered);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $FreeBSD
|
* $FreeBSD: src/sys/dev/age/if_agereg.h,v 1.1 2008/05/19 01:39:59 yongari Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _IF_AGEREG_H
|
#ifndef _IF_AGEREG_H
|
||||||
@@ -91,6 +91,9 @@
|
|||||||
#define AGE_SPI_OP_READ 0x217 /* 8bits */
|
#define AGE_SPI_OP_READ 0x217 /* 8bits */
|
||||||
|
|
||||||
#define AGE_TWSI_CTRL 0x218
|
#define AGE_TWSI_CTRL 0x218
|
||||||
|
#define TWSI_CTRL_SW_LD_START 0x00000800
|
||||||
|
#define TWSI_CTRL_HW_LD_START 0x00001000
|
||||||
|
#define TWSI_CTRL_LD_EXIST 0x00400000
|
||||||
|
|
||||||
#define AGE_DEV_MISC_CTRL 0x21C
|
#define AGE_DEV_MISC_CTRL 0x21C
|
||||||
|
|
||||||
@@ -483,10 +486,6 @@
|
|||||||
(INTR_SMB | INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST | \
|
(INTR_SMB | INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST | \
|
||||||
INTR_CMB_TX | INTR_CMB_RX)
|
INTR_CMB_TX | INTR_CMB_RX)
|
||||||
|
|
||||||
#define AGE_RD_RRD_IDX 0x1800
|
|
||||||
|
|
||||||
#define AGE_TPD_IDX 0x1804
|
|
||||||
|
|
||||||
/* Statistics counters collected by the MAC. */
|
/* Statistics counters collected by the MAC. */
|
||||||
struct smb {
|
struct smb {
|
||||||
/* Rx stats. */
|
/* Rx stats. */
|
||||||
|
|||||||
Reference in New Issue
Block a user