Since nobody with a working PCI_PRODUCT_ATTANSIC_L2C seems interested,
and the devices newly added in this diff are showing up more often
in submitted dmesg than the L2C version matched by the current driver,
I intend to commit this tomorrow unless there are objections.
On 2011/05/16 11:16, Stuart Henderson wrote:
> So far, only had reports from L1C and the new devices (which is
> not the point of sending out this sort of diff). This is a fairly
> large diff and changes behaviour for existing devices.
>
> Has anyone with a currently-working L2C tested this to make sure
> it doesn't break their nic?
>
>
> On 2011/05/01 20:10, Stuart Henderson wrote:
> > On 2011/05/01 18:35, Edd Barrett wrote:
> > > I have acquired a netboot (packard bell dot s), which I think uses this
> > > NIC. Is
> > > there an updated diff?
> >
> > Yes I just took the 2 minutes it took to apply it and fix
> > the minor conflicts and linewrapping issue with the diff.
> > Untested beyond "it builds".
> >
> > Test reports and dmesg lines from existing working alc(4) L1C and
> > L2C wanted. If it makes new chips work that's a bonus, but the
> > important thing is making sure it doesn't break something that
> > already works.
> >
> > Doesn't seem any point disabling interrupts in the ISR though.
> > I haven't touched that in this diff but that should probably be
> > done too.
>
> Index: share/man/man4/alc.4
> ===================================================================
> RCS file: /cvs/src/share/man/man4/alc.4,v
> retrieving revision 1.2
> diff -u -p -r1.2 alc.4
> --- share/man/man4/alc.4 8 Aug 2009 14:12:41 -0000 1.2
> +++ share/man/man4/alc.4 1 May 2011 18:55:25 -0000
> @@ -19,7 +19,7 @@
> .Os
> .Sh NAME
> .Nm alc
> -.Nd Atheros AR8131/AR8132 10/100/Gigabit Ethernet device
> +.Nd Atheros AR813x/AR815x 10/100/Gigabit Ethernet device
> .Sh SYNOPSIS
> .Cd "alc* at pci?"
> .Cd "atphy* at mii?"
> @@ -27,8 +27,7 @@
> The
> .Nm
> driver provides support for Ethernet interfaces based on the
> -Atheros AR8131/AR8132 Ethernet chipset, also known as
> -the Attansic L1C/L2C respectively.
> +Atheros AR813x/AR815x Ethernet chipset.
> .Pp
> The
> .Nm
> Index: sys/arch/amd64/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
> retrieving revision 1.316
> diff -u -p -r1.316 GENERIC
> --- sys/arch/amd64/conf/GENERIC 10 Apr 2011 20:27:02 -0000 1.316
> +++ sys/arch/amd64/conf/GENERIC 1 May 2011 18:55:25 -0000
> @@ -472,7 +472,7 @@ bce* at pci? # Broadcom
> BCM4401
> vic* at pci? # VMware VMXnet virtual interface
> et* at pci? # Agere/LSI ET1310
> age* at pci? # Attansic L1 Ethernet
> -alc* at pci? # Attansic L1C/L2C Ethernet
> +alc* at pci? # Attansic L1C/L1D/L2C Ethernet
> ale* at pci? # Attansic L1E Ethernet
> lii* at pci? # Attansic L2 Ethernet
> jme* at pci? # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/amd64/conf/RAMDISK_CD
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
> retrieving revision 1.116
> diff -u -p -r1.116 RAMDISK_CD
> --- sys/arch/amd64/conf/RAMDISK_CD 3 Apr 2011 12:32:05 -0000 1.116
> +++ sys/arch/amd64/conf/RAMDISK_CD 1 May 2011 18:55:25 -0000
> @@ -291,7 +291,7 @@ bce* at pci? # Broadcom BCM4401
> vic* at pci? # VMware VMXnet virtual interface
> et* at pci? # Agere/LSI ET1310
> age* at pci? # Attansic L1 Ethernet
> -alc* at pci? # Attansic L1C/L2C Ethernet
> +alc* at pci? # Attansic L1C/L1D/L2C Ethernet
> ale* at pci? # Attansic L1E Ethernet
> lii* at pci? # Attansic L2 Ethernet
> jme* at pci? # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/i386/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v
> retrieving revision 1.713
> diff -u -p -r1.713 GENERIC
> --- sys/arch/i386/conf/GENERIC 10 Apr 2011 20:27:02 -0000 1.713
> +++ sys/arch/i386/conf/GENERIC 1 May 2011 18:55:25 -0000
> @@ -632,7 +632,7 @@ gem* at pci? # Sun 'gem'
> ethernet
> vic* at pci? # VMware VMXnet virtual interface
> et* at pci? # Agere/LSI ET1310
> age* at pci? # Attansic L1 Ethernet
> -alc* at pci? # Attansic L1C/L2C Ethernet
> +alc* at pci? # Attansic L1C/L1D/L2C Ethernet
> ale* at pci? # Attansic L1E Ethernet
> lii* at pci? # Attansic L2 Ethernet
> jme* at pci? # JMicron JMC250/JMC260 Ethernet
> Index: sys/arch/i386/conf/RAMDISK_CD
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/conf/RAMDISK_CD,v
> retrieving revision 1.185
> diff -u -p -r1.185 RAMDISK_CD
> --- sys/arch/i386/conf/RAMDISK_CD 3 Apr 2011 12:32:05 -0000 1.185
> +++ sys/arch/i386/conf/RAMDISK_CD 1 May 2011 18:55:25 -0000
> @@ -372,7 +372,7 @@ xge* at pci? # Neterion
> Xframe-I/II 1
> vic* at pci? # VMware VMXnet virtual interface
> et* at pci? # Agere/LSI ET1310
> age* at pci? # Attansic L1 Ethernet
> -alc* at pci? # Attansic L1C/L2C Ethernet
> +alc* at pci? # Attansic L1C/L1D/L2C Ethernet
> ale* at pci? # Attansic L1E Ethernet
> lii* at pci? # Attansic L2 Ethernet
> jme* at pci? # JMicron JMC250/JMC260 Ethernet
> Index: sys/dev/pci/files.pci
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/files.pci,v
> retrieving revision 1.278
> diff -u -p -r1.278 files.pci
> --- sys/dev/pci/files.pci 10 Apr 2011 20:27:02 -0000 1.278
> +++ sys/dev/pci/files.pci 1 May 2011 18:55:25 -0000
> @@ -643,7 +643,7 @@ device age: ether, ifnet, mii, ifmedia,
> attach age at pci
> file dev/pci/if_age.c age
>
> -# Attansic/Atheros L1C/L2C Gigabit Ethernet
> +# Attansic/Atheros L1C/L1D/L2C Gigabit Ethernet
> device alc: ether, ifnet, mii, ifmedia, mii_phy
> attach alc at pci
> file dev/pci/if_alc.c alc
> Index: sys/dev/pci/if_alc.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_alc.c,v
> retrieving revision 1.11
> diff -u -p -r1.11 if_alc.c
> --- sys/dev/pci/if_alc.c 5 Apr 2011 18:01:21 -0000 1.11
> +++ sys/dev/pci/if_alc.c 1 May 2011 18:55:25 -0000
> @@ -88,7 +88,7 @@ void alc_watchdog(struct ifnet *);
> int alc_mediachange(struct ifnet *);
> void alc_mediastatus(struct ifnet *, struct ifmediareq *);
>
> -void alc_aspm(struct alc_softc *);
> +void alc_aspm(struct alc_softc *, int);
> void alc_disable_l0s_l1(struct alc_softc *);
> int alc_dma_alloc(struct alc_softc *);
> void alc_dma_free(struct alc_softc *);
> @@ -109,7 +109,7 @@ void alc_phy_down(struct alc_softc *);
> void alc_phy_reset(struct alc_softc *);
> void alc_reset(struct alc_softc *);
> void alc_rxeof(struct alc_softc *, struct rx_rdesc *);
> -int alc_rxintr(struct alc_softc *);
> +void alc_rxintr(struct alc_softc *);
> void alc_iff(struct alc_softc *);
> void alc_rxvlan(struct alc_softc *);
> void alc_start_queue(struct alc_softc *);
> @@ -125,7 +125,11 @@ uint32_t alc_dma_burst[] = { 128, 256, 5
>
> const struct pci_matchid alc_devices[] = {
> { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1C },
> - { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C }
> + { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C },
> + { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D },
> + { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L1D_1 },
> + { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_1 },
> + { PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_L2C_2 }
> };
>
> struct cfattach alc_ca = {
> @@ -236,8 +240,8 @@ alc_miibus_statchg(struct device *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);
> }
>
> void
> @@ -280,20 +284,53 @@ 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.
> */
> - 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);
> + eeprom++;
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L1C:
> + case PCI_PRODUCT_ATTANSIC_L2C:
> + 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 PCI_PRODUCT_ATTANSIC_L1D:
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_2:
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x00);
> + val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, val & 0xFF7F);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x3B);
> + val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_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--) {
> @@ -309,11 +346,36 @@ alc_get_macaddr(struct alc_softc *sc)
> if (alcdebug)
> printf("%s: EEPROM not found!\n", sc->sc_dev.dv_xname);
> }
> - 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);
> + if (eeprom != 0) {
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L1C:
> + case PCI_PRODUCT_ATTANSIC_L2C:
> + 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 PCI_PRODUCT_ATTANSIC_L1D:
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_2:
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x00);
> + val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, val | 0x0080);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x3B);
> + val = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, val & 0xFFF7);
> + DELAY(20);
> + break;
> + }
> }
>
> ea[0] = CSR_READ_4(sc, ALC_PAR0);
> @@ -358,6 +420,43 @@ alc_phy_reset(struct alc_softc *sc)
> CSR_READ_2(sc, ALC_GPHY_CFG);
> DELAY(10 * 1000);
>
> + /* DSP fixup, Vendor magic. */
> + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x000A);
> + data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, data & 0xDFFF);
> + }
> + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x003B);
> + data = alc_miibus_readreg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, data & 0xFFF7);
> + DELAY(20 * 1000);
> + }
> + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D) {
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x0029);
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_DATA, 0x929D);
> + }
> + if (sc->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2) {
> + alc_miibus_writereg(&sc->sc_dev, sc->alc_phyaddr,
> + ALC_MII_DBG_ADDR, 0x0029);
> + alc_miibus_writereg(&sc->sc_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);
> @@ -406,35 +505,114 @@ alc_phy_reset(struct alc_softc *sc)
> void
> alc_phy_down(struct alc_softc *sc)
> {
> -
> - /* 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);
> - DELAY(1000);
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L1D:
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + /*
> + * 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->sc_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);
> + DELAY(1000);
> + break;
> + }
> }
>
> void
> -alc_aspm(struct alc_softc *sc)
> +alc_aspm(struct alc_softc *sc, int media)
> {
> uint32_t pmcfg;
> + uint16_t linkcfg;
>
> 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 +
> + PCI_PCIE_LCSR);
> + 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_LCKDET_TIMER_DEFAULT << PM_CFG_LCKDET_TIMER_SHIFT);
> + 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->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
> + sc->alc_rev == ATHEROS_AR8152_B_V10)
> + linkcfg |= 0x80;
> + CSR_WRITE_2(sc, sc->alc_expcap + PCI_PCIE_LCSR,
> + 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;
> - pmcfg &= ~PM_CFG_ASPM_L0S_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->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
> + pmcfg &= ~PM_CFG_ASPM_L0S_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;
> + if (media == IFM_100_TX || media == IFM_1000_T) {
> + pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_MASK;
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L2C_1:
> + pmcfg |= (7 <<
> + PM_CFG_L1_ENTRY_TIMER_SHIFT);
> + break;
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_2:
> + 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_PLL_L1_ENB;
> + 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;
> - pmcfg &= ~PM_CFG_ASPM_L1_ENB;
> - pmcfg &= ~PM_CFG_ASPM_L0S_ENB;
> + if ((sc->alc_flags & ALC_FLAG_L1S) != 0)
> + pmcfg |= PM_CFG_ASPM_L1_ENB;
> }
> CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
> }
> @@ -450,9 +628,9 @@ alc_attach(struct device *parent, struct
> const char *intrstr;
> struct ifnet *ifp;
> pcireg_t memtype;
> - char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/l1" };
> + char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
> uint16_t burst;
> - int base, mii_flags, state, error = 0;
> + int base, state, error = 0;
> uint32_t cap, ctl, val;
>
> /*
> @@ -499,6 +677,7 @@ alc_attach(struct device *parent, struct
> if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
> &base, NULL)) {
> sc->alc_flags |= ALC_FLAG_PCIE;
> + sc->alc_expcap = base;
> burst = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
> base + PCI_PCIE_DCSR) >> 16;
> sc->alc_dma_rd_burst = (burst & 0x7000) >> 12;
> @@ -515,6 +694,20 @@ alc_attach(struct device *parent, struct
> 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->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 &&
> + 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 = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
> base + PCI_PCIE_LCAP) >> 16;
> @@ -528,13 +721,16 @@ alc_attach(struct device *parent, struct
> sc->sc_dev.dv_xname,
> 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 (alcdebug)
> printf("%s: ASPM %s %s\n",
> sc->sc_dev.dv_xname,
> aspm_state[state],
> state == 0 ? "disabled" : "enabled");
> - if (state != 0)
> - alc_disable_l0s_l1(sc);
> + alc_disable_l0s_l1(sc);
> }
> }
>
> @@ -551,12 +747,39 @@ alc_attach(struct device *parent, struct
> * used in AR8132 can't establish gigabit link even if it
> * shows the same PHY model/revision number of AR8131.
> */
> - if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATTANSIC_L2C)
> - sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_JUMBO;
> - else
> - sc->alc_flags |= ALC_FLAG_JUMBO | ALC_FLAG_ASPM_MON;
> + sc->sc_product = PCI_PRODUCT(pa->pa_id);
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L2C_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_2:
> + sc->alc_flags |= ALC_FLAG_APS;
> + /* FALLTHROUGH */
> + case PCI_PRODUCT_ATTANSIC_L2C:
> + sc->alc_flags |= ALC_FLAG_FASTETHER;
> + break;
> + case PCI_PRODUCT_ATTANSIC_L1D:
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + sc->alc_flags |= ALC_FLAG_APS;
> + /* FALLTHROUGH */
> + default:
> + break;
> + }
> + sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
> +
> + switch (sc->sc_product) {
> + case PCI_PRODUCT_ATTANSIC_L1C:
> + case PCI_PRODUCT_ATTANSIC_L2C:
> + sc->alc_max_framelen = 9 * 1024;
> + break;
> + case PCI_PRODUCT_ATTANSIC_L1D:
> + case PCI_PRODUCT_ATTANSIC_L1D_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_1:
> + case PCI_PRODUCT_ATTANSIC_L2C_2:
> + sc->alc_max_framelen = 6 * 1024;
> + break;
> + }
> +
> /*
> - * 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.
> @@ -619,11 +842,8 @@ alc_attach(struct device *parent, struct
>
> ifmedia_init(&sc->sc_miibus.mii_media, 0, alc_mediachange,
> alc_mediastatus);
> - mii_flags = 0;
> - if ((sc->alc_flags & ALC_FLAG_JUMBO) != 0)
> - mii_flags |= MIIF_DOPAUSE;
> mii_attach(self, &sc->sc_miibus, 0xffffffff, MII_PHY_ANY,
> - MII_OFFSET_ANY, mii_flags);
> + MII_OFFSET_ANY, MIIF_DOPAUSE);
>
> if (LIST_FIRST(&sc->sc_miibus.mii_phys) == NULL) {
> printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
> @@ -1136,16 +1356,15 @@ alc_start(struct ifnet *ifp)
> {
> struct alc_softc *sc = ifp->if_softc;
> struct mbuf *m_head;
> - int enq;
> -
> - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
> - return;
> + int enq = 0;
>
> /* Reclaim transmitted frames. */
> if (sc->alc_cdata.alc_tx_cnt >= ALC_TX_DESC_HIWAT)
> alc_txeof(sc);
>
> - enq = 0;
> + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
> + return;
> +
> for (;;) {
> IFQ_DEQUEUE(&ifp->if_snd, m_head);
> if (m_head == NULL)
> @@ -1162,7 +1381,7 @@ alc_start(struct ifnet *ifp)
> ifp->if_flags |= IFF_OACTIVE;
> break;
> }
> - enq = 1;
> + enq++;
>
> #if NBPFILTER > 0
> /*
> @@ -1174,7 +1393,7 @@ alc_start(struct ifnet *ifp)
> #endif
> }
>
> - if (enq) {
> + if (enq > 0) {
> /* Sync descriptors. */
> bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
> sc->alc_cdata.alc_tx_ring_map->dm_mapsize,
> @@ -1274,6 +1493,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->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> + 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:
> @@ -1451,24 +1674,25 @@ alc_intr(void *arg)
> struct alc_softc *sc = arg;
> struct ifnet *ifp = &sc->sc_arpcom.ac_if;
> uint32_t status;
> + int claimed = 0;
>
> status = CSR_READ_4(sc, ALC_INTR_STATUS);
> if ((status & ALC_INTRS) == 0)
> return (0);
>
> + /* Disable interrupts. */
> + CSR_WRITE_4(sc, ALC_INTR_STATUS, INTR_DIS_INT);
> +
> + status = CSR_READ_4(sc, ALC_INTR_STATUS);
> + if ((status & ALC_INTRS) == 0)
> + goto back;
> +
> /* Acknowledge and disable interrupts. */
> CSR_WRITE_4(sc, ALC_INTR_STATUS, status | INTR_DIS_INT);
>
> if (ifp->if_flags & IFF_RUNNING) {
> - if (status & INTR_RX_PKT) {
> - int error;
> -
> - error = alc_rxintr(sc);
> - if (error) {
> - alc_init(ifp);
> - return (0);
> - }
> - }
> + if (status & INTR_RX_PKT)
> + alc_rxintr(sc);
>
> if (status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST |
> INTR_TXQ_TO_RST)) {
> @@ -1485,14 +1709,17 @@ alc_intr(void *arg)
> return (0);
> }
>
> - alc_txeof(sc);
> - if (!IFQ_IS_EMPTY(&ifp->if_snd))
> + if (status & INTR_TX_PKT) {
> + alc_txeof(sc);
> + if (!IFQ_IS_EMPTY(&ifp->if_snd))
> alc_start(ifp);
> + }
> }
> -
> + claimed = 1;
> +back:
> /* Re-enable interrupts. */
> CSR_WRITE_4(sc, ALC_INTR_STATUS, 0x7FFFFFFF);
> - return (1);
> + return (claimed);
> }
>
> void
> @@ -1507,7 +1734,7 @@ alc_txeof(struct alc_softc *sc)
> return;
> bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_tx_ring_map, 0,
> sc->alc_cdata.alc_tx_ring_map->dm_mapsize,
> - BUS_DMASYNC_POSTREAD);
> + BUS_DMASYNC_POSTWRITE);
> if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
> bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_cmb_map, 0,
> sc->alc_cdata.alc_cmb_map->dm_mapsize,
> @@ -1591,7 +1818,7 @@ alc_newbuf(struct alc_softc *sc, struct
> return (0);
> }
>
> -int
> +void
> alc_rxintr(struct alc_softc *sc)
> {
> struct ifnet *ifp = &sc->sc_arpcom.ac_if;
> @@ -1615,7 +1842,7 @@ alc_rxintr(struct alc_softc *sc)
> if (alcdebug)
> printf("%s: unexpected segment count -- "
> "resetting\n", sc->sc_dev.dv_xname);
> - return (EIO);
> + break;
> }
> alc_rxeof(sc, rrd);
> /* Clear Rx return status. */
> @@ -1653,8 +1880,6 @@ alc_rxintr(struct alc_softc *sc)
> CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX,
> sc->alc_cdata.alc_rx_cons);
> }
> -
> - return (0);
> }
>
> /* Receive a frame. */
> @@ -1686,9 +1911,8 @@ alc_rxeof(struct alc_softc *sc, struct r
> * Force network stack compute checksum for
> * 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;
> }
>
> @@ -1801,7 +2025,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)
> @@ -1852,6 +2078,9 @@ alc_init(struct ifnet *ifp)
> alc_init_cmb(sc);
> alc_init_smb(sc);
>
> + /* Enable all clocks. */
> + CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
> +
> /* Reprogram the station address. */
> bcopy(LLADDR(ifp->if_sadl), eaddr, ETHER_ADDR_LEN);
> CSR_WRITE_4(sc, ALC_PAR0,
> @@ -1913,6 +2142,18 @@ alc_init(struct ifnet *ifp)
> 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->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1) {
> + /* 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);
>
> @@ -1922,14 +2163,11 @@ alc_init(struct ifnet *ifp)
> 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)
> @@ -1970,7 +2208,7 @@ alc_init(struct ifnet *ifp)
> * 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_max_framelen);
>
> /* Disable header split(?) */
> CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
> @@ -1997,11 +2235,14 @@ alc_init(struct ifnet *ifp)
> * TSO/checksum offloading.
> */
> CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH,
> - (ALC_JUMBO_FRAMELEN >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
> + (sc->alc_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->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> + 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);
> @@ -2018,14 +2259,22 @@ alc_init(struct ifnet *ifp)
> * XON : 80% of Rx FIFO
> * XOFF : 30% of Rx FIFO
> */
> - reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
> - rxf_hi = (reg * 8) / 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->sc_product == PCI_PRODUCT_ATTANSIC_L1C ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C) {
> + reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
> + rxf_hi = (reg * 8) / 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->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_1)
> + 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);
> @@ -2036,15 +2285,9 @@ alc_init(struct ifnet *ifp)
> 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;
> @@ -2070,7 +2313,7 @@ alc_init(struct ifnet *ifp)
> * - 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
> @@ -2080,6 +2323,10 @@ alc_init(struct ifnet *ifp)
> 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->sc_product == PCI_PRODUCT_ATTANSIC_L1D ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L1D_1 ||
> + sc->sc_product == PCI_PRODUCT_ATTANSIC_L2C_2)
> + 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
> Index: sys/dev/pci/if_alcreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_alcreg.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 if_alcreg.h
> --- sys/dev/pci/if_alcreg.h 8 Aug 2009 09:31:13 -0000 1.1
> +++ sys/dev/pci/if_alcreg.h 1 May 2011 18:55:25 -0000
> @@ -31,7 +31,10 @@
> #ifndef _IF_ALCREG_H
> #define _IF_ALCREG_H
>
> -#define ALC_PCIR_BAR 0x10
> +#define ALC_PCIR_BAR 0x10
> +
> +#define ATHEROS_AR8152_B_V10 0xC0
> +#define ATHEROS_AR8152_B_V11 0xC1
>
> /* 0x0000 - 0x02FF : PCIe configuration space */
>
> @@ -56,6 +59,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
>
> @@ -88,7 +97,9 @@
> #define PM_CFG_PCIE_RECV 0x00008000
> #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_LCKDET_TIMER_MASK 0x0F000000
> +#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
> @@ -96,10 +107,20 @@
> #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 1
> +#define PM_CFG_LCKDET_TIMER_DEFAULT 12
> +#define PM_CFG_PM_REQ_TIMER_DEFAULT 12
> +
> +#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
> @@ -114,7 +135,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)
>
> @@ -136,7 +157,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
> @@ -212,6 +233,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
> @@ -241,6 +264,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
>
> @@ -683,11 +708,19 @@
> #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
>
> +#define ALC_CLK_GATING_CFG 0x1814
> +#define CLK_GATING_DMAW_ENB 0x0001
> +#define CLK_GATING_DMAR_ENB 0x0002
> +#define CLK_GATING_TXQ_ENB 0x0004
> +#define CLK_GATING_RXQ_ENB 0x0008
> +#define CLK_GATING_TXMAC_ENB 0x0010
> +#define CLK_GATING_RXMAC_ENB 0x0020
> +
> #define ALC_DEBUG_DATA0 0x1900
>
> #define ALC_DEBUG_DATA1 0x1904
> @@ -1112,6 +1145,7 @@ struct alc_softc {
> bus_dma_tag_t sc_dmat;
> pci_chipset_tag_t sc_pct;
> pcitag_t sc_pcitag;
> + pci_vendor_id_t sc_product;
>
> void *sc_irq_handle;
>
> @@ -1120,19 +1154,23 @@ struct alc_softc {
> int alc_chip_rev;
> int alc_phyaddr;
> uint8_t alc_eaddr[ETHER_ADDR_LEN];
> + uint32_t alc_max_framelen;
> uint32_t alc_dma_rd_burst;
> uint32_t alc_dma_wr_burst;
> uint32_t alc_rcb;
> + int alc_expcap;
> 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