Module Name:    src
Committed By:   msaitoh
Date:           Tue Feb 16 15:17:18 UTC 2010

Modified Files:
        src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h

Log Message:
Add support for 82575, 82576 and 82580(ER).
- Apply the patch for 82575 from Wolfgang Stukenbrock (PR#42422). We use
  only one RX ring and with the legacy mode.
- Add support for 82576.
- Partial support for 82580.
- Partial support for the serdes systems.


To generate a diff of this commit:
cvs rdiff -u -r1.198 -r1.199 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.8 -r1.9 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/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.198 src/sys/dev/pci/if_wm.c:1.199
--- src/sys/dev/pci/if_wm.c:1.198	Tue Feb 16 10:06:19 2010
+++ src/sys/dev/pci/if_wm.c	Tue Feb 16 15:17:17 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.198 2010/02/16 10:06:19 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.199 2010/02/16 15:17:17 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.198 2010/02/16 10:06:19 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.199 2010/02/16 15:17:17 msaitoh Exp $");
 
 #include "rnd.h"
 
@@ -231,6 +231,13 @@
 
 #define WM_LINKUP_TIMEOUT	50
 
+static uint16_t swfwphysem[] = {
+	SWFW_PHY0_SM,
+	SWFW_PHY1_SM,
+	SWFW_PHY2_SM,
+	SWFW_PHY3_SM
+};
+
 /*
  * Software state per device.
  */
@@ -243,31 +250,33 @@
 	bus_space_tag_t sc_flasht;	/* flash registers space tag */
 	bus_space_handle_t sc_flashh;	/* flash registers space handle */
 	bus_dma_tag_t sc_dmat;		/* bus DMA tag */
+	bus_dmamap_t sc_cddmamap;	/* control data DMA map */
+#define	sc_cddma	sc_cddmamap->dm_segs[0].ds_addr
+
 	struct ethercom sc_ethercom;	/* ethernet common data */
+	struct mii_data sc_mii;		/* MII/media information */
+
 	pci_chipset_tag_t sc_pc;
 	pcitag_t sc_pcitag;
+	int sc_bus_speed;		/* PCI/PCIX bus speed */
+	int sc_pcixe_capoff;		/* PCI[Xe] capability register offset */
 
 	wm_chip_type sc_type;		/* MAC type */
 	int sc_rev;			/* MAC revision */
 	wm_phy_type sc_phytype;		/* PHY type */
+	int sc_funcid;			/* unit number of the chip (0 to 3) */
 	int sc_flags;			/* flags; see below */
 	int sc_if_flags;		/* last if_flags */
-	int sc_bus_speed;		/* PCI/PCIX bus speed */
-	int sc_pcix_offset;		/* PCIX capability register offset */
 	int sc_flowflags;		/* 802.3x flow control flags */
+	int sc_align_tweak;
 
 	void *sc_ih;			/* interrupt cookie */
-
-	int sc_ee_addrbits;		/* EEPROM address bits */
-
-	struct mii_data sc_mii;		/* MII/media information */
-
 	callout_t sc_tick_ch;		/* tick callout */
 
-	bus_dmamap_t sc_cddmamap;	/* control data DMA map */
-#define	sc_cddma	sc_cddmamap->dm_segs[0].ds_addr
-
-	int		sc_align_tweak;
+	int sc_ee_addrbits;		/* EEPROM address bits */
+	int sc_ich8_flash_base;
+	int sc_ich8_flash_bank_size;
+	int sc_nvm_k1_enabled;
 
 	/*
 	 * Software state for the transmit and receive descriptors.
@@ -364,9 +373,6 @@
 #if NRND > 0
 	rndsource_element_t rnd_source;	/* random source */
 #endif
-	int sc_ich8_flash_base;
-	int sc_ich8_flash_bank_size;
-	int sc_nvm_k1_enabled;
 };
 
 #define	WM_RXCHAIN_RESET(sc)						\
@@ -523,6 +529,8 @@
 static void	wm_gmii_bm_writereg(device_t, int, int, int);
 static int	wm_gmii_hv_readreg(device_t, int, int);
 static void	wm_gmii_hv_writereg(device_t, int, int, int);
+static int	wm_sgmii_readreg(device_t, int, int);
+static void	wm_sgmii_writereg(device_t, int, int, int);
 
 static void	wm_gmii_statchg(device_t);
 
@@ -533,7 +541,7 @@
 static int	wm_kmrn_readreg(struct wm_softc *, int);
 static void	wm_kmrn_writereg(struct wm_softc *, int, int);
 
-static void	wm_set_spiaddrsize(struct wm_softc *);
+static void	wm_set_spiaddrbits(struct wm_softc *);
 static int	wm_match(device_t, cfdata_t, void *);
 static void	wm_attach(device_t, device_t, void *);
 static int	wm_is_onboard_nvm_eeprom(struct wm_softc *);
@@ -566,6 +574,8 @@
 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 *);
 
 CFATTACH_DECL_NEW(wm, sizeof(struct wm_softc),
     wm_match, wm_attach, NULL, NULL);
@@ -882,6 +892,72 @@
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_PCH_D_DC,
 	  "PCH LAN (82578DC) Controller",
 	  WM_T_PCH,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82575EB_COPPER,
+	  "82575EB dual-1000baseT Ethernet",
+	  WM_T_82575,		WMP_F_1000T },
+#if 0
+	/*
+	 * not sure if WMP_F_1000X or WMP_F_SERDES - we do not have it - so
+	 * disabled for now ...
+	 */
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES,
+	  "82575EB dual-1000baseX Ethernet (SERDES)",
+	  WM_T_82575,		WMP_F_SERDES },
+#endif
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER,
+	  "82575GB quad-1000baseT Ethernet",
+	  WM_T_82575,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM,
+	  "82575GB quad-1000baseT Ethernet (PM)",
+	  WM_T_82575,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_COPPER,
+	  "82576 1000BaseT Ethernet",
+	  WM_T_82576,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_FIBER,
+	  "82576 1000BaseX Ethernet",
+	  WM_T_82576,		WMP_F_1000X },
+#if 0
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_SERDES,
+	  "82576 gigabit Ethernet (SERDES)",
+	  WM_T_82576,		WMP_F_SERDES },
+#endif
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_QUAD_COPPER,
+	  "82576 quad-1000BaseT Ethernet",
+	  WM_T_82576,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_NS,
+	  "82576 gigabit Ethernet",
+	  WM_T_82576,		WMP_F_1000T },
+#if 0
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_NS_SERDES,
+	  "82576 gigabit Ethernet (SERDES)",
+	  WM_T_82576,		WMP_F_SERDES },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82576_SERDES_QUAD,
+	  "82576 quad-gigabit Ethernet (SERDES)",
+	  WM_T_82576,		WMP_F_SERDES },
+#endif
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_COPPER,
+	  "82580 1000BaseT Ethernet",
+	  WM_T_82580,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_FIBER,
+	  "82580 1000BaseX Ethernet",
+	  WM_T_82580,		WMP_F_1000X },
+#if 0
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_SERDES,
+	  "82580 1000BaseT Ethernet (SERDES)",
+	  WM_T_82580,		WMP_F_SERDES },
+#endif
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_SGMII,
+	  "82580 gigabit Ethernet (SGMII)",
+	  WM_T_82580,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_COPPER_DUAL,
+	  "82580 dual-1000BaseT Ethernet",
+	  WM_T_82580,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_ER,
+	  "82580 1000BaseT Ethernet",
+	  WM_T_82580ER,		WMP_F_1000T },
+	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82580_ER_DUAL,
+	  "82580 dual-1000BaseT Ethernet",
+	  WM_T_82580ER,		WMP_F_1000T },
 	{ 0,			0,
 	  NULL,
 	  0,			0 },
