Module Name:    src
Committed By:   msaitoh
Date:           Fri May 25 23:37:38 UTC 2012

Modified Files:
        src/share/man/man4: wm.4
        src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h

Log Message:
Add support Intel I350 Ethernet.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/share/man/man4/wm.4
cvs rdiff -u -r1.227 -r1.228 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.46 -r1.47 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pci/if_wmvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/wm.4
diff -u src/share/man/man4/wm.4:1.21 src/share/man/man4/wm.4:1.22
--- src/share/man/man4/wm.4:1.21	Sat Apr 23 16:46:51 2011
+++ src/share/man/man4/wm.4	Fri May 25 23:37:37 2012
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wm.4,v 1.21 2011/04/23 16:46:51 tron Exp $
+.\"	$NetBSD: wm.4,v 1.22 2012/05/25 23:37:37 msaitoh Exp $
 .\"
 .\" Copyright 2002, 2003 Wasabi Systems, Inc.
 .\" All rights reserved.
@@ -120,11 +120,27 @@ Intel i82572 1000BASE-T Ethernet
 .It
 Intel i82573 1000BASE-T Ethernet
 .It
+Intel i82575 1000BASE-T Ethernet
+.It
+Intel i82576 Ethernet (Copper, Fiber)
+.It
+Intel i80003 Ethernet (Copper, Fiber)
+.It
 Intel i82801H (ICH8 LAN) 1000BASE-T Ethernet
 .It
 Intel i82801I (ICH9 LAN) 1000BASE-T Ethernet
 .It
-Intel i80003 1000BASE-T Ethernet
+Intel i82801J (ICH10 LAN) 1000BASE-T Ethernet
+.It
+Intel PCH 1000BASE-T Ethernet
+.It
+Intel PCH2 1000BASE-T Ethernet
+.It
+Intel 82580 Ethernet (Copper, Fiber)
+.It
+Intel 82583 1000BASE-T Ethernet
+.It
+Intel I350 Ethernet (Copper, Fiber)
 .El
 .Pp
 In addition to Intel's own

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.227 src/sys/dev/pci/if_wm.c:1.228
--- src/sys/dev/pci/if_wm.c:1.227	Thu Feb  2 19:43:05 2012
+++ src/sys/dev/pci/if_wm.c	Fri May 25 23:37:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.227 2012/02/02 19:43:05 tls Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.228 2012/05/25 23:37:38 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.227 2012/02/02 19:43:05 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.228 2012/05/25 23:37:38 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -603,6 +603,7 @@ static void	wm_enable_phy_wakeup(struct 
 static void	wm_enable_wakeup(struct wm_softc *);
 #endif
 static void	wm_init_manageability(struct wm_softc *);
+static void	wm_set_eee_i350(struct wm_softc *);
 
 CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
@@ -1001,6 +1002,20 @@ static const struct wm_product {
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_QUAD_FIBER,
 	  "82580 quad-1000BaseX Ethernet",
 	  WM_T_82580,		WMP_F_1000X },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I350_COPPER,
+	  "I350 Gigabit Network Connection",
+	  WM_T_I350,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I350_FIBER,
+	  "I350 Gigabit Fiber Network Connection",
+	  WM_T_I350,		WMP_F_1000X },
+#if 0
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I350_SERDES,
+	  "I350 Gigabit Backplane Connection",
+	  WM_T_I350,		WMP_F_SERDES },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_I350_SGMII,
+	  "I350 Gigabit Connection",
+	  WM_T_I350,		WMP_F_1000T },
+#endif
 	{ 0,			0,
 	  NULL,
 	  0,			0 },
@@ -1151,7 +1166,8 @@ wm_attach(device_t parent, device_t self
 	}
 
 	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_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
+	    || (sc->sc_type == WM_T_I350))
 		sc->sc_flags |= WM_F_NEWQUEUE;
 
 	/* Set device properties (mactype) */
@@ -1264,7 +1280,8 @@ wm_attach(device_t parent, device_t self
 	if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3)
 	    || (sc->sc_type ==  WM_T_82571) || (sc->sc_type == WM_T_80003)
 	    || (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_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
+	    || (sc->sc_type == WM_T_I350))
 		sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS)
 		    >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK;
 	else
@@ -1551,6 +1568,7 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 		/* SPI */
 		wm_set_spiaddrbits(sc);
