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