@@ -910,6 +986,28 @@
 }
 
 static inline void
+wm_82575_write_8bit_ctlr_reg(struct wm_softc *sc, uint32_t reg, uint32_t off,
+    uint32_t data)
+{
+	uint32_t regval;
+	int i;
+
+	regval = (data & SCTL_CTL_DATA_MASK) | (off << SCTL_CTL_ADDR_SHIFT);
+
+	CSR_WRITE(sc, reg, regval);
+
+	for (i = 0; i < SCTL_CTL_POLL_TIMEOUT; i++) {
+		delay(5);
+		if (CSR_READ(sc, reg) & SCTL_CTL_READY)
+			break;
+	}
+	if (i == SCTL_CTL_POLL_TIMEOUT) {
+		aprint_error("%s: WARNING: i82575 reg 0x%08x setup did not indicate ready\n",
+		    device_xname(sc->sc_dev), reg);
+	}
+}
+
+static inline void
 wm_set_dma_addr(volatile wiseman_addr_t *wa, bus_addr_t v)
 {
 	wa->wa_low = htole32(v & 0xffffffffU);
@@ -920,7 +1018,7 @@
 }
 
 static void
-wm_set_spiaddrsize(struct wm_softc *sc)
+wm_set_spiaddrbits(struct wm_softc *sc)
 {
 	uint32_t reg;
 
@@ -1010,6 +1108,10 @@
 			sc->sc_type = WM_T_82542_2_0;
 	}
 
+	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;
+
 	/* Set device properties (mactype) */
 	dict = device_properties(sc->sc_dev);
 	prop_dictionary_set_uint32(dict, "mactype", sc->sc_type);
@@ -1110,6 +1212,17 @@
 	aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
 
 	/*
+	 * Check the function ID (unit number of the chip).
+	 */
+	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_funcid = (CSR_READ(sc, WMREG_STATUS)
+		    >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK;
+	else
+		sc->sc_funcid = 0;
+
+	/*
 	 * Determine a few things about the bus we're connected to.
 	 */
 	if (sc->sc_type < WM_T_82543) {
@@ -1135,8 +1248,15 @@
 		sc->sc_flags |= WM_F_PCIE;
 		if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9)
 		    && (sc->sc_type != WM_T_ICH10)
-		    && (sc->sc_type != WM_T_PCH))
+		    && (sc->sc_type != WM_T_PCH)) {
 			sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
+			/* ICH* and PCH have no PCIe capability registers */
+			if (pci_get_capability(pa->pa_pc, pa->pa_tag,
+				PCI_CAP_PCIEXPRESS, &sc->sc_pcixe_capoff,
+				NULL) == 0)
+				aprint_error_dev(sc->sc_dev,
+				    "unable to find PCIe capability\n");
+		}
 		aprint_verbose_dev(sc->sc_dev, "PCI-Express bus\n");
 	} else {
 		reg = CSR_READ(sc, WMREG_STATUS);
@@ -1147,7 +1267,7 @@
 
 			sc->sc_flags |= WM_F_PCIX;
 			if (pci_get_capability(pa->pa_pc, pa->pa_tag,
-				PCI_CAP_PCIX, &sc->sc_pcix_offset, NULL) == 0)
+				PCI_CAP_PCIX, &sc->sc_pcixe_capoff, NULL) == 0)
 				aprint_error_dev(sc->sc_dev,
 				    "unable to find PCIX capability\n");
 			else if (sc->sc_type != WM_T_82545_3 &&
@@ -1158,9 +1278,9 @@
 				 * incorrectly.
 				 */
 				pcix_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag,
-				    sc->sc_pcix_offset + PCI_PCIX_CMD);
+				    sc->sc_pcixe_capoff + PCI_PCIX_CMD);
 				pcix_sts = pci_conf_read(pa->pa_pc, pa->pa_tag,
-				    sc->sc_pcix_offset + PCI_PCIX_STATUS);
+				    sc->sc_pcixe_capoff + PCI_PCIX_STATUS);
 
 				bytecnt =
 				    (pcix_cmd & PCI_PCIX_CMD_BYTECNT_MASK) >>
@@ -1176,7 +1296,7 @@
 					    ~PCI_PCIX_CMD_BYTECNT_MASK) |
 					   (maxb << PCI_PCIX_CMD_BYTECNT_SHIFT);
 					pci_conf_write(pa->pa_pc, pa->pa_tag,
-					    sc->sc_pcix_offset + PCI_PCIX_CMD,
+					    sc->sc_pcixe_capoff + PCI_PCIX_CMD,
 					    pcix_cmd);
 				}
 			}
@@ -1348,7 +1468,7 @@
 		reg = CSR_READ(sc, WMREG_EECD);
 		if (reg & EECD_EE_TYPE) {
 			/* SPI */
-			wm_set_spiaddrsize(sc);
+			wm_set_spiaddrbits(sc);
 		} else
 			/* Microwire */
 			sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6;
@@ -1357,7 +1477,7 @@
 	case WM_T_82571:
 	case WM_T_82572:
 		/* SPI */
-		wm_set_spiaddrsize(sc);
+		wm_set_spiaddrbits(sc);
 		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
 		break;
 	case WM_T_82573:
@@ -1367,25 +1487,21 @@
 			sc->sc_flags |= WM_F_EEPROM_FLASH;
 		else {
 			/* SPI */
-			wm_set_spiaddrsize(sc);
+			wm_set_spiaddrbits(sc);
 		}
 		sc->sc_flags |= WM_F_EEPROM_EERDEEWR;
 		break;
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_80003:
 		/* SPI */
