Hi,

The following diff adds support for Atheros AR8151/AR8152 chipsets;
mostly from FreeBSD. It also fixes an issue i386/6311.
Tested on Acer AOD255E.

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        25 Jan 2011 10:19:48 -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.312
diff -u -p -r1.312 GENERIC
--- sys/arch/amd64/conf/GENERIC 8 Jan 2011 11:56:30 -0000       1.312
+++ sys/arch/amd64/conf/GENERIC 25 Jan 2011 10:19:49 -0000
@@ -473,7 +473,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/amd64/conf/RAMDISK_CD
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
retrieving revision 1.115
diff -u -p -r1.115 RAMDISK_CD
--- sys/arch/amd64/conf/RAMDISK_CD      4 Aug 2010 21:44:41 -0000       1.115
+++ sys/arch/amd64/conf/RAMDISK_CD      25 Jan 2011 10:19:49 -0000
@@ -291,7 +291,7 @@ xge*        at pci?                 # Neterion Xframe-I/II 
10
 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.708
diff -u -p -r1.708 GENERIC
--- sys/arch/i386/conf/GENERIC  15 Jan 2011 04:39:27 -0000      1.708
+++ sys/arch/i386/conf/GENERIC  25 Jan 2011 10:19:50 -0000
@@ -634,7 +634,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.183
diff -u -p -r1.183 RAMDISK_CD
--- sys/arch/i386/conf/RAMDISK_CD       15 Jan 2011 04:39:27 -0000      1.183
+++ sys/arch/i386/conf/RAMDISK_CD       25 Jan 2011 10:19:51 -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.277
diff -u -p -r1.277 files.pci
--- sys/dev/pci/files.pci       15 Jan 2011 04:35:34 -0000      1.277
+++ sys/dev/pci/files.pci       25 Jan 2011 10:19:54 -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.8
diff -u -p -r1.8 if_alc.c
--- sys/dev/pci/if_alc.c        31 Aug 2010 17:13:44 -0000      1.8
+++ sys/dev/pci/if_alc.c        25 Jan 2011 10:19:55 -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, 
@@ -1601,7 +1828,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;
@@ -1625,7 +1852,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. */
@@ -1663,8 +1890,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. */
@@ -1696,9 +1921,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;
        }
 
@@ -1811,7 +2035,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)
@@ -1862,6 +2088,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,
@@ -1923,6 +2152,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);
 
@@ -1932,14 +2173,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)
@@ -1980,7 +2218,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);
@@ -2007,11 +2245,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);
@@ -2028,14 +2269,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);
@@ -2046,15 +2295,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;
@@ -2080,7 +2323,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
@@ -2090,6 +2333,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
@@ -2191,7 +2438,7 @@ alc_stop_mac(struct alc_softc *sc)
        /* Disable Rx/Tx MAC. */
        reg = CSR_READ_4(sc, ALC_MAC_CFG);
        if ((reg & (MAC_CFG_TX_ENB | MAC_CFG_RX_ENB)) != 0) {
-               reg &= ~MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
+               reg &= ~(MAC_CFG_TX_ENB | MAC_CFG_RX_ENB);
                CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
        }
        for (i = ALC_TIMEOUT; i > 0; i--) {
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     25 Jan 2011 10:19:56 -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
 
Index: sys/dev/pci/pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1588
diff -u -p -r1.1588 pcidevs
--- sys/dev/pci/pcidevs 19 Jan 2011 10:56:37 -0000      1.1588
+++ sys/dev/pci/pcidevs 25 Jan 2011 10:19:59 -0000
@@ -1429,6 +1429,10 @@ product ATTANSIC L1              0x1048  L1
 product ATTANSIC L2C           0x1062  L2C
 product ATTANSIC L1C           0x1063  L1C
 product ATTANSIC L2            0x2048  L2
+product ATTANSIC L1D           0x1073  L1D
+product ATTANSIC L1D_1         0x1083  L1D
+product ATTANSIC L2C_1         0x2060  L2C
+product ATTANSIC L2C_2         0x2062  L2C
 
 /* Aureal products */
 product AUREAL AU8820          0x0001  Vortex 1

Reply via email to