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

Reply via email to