-		wm_set_spiaddrsize(sc);
+		wm_set_spiaddrbits(sc);
 		sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC;
 		break;
 	case WM_T_ICH8:
 	case WM_T_ICH9:
-		/* Check whether EEPROM is present or not */
-		if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
-			/* Not found */
-			aprint_error_dev(sc->sc_dev,
-			    "EEPROM PRESENT bit isn't set\n");
-			sc->sc_flags |= WM_F_EEPROM_INVALID;
-		}
-		/* FALLTHROUGH */
 	case WM_T_ICH10:
 	case WM_T_PCH:
 		/* FLASH */
@@ -1400,10 +1516,10 @@
 		reg = ICH8_FLASH_READ32(sc, ICH_FLASH_GFPREG);
 		sc->sc_ich8_flash_base = (reg & ICH_GFPREG_BASE_MASK) *
 						ICH_FLASH_SECTOR_SIZE;
-		sc->sc_ich8_flash_bank_size = 
-			((reg >> 16) & ICH_GFPREG_BASE_MASK) + 1;
+		sc->sc_ich8_flash_bank_size =
+		    ((reg >> 16) & ICH_GFPREG_BASE_MASK) + 1;
 		sc->sc_ich8_flash_bank_size -=
-			(reg & ICH_GFPREG_BASE_MASK);
+		    (reg & ICH_GFPREG_BASE_MASK);
 		sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
 		sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t);
 		break;
@@ -1475,9 +1591,10 @@
 	 * Toggle the LSB of the MAC address on the second port
 	 * of the dual port controller.
 	 */
-	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) {
-		if ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1)
+	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)) {
+		if (sc->sc_funcid == 1)
 			enaddr[5] ^= 1;
 	}
 
@@ -1588,7 +1705,7 @@
 	}
 
 	/*
-	 * Determine if we're TBI or GMII mode, and initialize the
+	 * Determine if we're TBI,GMII or SGMII mode, and initialize the
 	 * media structures accordingly.
 	 */
 	if (sc->sc_type == WM_T_ICH8 || sc->sc_type == WM_T_ICH9
@@ -1604,10 +1721,41 @@
 			    "WARNING: TBIMODE set on 1000BASE-T product!\n");
 		wm_tbi_mediainit(sc);
 	} else {
-		if (wmp->wmp_flags & WMP_F_1000X)
-			aprint_error_dev(sc->sc_dev,
-			    "WARNING: TBIMODE clear on 1000BASE-X product!\n");
-		wm_gmii_mediainit(sc, wmp->wmp_product);
+		switch (sc->sc_type) {
+		case WM_T_82575:
+		case WM_T_82576:
+		case WM_T_82580:
+		case WM_T_82580ER:
+			reg = CSR_READ(sc, WMREG_CTRL_EXT);
+			switch (reg & CTRL_EXT_LINK_MODE_MASK) {
+			case CTRL_EXT_LINK_MODE_SGMII:
+				aprint_verbose_dev(sc->sc_dev, "SGMII\n");
+				sc->sc_flags |= WM_F_SGMII;
+				CSR_WRITE(sc, WMREG_CTRL_EXT,
+				    reg | CTRL_EXT_I2C_ENA);
+				wm_gmii_mediainit(sc, wmp->wmp_product);
+				break;
+			case CTRL_EXT_LINK_MODE_1000KX:
+			case CTRL_EXT_LINK_MODE_PCIE_SERDES:
+				aprint_verbose_dev(sc->sc_dev, "1000KX or SERDES\n");
+				CSR_WRITE(sc, WMREG_CTRL_EXT,
+				    reg | CTRL_EXT_I2C_ENA);
+				panic("not supported yet\n");
+				break;
+			case CTRL_EXT_LINK_MODE_GMII:
+			default:
+				CSR_WRITE(sc, WMREG_CTRL_EXT,
+				    reg & ~CTRL_EXT_I2C_ENA);
+				wm_gmii_mediainit(sc, wmp->wmp_product);
+				break;
+			}
+			break;
+		default:
+			if (wmp->wmp_flags & WMP_F_1000X)
+				aprint_error_dev(sc->sc_dev,
+				    "WARNING: TBIMODE clear on 1000BASE-X product!\n");
+			wm_gmii_mediainit(sc, wmp->wmp_product);
+		}
 	}
 
 	ifp = &sc->sc_ethercom.ec_if;
@@ -1634,6 +1782,10 @@
 	case WM_T_82571:
 	case WM_T_82572:
 	case WM_T_82574:
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_80003:
 	case WM_T_ICH9:
 	case WM_T_ICH10:
@@ -3108,7 +3260,7 @@
 wm_reset(struct wm_softc *sc)
 {
 	int phy_reset = 0;
-	uint32_t reg, func, mask;
+	uint32_t reg, mask;
 	int i;
 
 	/*
@@ -3129,9 +3281,17 @@
 		break;
 	case WM_T_82571:
 	case WM_T_82572:
+	case WM_T_82575:	/* XXX need special handing for jumbo frames */
 	case WM_T_80003:
 		sc->sc_pba = PBA_32K;
 		break;
+	case WM_T_82580:
+	case WM_T_82580ER:
+		sc->sc_pba = PBA_35K;
+		break;
+	case WM_T_82576:
+		sc->sc_pba = PBA_64K;
+		break;
 	case WM_T_82573:
 		sc->sc_pba = PBA_12K;
 		break;
@@ -3155,6 +3315,7 @@
 	}
 	CSR_WRITE(sc, WMREG_PBA, sc->sc_pba);
 
+	/* Prevent the PCI-E bus from sticking */
 	if (sc->sc_flags & WM_F_PCIE) {
 		int timeout = 800;
 
@@ -3168,14 +3329,19 @@
 		}
 	}
 
-	/* clear interrupt */
+	/* Set the completion timeout for interface */
+	if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576))
+		wm_set_pcie_completion_timeout(sc);
+
+	/* Clear interrupt */
 	CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
 
 	/* Stop the transmit and receive processes. */
 	CSR_WRITE(sc, WMREG_RCTL, 0);
 	CSR_WRITE(sc, WMREG_TCTL, TCTL_PSP);
+	sc->sc_rctl &= ~RCTL_EN;
 
-	/* set_tbi_sbp_82543() */
+	/* XXX set_tbi_sbp_82543() */
 
 	delay(10*1000);
 
@@ -3241,8 +3407,7 @@
 		CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST);
 		break;
 	case WM_T_80003:
-		func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1;
-		mask = func ? SWFW_PHY1_SM : SWFW_PHY0_SM;
+		mask = swfwphysem[sc->sc_funcid];
 		reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST;
 		wm_get_swfw_semaphore(sc, mask);
 		CSR_WRITE(sc, WMREG_CTRL, reg);
@@ -3280,6 +3445,8 @@
 	case WM_T_82572:
 	case WM_T_82573:
 	case WM_T_82574:
+	case WM_T_82575:
+	case WM_T_82576:
 	case WM_T_82583:
 	default:
 		/* Everything else can safely use the documented method. */
@@ -3336,6 +3503,8 @@
 		    || (sc->sc_type == WM_T_82583))
 			delay(25*1000);
 		break;
+	case WM_T_82575:
+	case WM_T_82576:
 	case WM_T_80003:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -3350,6 +3519,28 @@
 		panic("%s: unknown type\n", __func__);
 	}
 
+	/* Check whether EEPROM is present or not */
+	switch (sc->sc_type) {
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_ICH8:
+	case WM_T_ICH9:
+		if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) {
+			/* Not found */
+			sc->sc_flags |= WM_F_EEPROM_INVALID;
+			if (sc->sc_type == WM_T_82575) /* 82575 only */
+				wm_reset_init_script_82575(sc);
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* Clear any pending interrupt events. */
+	CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
+	reg = CSR_READ(sc, WMREG_ICR);
+
 	/* reload sc_ctrl */
 	sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL);
 
@@ -3364,18 +3555,10 @@
 	if (sc->sc_type == WM_T_PCH)
 		CSR_WRITE(sc, WMREG_CRC_OFFSET, 0x65656565);
 
-#if 0
-	for (i = 0; i < 1000; i++) {
-		if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0) {
-			return;
-		}
-		delay(20);
-	}
+	if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+		CSR_WRITE(sc, WMREG_WUC, 0);
 
-	if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST)
-		log(LOG_ERR, "%s: reset failed to complete\n",
-		    device_xname(sc->sc_dev));
-#endif
+	/* XXX need special handling for 82580 */
 }
 
 /*
@@ -3471,10 +3654,16 @@
 		CSR_WRITE(sc, WMREG_TIDV, 375);		/* ITR / 4 */
 		CSR_WRITE(sc, WMREG_TADV, 375);		/* should be same */
 
-		CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
-		    TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
-		CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
-		    RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1));
+		if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+			CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_QUEUE_ENABLE
+			    | TXDCTL_PTHRESH(0) | TXDCTL_HTHRESH(0)
+			    | TXDCTL_WTHRESH(0));
+		else {
+			CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
+			    TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
+			CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
+			    RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1));
+		}
 	}
 	CSR_WRITE(sc, WMREG_TQSA_LO, 0);
 	CSR_WRITE(sc, WMREG_TQSA_HI, 0);
@@ -3508,10 +3697,21 @@
 		CSR_WRITE(sc, WMREG_RDBAH, WM_CDRXADDR_HI(sc, 0));
 		CSR_WRITE(sc, WMREG_RDBAL, WM_CDRXADDR_LO(sc, 0));
 		CSR_WRITE(sc, WMREG_RDLEN, sizeof(sc->sc_rxdescs));
-		CSR_WRITE(sc, WMREG_RDH, 0);
-		CSR_WRITE(sc, WMREG_RDT, 0);
-		CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD);	/* ITR/4 */
-		CSR_WRITE(sc, WMREG_RADV, 375);		/* MUST be same */
+		if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
+			CSR_WRITE(sc, WMREG_EITR(0), 450);
+			if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1))
+				panic("%s: MCLBYTES %d unsupported for i2575 or higher\n", __func__, MCLBYTES);
+			CSR_WRITE(sc, WMREG_SRRCTL, SRRCTL_DESCTYPE_LEGACY
+			    | (MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT));
+			CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE
+			    | RXDCTL_PTHRESH(16) | RXDCTL_HTHRESH(8)
+			    | RXDCTL_WTHRESH(1));
+		} else {
+			CSR_WRITE(sc, WMREG_RDH, 0);
+			CSR_WRITE(sc, WMREG_RDT, 0);
+			CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD);	/* ITR/4 */
+			CSR_WRITE(sc, WMREG_RADV, 375);		/* MUST be same */
+		}
 	}
 	for (i = 0; i < WM_NRXDESC; i++) {
 		rxs = &sc->sc_rxsoft[i];
@@ -3527,8 +3727,10 @@
 				wm_rxdrain(sc);
 				goto out;
 			}
-		} else
-			WM_INIT_RXDESC(sc, i);
+		} else {
+			if ((sc->sc_flags & WM_F_NEWQUEUE) == 0)
+				WM_INIT_RXDESC(sc, i);
+		}
 	}
 	sc->sc_rxptr = 0;
 	sc->sc_rxdiscard = 0;
@@ -3720,8 +3922,11 @@
 	    | RCTL_MO(sc->sc_mchash_type);
 
 	if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
-	    && (ifp->if_mtu > ETHERMTU))
-			sc->sc_rctl |= RCTL_LPE;
+	    && (ifp->if_mtu > ETHERMTU)) {
+		sc->sc_rctl |= RCTL_LPE;
+		if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+			CSR_WRITE(sc, WMREG_RLPML, ETHER_MAX_LEN_JUMBO);
+	}
 
 	if (MCLBYTES == 2048) {
 		sc->sc_rctl |= RCTL_2k;
@@ -3748,6 +3953,11 @@
 	/* Set the receive filter. */
 	wm_set_filter(sc);
 
+	/* On 575 and later set RDT only if RX enabled... */
+	if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
+		for (i = 0; i < WM_NRXDESC; i++)
+			WM_INIT_RXDESC(sc, i);
+
 	/* Start the one second link check clock. */
 	callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
 
@@ -3815,6 +4025,7 @@
 	/* Stop the transmit and receive processes. */
 	CSR_WRITE(sc, WMREG_TCTL, 0);
 	CSR_WRITE(sc, WMREG_RCTL, 0);
+	sc->sc_rctl &= ~RCTL_EN;
 
 	/*
 	 * Clear the interrupt mask to ensure the device cannot assert its
@@ -3841,6 +4052,11 @@
 
 	if (disable)
 		wm_rxdrain(sc);
+
+#if 0 /* notyet */
+	if (sc->sc_type >= WM_T_82544)
+		CSR_WRITE(sc, WMREG_WUC, 0);
+#endif
 }
 
 void
@@ -3855,6 +4071,8 @@
 	case WM_T_82573:
 	case WM_T_82574:
 	case WM_T_82583:
