Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev - Add code for WOL, ASF, IPMI and Intel AMT.



details:   https://anonhg.NetBSD.org/src/rev/d7a5f1e21d10
branches:  trunk
changeset: 752796:d7a5f1e21d10
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Sun Mar 07 09:05:19 2010 +0000

description:
- Add code for WOL, ASF, IPMI and Intel AMT.
    - wm_enable_wakeup() is disabled by default. If you want to use WOL with
      the Magic Packet, define WM_WOL.
    - Add the following flags:
        WM_F_ASF_FIRMWARE_PRESENT
        WM_F_ARC_SUBSYSTEM_VALID
        WM_F_HAS_AMT
        WM_F_HAS_MANAGE
        WM_F_WOL
    - Add wm_suspend() and wm_resume(). Give/get the control to/from the
      firmware.
    - Need more work for PCH. See wm_enable_phy_wakeup().
- Enable wm_get_hw_control() for 82574 and 82583.
- Add Yet another workaround for ICH8.
    - Add wm_igp3_phy_powerdown_workaround_ich8lan() for power down problem
      on D3.

diffstat:

 sys/dev/mii/igphyreg.h |   18 +-
 sys/dev/pci/if_wm.c    |  417 ++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/pci/if_wmreg.h |   35 +++-
 sys/dev/pci/if_wmvar.h |   39 ++-
 4 files changed, 467 insertions(+), 42 deletions(-)

diffs (truncated from 767 to 300 lines):

diff -r c6875c96336e -r d7a5f1e21d10 sys/dev/mii/igphyreg.h
--- a/sys/dev/mii/igphyreg.h    Sun Mar 07 08:56:07 2010 +0000
+++ b/sys/dev/mii/igphyreg.h    Sun Mar 07 09:05:19 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: igphyreg.h,v 1.5 2010/01/12 21:48:26 msaitoh Exp $     */
+/*     $NetBSD: igphyreg.h,v 1.6 2010/03/07 09:05:19 msaitoh Exp $     */
 
 /*******************************************************************************
 
@@ -154,6 +154,22 @@
 #define ANALOG_FUSE_FINE_1             0x0080
 #define ANALOG_FUSE_FINE_10            0x0500
 
+/*
+ * IGP3 regs
+ */
+#define IGP3_PAGE_SHIFT                5
+#define IGP3_MAX_REG_ADDRESS   0x1f  /* 5 bit address bus (0-0x1f) */
+#define IGP3_REG(page, reg) \
+       (((page) << IGP3_PAGE_SHIFT) | ((reg) & IGP3_MAX_REG_ADDRESS))
+
+#define IGP3_VR_CTRL   IGP3_REG(776, 18)
+#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK   0x0300
+#define IGP3_VR_CTRL_MODE_SHUTDOWN             0x0200
+
+#define IGP3_PM_CTRL   IGP3_REG(769, 20)
+#define IGP3_PM_CTRL_FORCE_PWR_DOWN            0x0020
+
+
 #define IGPHY_READ(sc, reg) \
     (PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, (reg) & ~0x1f), \
      PHY_READ(sc, (reg) & 0x1f))
diff -r c6875c96336e -r d7a5f1e21d10 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Sun Mar 07 08:56:07 2010 +0000
+++ b/sys/dev/pci/if_wm.c       Sun Mar 07 09:05:19 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.202 2010/03/07 07:53:37 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.203 2010/03/07 09:05:19 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.202 2010/03/07 07:53:37 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.203 2010/03/07 09:05:19 msaitoh Exp $");
 
 #include "rnd.h"
 
@@ -137,7 +137,9 @@
 #define        WM_DEBUG_TX             0x02
 #define        WM_DEBUG_RX             0x04
 #define        WM_DEBUG_GMII           0x08
-int    wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK|WM_DEBUG_GMII;
+#define        WM_DEBUG_MANAGE         0x10
+int    wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII
+    | WM_DEBUG_MANAGE;
 
 #define        DPRINTF(x, y)   if (wm_debug & (x)) printf y
 #else
@@ -262,6 +264,7 @@
        int sc_bus_speed;               /* PCI/PCIX bus speed */
        int sc_pcixe_capoff;            /* PCI[Xe] capability register offset */
 
+       const struct wm_product *sc_wmp; /* Pointer to the wm_product entry */
        wm_chip_type sc_type;           /* MAC type */
        int sc_rev;                     /* MAC revision */
        wm_phy_type sc_phytype;         /* PHY type */