@@ -1696,11 +1714,13 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
 	case WM_T_ICH10:
 	case WM_T_PCH:
 	case WM_T_PCH2:
+		/* XXX The funcid should be checked on some devices */
 		apme_mask = WUC_APME;
 		eeprom_data = CSR_READ(sc, WMREG_WUC);
 		break;
@@ -1818,6 +1838,7 @@ wm_attach(device_t parent, device_t self
 		case WM_T_82576:
 		case WM_T_82580:
 		case WM_T_82580ER:
+		case WM_T_I350:
 			reg = CSR_READ(sc, WMREG_CTRL_EXT);
 			switch (reg & CTRL_EXT_LINK_MODE_MASK) {
 			case CTRL_EXT_LINK_MODE_SGMII:
@@ -1878,6 +1899,7 @@ wm_attach(device_t parent, device_t self
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 	case WM_T_ICH9:
 	case WM_T_ICH10:
@@ -3114,18 +3136,24 @@ wm_rxintr(struct wm_softc *sc)
 
 		/*
 		 * Okay, we have the entire packet now.  The chip is
-		 * configured to include the FCS (not all chips can
-		 * be configured to strip it), so we need to trim it.
+		 * configured to include the FCS except I350
+		 * (not all chips can be configured to strip it),
+		 * so we need to trim it.
 		 * May need to adjust length of previous mbuf in the
 		 * chain if the current mbuf is too short.
+		 * For an eratta, the RCTL_SECRC bit in RCTL register
+		 * is always set in I350, so we don't trim it.
 		 */
-		if (m->m_len < ETHER_CRC_LEN) {
-			sc->sc_rxtail->m_len -= (ETHER_CRC_LEN - m->m_len);
-			m->m_len = 0;
-		} else {
-			m->m_len -= ETHER_CRC_LEN;
-		}
-		len = sc->sc_rxlen - ETHER_CRC_LEN;
+		if (sc->sc_type != WM_T_I350) {
+			if (m->m_len < ETHER_CRC_LEN) {
+				sc->sc_rxtail->m_len
+				    -= (ETHER_CRC_LEN - m->m_len);
+				m->m_len = 0;
+			} else
+				m->m_len -= ETHER_CRC_LEN;
+			len = sc->sc_rxlen - ETHER_CRC_LEN;
+		} else
+			len = sc->sc_rxlen;
 
 		WM_RXCHAIN_LINK(sc, m);
 
@@ -3448,6 +3476,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82571:
 	case WM_T_82572:
 	case WM_T_82575:	/* XXX need special handing for jumbo frames */
+	case WM_T_I350:
 	case WM_T_80003:
 		sc->sc_pba = PBA_32K;
 		break;
@@ -3499,7 +3528,8 @@ wm_reset(struct wm_softc *sc)
 	}
 
 	/* Set the completion timeout for interface */
-	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576))
+	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
+	    || (sc->sc_type == WM_T_I350))
 		wm_set_pcie_completion_timeout(sc);
 
 	/* Clear interrupt */
@@ -3622,6 +3652,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 	case WM_T_82583:
+	case WM_T_I350:
 	default:
 		/* Everything else can safely use the documented method. */
 		CSR_WRITE(sc, WMREG_CTRL, CSR_READ(sc, WMREG_CTRL) | CTRL_RST);
@@ -3681,6 +3712,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -3704,6 +3736,7 @@ wm_reset(struct wm_softc *sc)
 	case WM_T_82580:
 	case WM_T_82580ER:
 #endif
+	case WM_T_I350:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
 		if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
@@ -3712,7 +3745,8 @@ wm_reset(struct wm_softc *sc)
 			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_type == WM_T_82580ER)
+			    || (sc->sc_type == WM_T_I350))
 				wm_reset_init_script_82575(sc);
 		}
 		break;
@@ -3720,7 +3754,8 @@ wm_reset(struct wm_softc *sc)
 		break;
 	}
 