+	case WM_T_82575:
+	case WM_T_82576:
 	case WM_T_80003:
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -3907,7 +4125,6 @@
 void
 wm_get_cfg_done(struct wm_softc *sc)
 {
-	int func = 0;
 	int mask;
 	uint32_t reg;
 	int i;
@@ -3938,12 +4155,10 @@
 	case WM_T_80003:
 	case WM_T_82571:
 	case WM_T_82572:
-		if (sc->sc_type == WM_T_80003)
-			func = (CSR_READ(sc, WMREG_STATUS)
-			    >> STATUS_FUNCID_SHIFT) & 1;
-		else
-			func = 0; /* XXX Is it true for 82571? */
-		mask = (func == 1) ? EEMNGCTL_CFGDONE_1 : EEMNGCTL_CFGDONE_0;
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+		mask = EEMNGCTL_CFGDONE_0 << sc->sc_funcid;
 		for (i = 0; i < WM_PHY_CFG_TIMEOUT; i++) {
 			if (CSR_READ(sc, WMREG_EEMNGCTL) & mask)
 				break;
@@ -4367,7 +4582,11 @@
 	bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
 	    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
 
-	WM_INIT_RXDESC(sc, idx);
+	if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
+		if ((sc->sc_rctl & RCTL_EN) != 0)
+			WM_INIT_RXDESC(sc, idx);
+	} else 
+		WM_INIT_RXDESC(sc, idx);
 
 	return 0;
 }
@@ -4826,7 +5045,6 @@
 wm_gmii_reset(struct wm_softc *sc)
 {
 	uint32_t reg;
-	int func = 0; /* XXX gcc */
 	int rv;
 
 	/* get phy semaphore */
@@ -4839,10 +5057,12 @@
 		 /* XXX should get sw semaphore, too */
 		rv = wm_get_swsm_semaphore(sc);
 		break;
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_80003:
-		func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1;
-		rv = wm_get_swfw_semaphore(sc,
-		    func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+		rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
 		break;
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -4906,6 +5126,10 @@
 	case WM_T_82572:
 	case WM_T_82573:
 	case WM_T_82574:
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_82583:
 	case WM_T_80003:
 		/* generic reset */
@@ -4948,8 +5172,12 @@
 		 /* XXX sould put sw semaphore, too */
 		wm_put_swsm_semaphore(sc);
 		break;
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_80003:
-		wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+		wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
 		break;
 	case WM_T_ICH8:
 	case WM_T_ICH9:
@@ -4983,6 +5211,10 @@
 	case WM_T_82572:
 	case WM_T_82573:
 	case WM_T_82574:
+	case WM_T_82575:
+	case WM_T_82576:
+	case WM_T_82580:
+	case WM_T_82580ER:
 	case WM_T_82583:
 	case WM_T_80003:
 		/* null */
@@ -5088,7 +5320,10 @@
 		sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
 		break;
 	default:
-		if (sc->sc_type >= WM_T_80003) {
+		if ((sc->sc_flags & WM_F_SGMII) != 0) {
+			sc->sc_mii.mii_readreg = wm_sgmii_readreg;
+			sc->sc_mii.mii_writereg = wm_sgmii_writereg;
+		} else if (sc->sc_type >= WM_T_80003) {
 			sc->sc_mii.mii_readreg = wm_gmii_i80003_readreg;
 			sc->sc_mii.mii_writereg = wm_gmii_i80003_writereg;
 		} else if (sc->sc_type >= WM_T_82544) {
@@ -5378,13 +5613,14 @@
 wm_gmii_i80003_readreg(device_t self, int phy, int reg)
 {
 	struct wm_softc *sc = device_private(self);
-	int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+	int sem;
 	int rv;
 
 	if (phy != 1) /* only one PHY on kumeran bus */
 		return 0;
 
-	if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+	sem = swfwphysem[sc->sc_funcid];
+	if (wm_get_swfw_semaphore(sc, sem)) {
 		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
 		    __func__);
 		return 0;
@@ -5402,7 +5638,7 @@
 	rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS);
 	delay(200);
 
-	wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+	wm_put_swfw_semaphore(sc, sem);
 	return rv;
 }
 
@@ -5417,12 +5653,13 @@
 wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val)
 {
 	struct wm_softc *sc = device_private(self);
-	int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+	int sem;
 
 	if (phy != 1) /* only one PHY on kumeran bus */
 		return;
 
-	if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+	sem = swfwphysem[sc->sc_funcid];
+	if (wm_get_swfw_semaphore(sc, sem)) {
 		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
 		    __func__);
 		return;
@@ -5440,7 +5677,7 @@
 	wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val);
 	delay(200);
 
-	wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+	wm_put_swfw_semaphore(sc, sem);
 }
 
 /*
@@ -5454,10 +5691,11 @@
 wm_gmii_bm_readreg(device_t self, int phy, int reg)
 {
 	struct wm_softc *sc = device_private(self);
-	int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+	int sem;
 	int rv;
 
-	if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+	sem = swfwphysem[sc->sc_funcid];
+	if (wm_get_swfw_semaphore(sc, sem)) {
 		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
 		    __func__);
 		return 0;
@@ -5474,7 +5712,7 @@
 	}
 
 	rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS);
-	wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+	wm_put_swfw_semaphore(sc, sem);
 	return rv;
 }
 
@@ -5489,9 +5727,10 @@
 wm_gmii_bm_writereg(device_t self, int phy, int reg, int val)
 {
 	struct wm_softc *sc = device_private(self);
-	int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+	int sem;
 
-	if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+	sem = swfwphysem[sc->sc_funcid];
+	if (wm_get_swfw_semaphore(sc, sem)) {
 		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
 		    __func__);
 		return;
@@ -5508,7 +5747,7 @@
 	}
 
 	wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val);
-	wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+	wm_put_swfw_semaphore(sc, sem);
 }
 
 static void
@@ -5659,6 +5898,89 @@
 }
 
 /*
+ * wm_gmii_hv_readreg:	[mii interface function]
+ *
+ *	Read a PHY register on the kumeran
+ * This could be handled by the PHY layer if we didn't have to lock the
+ * ressource ...
+ */
+static int
+wm_sgmii_readreg(device_t self, int phy, int reg)
+{
+	struct wm_softc *sc = device_private(self);
+	uint32_t i2ccmd;
+	int i, rv;
+
+	if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) {
+		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
+		    __func__);
+		return 0;
+	}
+
+	i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT)
+	    | (phy << I2CCMD_PHY_ADDR_SHIFT)
+	    | I2CCMD_OPCODE_READ;
+	CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd);
+
+	/* Poll the ready bit */
+	for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) {
+		delay(50);
+		i2ccmd = CSR_READ(sc, WMREG_I2CCMD);
+		if (i2ccmd & I2CCMD_READY)
+			break;
+	}
+	if ((i2ccmd & I2CCMD_READY) == 0)
+		aprint_error_dev(sc->sc_dev, "I2CCMD Read did not complete\n");
+	if ((i2ccmd & I2CCMD_ERROR) != 0)
+		aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n");
+
+	rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00);
+
+	wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
+	return rv;
+}
+
+/*
+ * wm_gmii_hv_writereg:	[mii interface function]
+ *
+ *	Write a PHY register on the kumeran.
+ * This could be handled by the PHY layer if we didn't have to lock the
+ * ressource ...
+ */
+static void
+wm_sgmii_writereg(device_t self, int phy, int reg, int val)
+{
+	struct wm_softc *sc = device_private(self);
+	uint32_t i2ccmd;
+	int i;
+
+	if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) {
+		aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
+		    __func__);
+		return;
+	}
+
+	i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT)
+	    | (phy << I2CCMD_PHY_ADDR_SHIFT)
+	    | I2CCMD_OPCODE_WRITE;
+	CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd);
+
+	/* Poll the ready bit */
+	for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) {
+		delay(50);
+		i2ccmd = CSR_READ(sc, WMREG_I2CCMD);
+		if (i2ccmd & I2CCMD_READY)
+			break;
+	}
+	if ((i2ccmd & I2CCMD_READY) == 0)
+		aprint_error_dev(sc->sc_dev, "I2CCMD Write did not complete\n");
+	if ((i2ccmd & I2CCMD_ERROR) != 0)
+		aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n");
+
+	wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
+}
+
+/*
  * wm_gmii_statchg:	[mii interface function]
  *
  *	Callback from MII layer when media changes.
@@ -6544,3 +6866,64 @@
 	CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext);
 	delay(20);
 }
+
+static void
+wm_set_pcie_completion_timeout(struct wm_softc *sc)
+{
+	uint32_t gcr;
+	pcireg_t ctrl2;
+
+	gcr = CSR_READ(sc, WMREG_GCR);
+
+	/* Only take action if timeout value is defaulted to 0 */
+	if ((gcr & GCR_CMPL_TMOUT_MASK) != 0)
+		goto out;
+
+	if ((gcr & GCR_CAP_VER2) == 0) {
+		gcr |= GCR_CMPL_TMOUT_10MS;
+		goto out;
+	}
+
+	ctrl2 = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+	    sc->sc_pcixe_capoff + PCI_PCIE_DCSR2);
+	ctrl2 |= WM_PCI_PCIE_DCSR2_16MS;
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+	    sc->sc_pcixe_capoff + PCI_PCIE_DCSR2, ctrl2);
+
+out:
+	/* Disable completion timeout resend */
+	gcr &= ~GCR_CMPL_TMOUT_RESEND;
+
+	CSR_WRITE(sc, WMREG_GCR, gcr);
+}
+
+/* special case - for 82575 - need to do manual init ... */
+static void
+wm_reset_init_script_82575(struct wm_softc *sc)
+{
+	/*
+	 * remark: this is untested code - we have no board without EEPROM
+	 *  same setup as mentioned int the freeBSD driver for the i82575
+	 */
+
+	/* SerDes configuration via SERDESCTRL */
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x00, 0x0c);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x01, 0x78);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x1b, 0x23);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x23, 0x15);
+
+	/* CCM configuration via CCMCTL register */
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x14, 0x00);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x10, 0x00);
+
+	/* PCIe lanes configuration */
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x00, 0xec);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x61, 0xdf);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x34, 0x05);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x2f, 0x81);
+
+	/* PCIe PLL Configuration */
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x02, 0x47);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x14, 0x00);
+	wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x10, 0x00);
+}

Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.37 src/sys/dev/pci/if_wmreg.h:1.38
--- src/sys/dev/pci/if_wmreg.h:1.37	Tue Feb 16 10:06:19 2010
+++ src/sys/dev/pci/if_wmreg.h	Tue Feb 16 15:17:17 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmreg.h,v 1.37 2010/02/16 10:06:19 msaitoh Exp $	*/
+/*	$NetBSD: if_wmreg.h,v 1.38 2010/02/16 15:17:17 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -338,12 +338,16 @@
 #define	CTRL_EXT_SPD_BYPS	(1U << 15) /* speed select bypass */
 #define	CTRL_EXT_IPS1		(1U << 16) /* invert power state bit 1 */
 #define	CTRL_EXT_RO_DIS		(1U << 17) /* relaxed ordering disabled */