@@ -282,9 +285,9 @@
        /*
         * Software state for the transmit and receive descriptors.
         */
-       int                     sc_txnum;       /* must be a power of two */
-       struct wm_txsoft        sc_txsoft[WM_TXQUEUELEN_MAX];
-       struct wm_rxsoft        sc_rxsoft[WM_NRXDESC];
+       int sc_txnum;                   /* must be a power of two */
+       struct wm_txsoft sc_txsoft[WM_TXQUEUELEN_MAX];
+       struct wm_rxsoft sc_rxsoft[WM_NRXDESC];
 
        /*
         * Control data structures.
@@ -498,6 +501,8 @@
 static int     wm_ioctl(struct ifnet *, u_long, void *);
 static int     wm_init(struct ifnet *);
 static void    wm_stop(struct ifnet *, int);
+static bool    wm_suspend(device_t, const pmf_qual_t *);
+static bool    wm_resume(device_t, const pmf_qual_t *);
 
 static void    wm_reset(struct wm_softc *);
 static void    wm_rxdrain(struct wm_softc *);
@@ -575,16 +580,28 @@
 static int     wm_check_mng_mode_ich8lan(struct wm_softc *);
 static int     wm_check_mng_mode_82574(struct wm_softc *);
 static int     wm_check_mng_mode_generic(struct wm_softc *);
+static int     wm_enable_mng_pass_thru(struct wm_softc *);
 static int     wm_check_reset_block(struct wm_softc *);
 static void    wm_get_hw_control(struct wm_softc *);
 static int     wm_check_for_link(struct wm_softc *);
 static void    wm_kmrn_lock_loss_workaround_ich8lan(struct wm_softc *);
 static void    wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
+#ifdef WM_WOL
+static void    wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
+#endif
 static void    wm_hv_phy_workaround_ich8lan(struct wm_softc *);
 static void    wm_k1_gig_workaround_hv(struct wm_softc *, int);
 static void    wm_configure_k1_ich8lan(struct wm_softc *, int);
 static void    wm_set_pcie_completion_timeout(struct wm_softc *);
 static void    wm_reset_init_script_82575(struct wm_softc *);
+static void    wm_release_manageability(struct wm_softc *);
+static void    wm_release_hw_control(struct wm_softc *);
+static void    wm_get_wakeup(struct wm_softc *);
+#ifdef WM_WOL
+static void    wm_enable_phy_wakeup(struct wm_softc *);
+static void    wm_enable_wakeup(struct wm_softc *);
+#endif
+static void    wm_init_manageability(struct wm_softc *);
 
 CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -600,6 +617,7 @@
        int                     wmp_flags;
 #define        WMP_F_1000X             0x01
 #define        WMP_F_1000T             0x02
+#define        WMP_F_SERDES            0x04
 } wm_products[] = {
        { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82542,
          "Intel i82542 1000BASE-X Ethernet",
@@ -1082,12 +1100,13 @@
        uint8_t enaddr[ETHER_ADDR_LEN];
        uint16_t myea[ETHER_ADDR_LEN / 2], cfg1, cfg2, swdpin, io3;
        pcireg_t preg, memtype;
+       uint16_t eeprom_data, apme_mask;
        uint32_t reg;
 
        sc->sc_dev = self;
        callout_init(&sc->sc_tick_ch, 0);
 
-       wmp = wm_lookup(pa);
+       sc->sc_wmp = wmp = wm_lookup(pa);
        if (wmp == NULL) {
                printf("\n");
                panic("wm_attach: impossible");
@@ -1118,7 +1137,7 @@
 
        if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
            || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER))
-         sc->sc_flags |= WM_F_NEWQUEUE;
+               sc->sc_flags |= WM_F_NEWQUEUE;
 
        /* Set device properties (mactype) */
        dict = device_properties(sc->sc_dev);
@@ -1150,6 +1169,8 @@
                return;
        }
 