-	if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)) {
+	if ((sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
+	    || (sc->sc_type == WM_T_I350)) {
 		/* clear global device reset status bit */
 		CSR_WRITE(sc, WMREG_STATUS, STATUS_DEV_RST_SET);
 	}
@@ -3732,6 +3767,9 @@ wm_reset(struct wm_softc *sc)
 	/* reload sc_ctrl */
 	sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL);
 
+	if (sc->sc_type == WM_T_I350)
+		wm_set_eee_i350(sc);
+
 	/* dummy read from WUC */
 	if (sc->sc_type == WM_T_PCH)
 		reg = wm_gmii_hv_readreg(sc->sc_dev, 1, BM_WUC);
@@ -3772,7 +3810,7 @@ wm_init(struct ifnet *ifp)
 {
 	struct wm_softc *sc = ifp->if_softc;
 	struct wm_rxsoft *rxs;
-	int i, error = 0;
+	int i, j, trynum, error = 0;
 	uint32_t reg;
 
 	/*
@@ -3951,8 +3989,13 @@ wm_init(struct ifnet *ifp)
 	 * Clear out the VLAN table -- we don't use it (yet).
 	 */
 	CSR_WRITE(sc, WMREG_VET, 0);
+	if (sc->sc_type == WM_T_I350)
+		trynum = 10; /* Due to hw errata */
+	else
+		trynum = 1;
 	for (i = 0; i < WM_VLAN_TABSIZE; i++)
-		CSR_WRITE(sc, WMREG_VFTA + (i << 2), 0);
+		for (j = 0; j < trynum; j++)
+			CSR_WRITE(sc, WMREG_VFTA + (i << 2), 0);
 
 	/*
 	 * Set up flow-control parameters.
@@ -4140,6 +4183,13 @@ wm_init(struct ifnet *ifp)
 	sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_DPF
 	    | RCTL_MO(sc->sc_mchash_type);
 
+	/*
+	 * The I350 has a bug where it always strips the CRC whether
+	 * asked to or not. So ask for stripped CRC here and cope in rxeof
+	 */
+	if (sc->sc_type == WM_T_I350)
+		sc->sc_rctl |= RCTL_SECRC;
+
 	if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
 	    && (ifp->if_mtu > ETHERMTU)) {
 		sc->sc_rctl |= RCTL_LPE;
@@ -4295,6 +4345,7 @@ wm_get_auto_rd_done(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -4382,6 +4433,7 @@ wm_get_cfg_done(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 		if (sc->sc_type == WM_T_82571) {
 			/* Only 82571 shares port 0 */
 			mask = EEMNGCTL_CFGDONE_0;
@@ -4810,6 +4862,7 @@ wm_read_mac_addr(struct wm_softc *sc, ui
 	switch (sc->sc_type) {
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 		switch (sc->sc_funcid) {
 		case 0:
 			/* default value (== EEPROM_OFF_MACADDR) */
@@ -5420,6 +5473,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 		rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
 		break;
@@ -5490,6 +5544,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_82583:
 	case WM_T_80003:
 		/* generic reset */
@@ -5537,6 +5592,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_80003:
 		wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
 		break;
@@ -5577,6 +5633,7 @@ wm_gmii_reset(struct wm_softc *sc)
 	case WM_T_82576:
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 	case WM_T_82583:
 	case WM_T_80003:
 		/* null */
@@ -5718,7 +5775,8 @@ wm_gmii_mediainit(struct wm_softc *sc, p
 	    wm_gmii_mediastatus);
 
 	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_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
+	    || (sc->sc_type == WM_T_I350)) {
 		if ((sc->sc_flags & WM_F_SGMII) == 0) {
 			/* Attach only one port */
 			mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1,
@@ -7599,6 +7657,7 @@ wm_get_wakeup(struct wm_softc *sc)
 #if 0 /* XXX */
 	case WM_T_82580:
 	case WM_T_82580ER:
+	case WM_T_I350:
 #endif
 		if ((CSR_READ(sc, WMREG_FWSM) & FWSM_MODE_MASK) != 0)
 			sc->sc_flags |= WM_F_ARC_SUBSYS_VALID;
@@ -7769,3 +7828,27 @@ wm_resume(device_t self, const pmf_qual_
 
 	return true;
 }
+
+static void
+wm_set_eee_i350(struct wm_softc * sc)
+{
+	uint32_t ipcnfg, eeer;
+
+	ipcnfg = CSR_READ(sc, WMREG_IPCNFG);
+	eeer = CSR_READ(sc, WMREG_EEER);
+
+	if ((sc->sc_flags & WM_F_EEE) != 0) {
+		ipcnfg |= (IPCNFG_EEE_1G_AN | IPCNFG_EEE_100M_AN);
+		eeer |= (EEER_TX_LPI_EN | EEER_RX_LPI_EN
+		    | EEER_LPI_FC);
+	} else {
+		ipcnfg &= ~(IPCNFG_EEE_1G_AN | IPCNFG_EEE_100M_AN);
+		eeer &= ~(EEER_TX_LPI_EN | EEER_RX_LPI_EN
+		    | EEER_LPI_FC);
+	}
+
+	CSR_WRITE(sc, WMREG_IPCNFG, ipcnfg);
+	CSR_WRITE(sc, WMREG_EEER, eeer);
+	CSR_READ(sc, WMREG_IPCNFG); /* XXX flush? */
+	CSR_READ(sc, WMREG_EEER); /* XXX flush? */
+}

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.46 src/sys/dev/pci/if_wmreg.h:1.47
--- src/sys/dev/pci/if_wmreg.h:1.46	Tue Dec 20 21:27:29 2011
+++ src/sys/dev/pci/if_wmreg.h	Fri May 25 23:37:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.46 2011/12/20 21:27:29 dyoung Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.47 2012/05/25 23:37:38 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -893,6 +893,22 @@ struct livengood_tcpip_ctxdesc {
 #define	PHY_CTRL_NOND0A_GBE_DIS	(1 << 3)
 #define	PHY_CTRL_GBE_DIS	(1 << 4)
 
+/* Energy Efficient Ethernet "EEE" registers */
+#define WMREG_LTRC	0x01a0	/* Latency Tolerance Reportiong Control */
+#define WMREG_EEER	0x0e30	/* Energy Efficiency Ethernet "EEE" */
+#define EEER_TX_LPI_EN		0x00010000 /* EEER Tx LPI Enable */
+#define EEER_RX_LPI_EN		0x00020000 /* EEER Rx LPI Enable */
+#define EEER_LPI_FC		0x00040000 /* EEER Ena on Flow Cntrl */
+#define EEER_EEER_NEG		0x20000000 /* EEER capability nego */
+#define EEER_EEER_RX_LPI_STATUS	0x40000000 /* EEER Rx in LPI state */
+#define EEER_EEER_TX_LPI_STATUS	0x80000000 /* EEER Tx in LPI state */
+#define WMREG_EEE_SU	0x0e34	/* EEE Setup */
+#define WMREG_IPCNFG	0x0e38	/* Internal PHY Configuration */
+#define IPCNFG_EEE_100M_AN	0x00000004 /* IPCNFG EEE Ena 100M AN */
+#define IPCNFG_EEE_1G_AN	0x00000008 /* IPCNFG EEE Ena 1G AN */
+#define WMREG_TLPIC	0x4148	/* EEE Tx LPI Count */
+#define WMREG_RLPIC	0x414c	/* EEE Rx LPI Count */
+
 /* ich8 flash control */
 #define ICH_FLASH_COMMAND_TIMEOUT            5000    /* 5000 uSecs - adjusted */
 #define ICH_FLASH_ERASE_TIMEOUT              3000000 /* Up to 3 seconds - worst case */

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.12 src/sys/dev/pci/if_wmvar.h:1.13
--- src/sys/dev/pci/if_wmvar.h:1.12	Fri May 20 01:51:36 2011
+++ src/sys/dev/pci/if_wmvar.h	Fri May 25 23:37:38 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.12 2011/05/20 01:51:36 msaitoh Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.13 2012/05/25 23:37:38 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -93,6 +93,7 @@
 #define WM_F_HAS_AMT		0x00040000
 #define WM_F_HAS_MANAGE		0x00080000
 #define WM_F_WOL		0x00100000
+#define WM_F_EEE		0x00200000  /* Energy Efficiency Ethernet */
 
 typedef enum {
 	WM_T_unknown		= 0,
@@ -118,6 +119,7 @@ typedef enum {
 	WM_T_82576,			/* i82576 */
 	WM_T_82580,			/* i82580 */
 	WM_T_82580ER,			/* i82580ER */
+	WM_T_I350,			/* I350 */
 	WM_T_80003,			/* i80003 */
 	WM_T_ICH8,			/* ICH8 LAN */
 	WM_T_ICH9,			/* ICH9 LAN */

Reply via email to