-#define	CTRL_EXT_LINK_MODE_MASK	0x00C00000
-#define	CTRL_EXT_LINK_MODE_GMII	0x00000000
-#define	CTRL_EXT_LINK_MODE_TBI	0x00C00000
-#define	CTRL_EXT_LINK_MODE_KMRN	0x00000000
-#define	CTRL_EXT_LINK_MODE_SERDES 0x00C00000
+#define	CTRL_EXT_LINK_MODE_MASK		0x00C00000
+#define	CTRL_EXT_LINK_MODE_GMII		0x00000000
+#define	CTRL_EXT_LINK_MODE_KMRN		0x00000000
+#define	CTRL_EXT_LINK_MODE_1000KX	0x00400000
+#define	CTRL_EXT_LINK_MODE_SGMII	0x00800000
+#define	CTRL_EXT_LINK_MODE_PCIX_SERDES	0x00800000
+#define	CTRL_EXT_LINK_MODE_TBI		0x00C00000
+#define	CTRL_EXT_LINK_MODE_PCIE_SERDES	0x00C00000
 #define	CTRL_EXT_PHYPDEN	0x00100000
+#define CTRL_EXT_I2C_ENA	0x02000000  /* I2C enable */
 #define	CTRL_EXT_DRV_LOAD	0x10000000
 
 
@@ -357,6 +361,16 @@
 #define	MDIC_I		(1U << 29)	/* interrupt on MDI complete */
 #define	MDIC_E		(1U << 30)	/* MDI error */
 
+#define WMREG_SCTL	0x0024	/* SerDes Control - RW */
+/*
+ * These 4 macros are also used for other 8bit control registers on the
+ * 82575
+ */
+#define SCTL_CTL_READY  (1U << 31)
+#define SCTL_CTL_DATA_MASK 0x000000ff
+#define SCTL_CTL_ADDR_SHIFT 8
+#define SCTL_CTL_POLL_TIMEOUT 640
+
 #define	WMREG_FCAL	0x0028	/* Flow Control Address Low */
 #define	FCAL_CONST	0x00c28001	/* Flow Control MAC addr low */
 