+       wm_get_wakeup(sc);
+
        /*
         * In addition, i82544 and later support I/O mapped indirect
         * register access.  It is not desirable (nor supported in
@@ -1638,6 +1659,58 @@
                }
        }
 
+       /* check for WM_F_WOL */
+       switch (sc->sc_type) {
+       case WM_T_82542_2_0:
+       case WM_T_82542_2_1:
+       case WM_T_82543:
+               /* dummy? */
+               eeprom_data = 0;
+               apme_mask = EEPROM_CFG3_APME;
+               break;
+       case WM_T_82544:
+               apme_mask = EEPROM_CFG2_82544_APM_EN;
+               eeprom_data = cfg2;
+               break;
+       case WM_T_82546:
+       case WM_T_82546_3:
+       case WM_T_82571:
+       case WM_T_82572:
+       case WM_T_82573:
+       case WM_T_82574:
+       case WM_T_82583:
+       case WM_T_80003:
+       default:
+               apme_mask = EEPROM_CFG3_APME;
+               wm_read_eeprom(sc, (sc->sc_funcid == 1) ? EEPROM_OFF_CFG3_PORTB
+                   : EEPROM_OFF_CFG3_PORTA, 1, &eeprom_data);
+               break;
+       case WM_T_82575:
+       case WM_T_82576:
+       case WM_T_82580:
+       case WM_T_82580ER:
+       case WM_T_ICH8:
+       case WM_T_ICH9:
+       case WM_T_ICH10:
+       case WM_T_PCH:
+               apme_mask = WUC_APME;
+               eeprom_data = CSR_READ(sc, WMREG_WUC);
+               break;
+       }
+
+       /* Check for WM_F_WOL flag after the setting of the EEPROM stuff */
+       if ((eeprom_data & apme_mask) != 0)
+               sc->sc_flags |= WM_F_WOL;
+#ifdef WM_DEBUG
+       if ((sc->sc_flags & WM_F_WOL) != 0)
+               printf("WOL\n");
+#endif
+
+       /*
+        * XXX need special handling for some multiple port cards
+        * to disable a paticular port.
+        */
+
        if (sc->sc_type >= WM_T_82544) {
                pn = prop_dictionary_get(dict, "i82543-swdpin");
                if (pn != NULL) {
@@ -1930,7 +2003,7 @@
            NULL, xname, "rx_macctl");
 #endif /* WM_EVENT_COUNTERS */
 
-       if (pmf_device_register(self, NULL, NULL))
+       if (pmf_device_register(self, wm_suspend, wm_resume))
                pmf_class_network_register(self, ifp);
        else
                aprint_error_dev(self, "couldn't establish power handler\n");
@@ -1980,9 +2053,7 @@
        pmf_device_deregister(self);
 
        /* Tell the firmware about the release */
-#if 0
        wm_release_manageability(sc);
-#endif
 
        mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
 
@@ -2025,9 +2096,7 @@
                sc->sc_ss = 0;
        }
 
-#if 0
        wm_release_hw_control(sc);
-#endif
 
        return 0;
 }
@@ -3990,6 +4059,9 @@
        if ((error = mii_ifmedia_change(&sc->sc_mii)) != 0)
                goto out;
 
+       /* Configure for OS presence */
+       wm_init_manageability(sc);
+
        /*
         * Set up the receive control register; we actually program
         * the register when we set the receive filter.  Use multicast
@@ -6729,6 +6801,36 @@
 }
 
 static int
+wm_enable_mng_pass_thru(struct wm_softc *sc)
+{
+       uint32_t manc, fwsm, factps;
+
+       if ((sc->sc_flags & WM_F_ASF_FIRMWARE_PRES) == 0)
+               return 0;
+
+       manc = CSR_READ(sc, WMREG_MANC);
+
+       DPRINTF(WM_DEBUG_MANAGE, ("%s: MANC (%08x)\n",
+               device_xname(sc->sc_dev), manc));
+       if (((manc & MANC_RECV_TCO_EN) == 0)
+           || ((manc & MANC_EN_MAC_ADDR_FILTER) == 0))
+               return 0;
+
+       if ((sc->sc_flags & WM_F_ARC_SUBSYS_VALID) != 0) {
+               fwsm = CSR_READ(sc, WMREG_FWSM);
+               factps = CSR_READ(sc, WMREG_FACTPS);
+               if (((factps & FACTPS_MNGCG) == 0)
+                   && ((fwsm & FWSM_MODE_MASK)
+                       == (MNG_ICH_IAMT_MODE << FWSM_MODE_SHIFT)))
+                       return 1;
+       } else if (((manc & MANC_SMBUS_EN) != 0)
+           && ((manc & MANC_ASF_EN) == 0))
+               return 1;
+
+       return 0;
+}
+
+static int
 wm_check_reset_block(struct wm_softc *sc)
 {
        uint32_t reg;
@@ -6771,19 +6873,13 @@
 
        switch (sc->sc_type) {
        case WM_T_82573:



Home | Main Index | Thread Index | Old Index