@@ -447,24 +461,48 @@
 
 #define	WMREG_OLD_RDBAL0 0x0110	/* Receive Descriptor Base Low (ring 0) */
 #define	WMREG_RDBAL	0x2800
+#define	WMREG_RDBAL_2	0x0c00	/* for 82576 ... */
 
 #define	WMREG_OLD_RDBAH0 0x0114	/* Receive Descriptor Base High (ring 0) */
 #define	WMREG_RDBAH	0x2804
+#define	WMREG_RDBAH_2	0x0c04	/* for 82576 ... */
 
 #define	WMREG_OLD_RDLEN0 0x0118	/* Receive Descriptor Length (ring 0) */
 #define	WMREG_RDLEN	0x2808
+#define	WMREG_RDLEN_2	0x0c08	/* for 82576 ... */
+
+#define WMREG_SRRCTL	0x280c	/* additional recieve control used in 82575 ... */
+#define WMREG_SRRCTL_2	0x0c0c	/* for 82576 ... */
+#define SRRCTL_BSIZEPKT_MASK				0x0000007f
+#define SRRCTL_BSIZEPKT_SHIFT		10	/* Shift _right_ */
+#define SRRCTL_BSIZEHDRSIZE_MASK			0x00000f00
+#define SRRCTL_BSIZEHDRSIZE_SHIFT	2	/* Shift _left_ */
+#define SRRCTL_DESCTYPE_LEGACY				0x00000000
+#define SRRCTL_DESCTYPE_ADV_ONEBUF			(1U << 25)
+#define SRRCTL_DESCTYPE_HDR_SPLIT			(2U << 25)
+#define SRRCTL_DESCTYPE_HDR_REPLICATION			(3U << 25)
+#define SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT	(4U << 25)
+#define SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS		(5U << 25) /* 82575 only */
+#define SRRCTL_DESCTYPE_MASK				(7U << 25)
+#define SRRCTL_DROP_EN					0x80000000
 
 #define	WMREG_OLD_RDH0	0x0120	/* Receive Descriptor Head (ring 0) */
 #define	WMREG_RDH	0x2810
+#define	WMREG_RDH_2	0x0c10	/* for 82576 ... */
 
 #define	WMREG_OLD_RDT0	0x0128	/* Receive Descriptor Tail (ring 0) */
 #define	WMREG_RDT	0x2818
+#define	WMREG_RDT_2	0x0c18	/* for 82576 ... */
 
 #define	WMREG_RXDCTL	0x2828	/* Receive Descriptor Control */
+#define	WMREG_RXDCTL_2	0x0c28	/* for 82576 ... */
 #define	RXDCTL_PTHRESH(x) ((x) << 0)	/* prefetch threshold */
 #define	RXDCTL_HTHRESH(x) ((x) << 8)	/* host threshold */
 #define	RXDCTL_WTHRESH(x) ((x) << 16)	/* write back threshold */
 #define	RXDCTL_GRAN	(1U << 24)	/* 0 = cacheline, 1 = descriptor */
+/* flags used starting with 82575 ... */
+#define RXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
+#define RXDCTL_SWFLSH        0x04000000 /* Rx Desc. write-back flushing */
 
 #define	WMREG_OLD_RDTR1	0x0130	/* Receive Delay Timer (ring 1) */
 
@@ -590,6 +628,10 @@
 #define	TXDCTL_PTHRESH(x) ((x) << 0)	/* prefetch threshold */
 #define	TXDCTL_HTHRESH(x) ((x) << 8)	/* host threshold */
 #define	TXDCTL_WTHRESH(x) ((x) << 16)	/* write back threshold */
+/* flags used starting with 82575 ... */
+#define TXDCTL_QUEUE_ENABLE  0x02000000 /* Enable specific Tx Queue */
+#define TXDCTL_SWFLSH        0x04000000 /* Tx Desc. write-back flushing */
+#define TXDCTL_PRIORITY      0x08000000
 
 #define	WMREG_TADV	0x382c	/* Transmit Absolute Interrupt Delay Timer */
 
@@ -613,8 +655,10 @@
 #define	PBA_24K		0x0018
 #define	PBA_30K		0x001e
 #define	PBA_32K		0x0020
+#define	PBA_35K		0x0023
 #define	PBA_40K		0x0028
 #define	PBA_48K		0x0030		/* 48K, default Rx allocation */
+#define	PBA_64K		0x0040
 
 #define	WMREG_PBS	0x1008	/* Packet Buffer Size (ICH) */
 
@@ -622,6 +666,42 @@
 #define EEMNGCTL_CFGDONE_0 0x040000	/* MNG config cycle done */
 #define EEMNGCTL_CFGDONE_1 0x080000	/*  2nd port */
 
+#define WMREG_I2CCMD	0x1028	/* SFPI2C Command Register - RW */
+#define I2CCMD_REG_ADDR_SHIFT	16
+#define I2CCMD_REG_ADDR		0x00ff0000
+#define I2CCMD_PHY_ADDR_SHIFT	24
+#define I2CCMD_PHY_ADDR		0x07000000
+#define I2CCMD_OPCODE_READ	0x08000000
+#define I2CCMD_OPCODE_WRITE	0x00000000
+#define I2CCMD_RESET		0x10000000
+#define I2CCMD_READY		0x20000000
+#define I2CCMD_INTERRUPT_ENA	0x40000000
+#define I2CCMD_ERROR		0x80000000
+#define MAX_SGMII_PHY_REG_ADDR	255
+#define I2CCMD_PHY_TIMEOUT	200
+
+#define WMREG_EICS	0x01520  /* Ext. Interrupt Cause Set - WO */
+#define WMREG_EIMS	0x01524  /* Ext. Interrupt Mask Set/Read - RW */
+#define WMREG_EIMC	0x01528  /* Ext. Interrupt Mask Clear - WO */
+#define WMREG_EIAC	0x0152C  /* Ext. Interrupt Auto Clear - RW */
+#define WMREG_EIAM	0x01530  /* Ext. Interrupt Ack Auto Clear Mask - RW */
+
+#define WMREG_EICR	0x01580  /* Ext. Interrupt Cause Read - R/clr */
+
+#define EITR_RX_QUEUE0	0x00000001 /* Rx Queue 0 Interrupt */
+#define EITR_RX_QUEUE1	0x00000002 /* Rx Queue 1 Interrupt */
+#define EITR_RX_QUEUE2	0x00000004 /* Rx Queue 2 Interrupt */
+#define EITR_RX_QUEUE3	0x00000008 /* Rx Queue 3 Interrupt */
+#define EITR_TX_QUEUE0	0x00000100 /* Tx Queue 0 Interrupt */
+#define EITR_TX_QUEUE1	0x00000200 /* Tx Queue 1 Interrupt */
+#define EITR_TX_QUEUE2	0x00000400 /* Tx Queue 2 Interrupt */
+#define EITR_TX_QUEUE3	0x00000800 /* Tx Queue 3 Interrupt */
+#define EITR_TCP_TIMER	0x40000000 /* TCP Timer */
+#define EITR_OTHER	0x80000000 /* Interrupt Cause Active */
+
+#define WMREG_EITR(x)	(0x01680 + (0x4 * (x)))
+#define EITR_ITR_INT_MASK	0x0000ffff
+
 #define	WMREG_TXDMAC	0x3000	/* Transfer DMA Control */
 #define	TXDMAC_DPP	(1U << 0)	/* disable packet prefetch */
 
@@ -636,12 +716,6 @@
 #define	TSPMT_TSMT(x)	(x)		/* TCP seg min transfer */
 #define	TSPMT_TSPBP(x)	((x) << 16)	/* TCP seg pkt buf padding */
 
-#define	WMREG_RXCSUM	0x5000	/* Receive Checksum register */
-#define	RXCSUM_PCSS	0x000000ff	/* Packet Checksum Start */
-#define	RXCSUM_IPOFL	(1U << 8)	/* IP checksum offload */
-#define	RXCSUM_TUOFL	(1U << 9)	/* TCP/UDP checksum offload */
-#define	RXCSUM_IPV6OFL	(1U << 10)	/* IPv6 checksum offload */
-
 #define	WMREG_CRCERRS	0x4000	/* CRC Error Count */
 #define	WMREG_ALGNERRC	0x4004	/* Alignment Error Count */
 #define	WMREG_SYMERRC	0x4008	/* Symbol Error Count */
@@ -692,11 +766,36 @@
 
 #define	WMREG_MDPHYA	0x003C	/* PHY address - RW */
 
+#define	WMREG_RXCSUM	0x5000	/* Receive Checksum register */
+#define	RXCSUM_PCSS	0x000000ff	/* Packet Checksum Start */
+#define	RXCSUM_IPOFL	(1U << 8)	/* IP checksum offload */
+#define	RXCSUM_TUOFL	(1U << 9)	/* TCP/UDP checksum offload */
+#define	RXCSUM_IPV6OFL	(1U << 10)	/* IPv6 checksum offload */
+
+#define WMREG_RLPML	0x5004	/* Rx Long Packet Max Length */
+
+#define	WMREG_WUC	0x5800	/* Wakeup Control */
+
 #define	WMREG_MANC	0x5820	/* Management Control */
 #define	MANC_BLK_PHY_RST_ON_IDE	0x00040000
 
 #define	WMREG_MANC2H	0x5860	/* Manaegment Control To Host - RW */
 
+#define WMREG_GCR	0x5b00	/* PCIe Control */
+#define GCR_RXD_NO_SNOOP	0x00000001
+#define GCR_RXDSCW_NO_SNOOP	0x00000002
+#define GCR_RXDSCR_NO_SNOOP	0x00000004
+#define GCR_TXD_NO_SNOOP	0x00000008
+#define GCR_TXDSCW_NO_SNOOP	0x00000010
+#define GCR_TXDSCR_NO_SNOOP	0x00000020
+#define GCR_CMPL_TMOUT_MASK	0x0000f000
+#define GCR_CMPL_TMOUT_10MS	0x00001000
+#define GCR_CMPL_TMOUT_RESEND	0x00010000
+#define GCR_CAP_VER2		0x00040000
+#define WMREG_GIOCTL	0x5b44	/* GIO Analog Control Register */
+#define WMREG_CCMCTL	0x5b48	/* CCM Control Register */
+#define WMREG_SCCTL	0x5b4c	/* PCIc PLL Configuration Register */
+
 #define	WMREG_SWSM	0x5b50	/* SW Semaphore */
 #define	SWSM_SMBI	0x00000001	/* Driver Semaphore bit */
 #define	SWSM_SWESMBI	0x00000002	/* FW Semaphore bit */
@@ -715,6 +814,8 @@
 #define	SWFW_PHY0_SM		0x0002 /* first ctrl phy access */
 #define	SWFW_PHY1_SM		0x0004 /* second ctrl phy access */
 #define	SWFW_MAC_CSR_SM		0x0008
+#define	SWFW_PHY2_SM		0x0020 /* first ctrl phy access */
+#define	SWFW_PHY3_SM		0x0040 /* first ctrl phy access */
 #define	SWFW_SOFT_SHIFT		0	/* software semaphores */
 #define	SWFW_FIRM_SHIFT		16	/* firmware semaphores */
 
@@ -784,3 +885,6 @@
 
 #define ICH_NVM_SIG_WORD	0x13
 #define ICH_NVM_SIG_MASK	0xc000
+
+/* for PCI express Capability registers */
+#define	WM_PCI_PCIE_DCSR2_16MS	0x00000005

Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.8 src/sys/dev/pci/if_wmvar.h:1.9
--- src/sys/dev/pci/if_wmvar.h:1.8	Thu Jan 14 18:56:02 2010
+++ src/sys/dev/pci/if_wmvar.h	Tue Feb 16 15:17:17 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wmvar.h,v 1.8 2010/01/14 18:56:02 msaitoh Exp $	*/
+/*	$NetBSD: if_wmvar.h,v 1.9 2010/02/16 15:17:17 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -86,6 +86,8 @@
 #define	WM_F_PCIE		0x0800	/* bus is PCI-Express */
 #define WM_F_SWFW_SYNC		0x1000  /* Software-Firmware synchronisation */
 #define WM_F_SWFWHW_SYNC	0x2000  /* Software-Firmware synchronisation */
+#define WM_F_SGMII		0x4000  /* use SGMII */
+#define WM_F_NEWQUEUE		0x8000  /* chips which has the new queue system */
 
 typedef enum {
 	WM_T_unknown		= 0,
@@ -107,6 +109,10 @@
 	WM_T_82573,			/* i82573 */
 	WM_T_82574,			/* i82574 */
 	WM_T_82583,			/* i82583 */
+	WM_T_82575,			/* i82575 */
+	WM_T_82576,			/* i82576 */
+	WM_T_82580,			/* i82580 */
+	WM_T_82580ER,			/* i82580ER */
 	WM_T_80003,			/* i80003 */
 	WM_T_ICH8,			/* ICH8 LAN */
 	WM_T_ICH9,			/* ICH9 LAN */

Reply via email to