From 4c89b5bc10de411075e8b1c192f766c27c609e3c Mon Sep 17 00:00:00 2001
From: glebius <glebius@FreeBSD.org>
Date: Thu, 6 Apr 2006 17:09:03 +0000
Subject: Merge in new driver from Intel, version 5.1.5. Adds support for some
 new chips and improves support for already supported ones.

Some details, important for future merges:
  - if_em.c merged manually, viewing diff between new vendor
    driver and previous one.
  - if_em_hw.h dropped in from vendor, and then restored revisions
    1.16, 1.17, 1.18.
  - if_em_hw.c dropped in from vendor, and then two liner change made,
    that restores support for two rare chips.
---
 sys/dev/em/LICENSE    |    4 +-
 sys/dev/em/README     |   83 +++-
 sys/dev/em/if_em.c    |   71 ++-
 sys/dev/em/if_em_hw.c | 1293 ++++++++++++++++++++++++++++++++++++++-----------
 sys/dev/em/if_em_hw.h |  358 +++++++++++++-
 5 files changed, 1478 insertions(+), 331 deletions(-)

(limited to 'sys')

diff --git a/sys/dev/em/LICENSE b/sys/dev/em/LICENSE
index 42545ca..c527bb5 100644
--- a/sys/dev/em/LICENSE
+++ b/sys/dev/em/LICENSE
@@ -1,6 +1,5 @@
 $FreeBSD$
-/*-
-Copyright (c) 2001-2003, Intel Corporation 
+Copyright (c) 2001-2005, Intel Corporation 
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without 
@@ -28,4 +27,3 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
-*/
diff --git a/sys/dev/em/README b/sys/dev/em/README
index 4c4e981..0dd9c36 100644
--- a/sys/dev/em/README
+++ b/sys/dev/em/README
@@ -2,7 +2,7 @@ $FreeBSD$
 FreeBSD* Driver for the Intel(R) PRO/1000 Family of Adapters
 ============================================================
 
-March 18, 2005
+January 4, 2006
 
 
 Contents
@@ -21,9 +21,9 @@ Contents
 Overview
 ========
 
-This file describes the FreeBSD* driver, version 2.1.x, for the Intel(R)
-PRO/1000 Family of Adapters. This driver has been developed for use with
-FreeBSD, version 5.x.
+This file describes the FreeBSD* driver for the Intel(R) PRO/1000 Family of
+Adapters. This driver has been developed for use with FreeBSD, Release 4.11
+and greater and Release 5.4.
 
 For questions related to hardware requirements, refer to the documentation
 supplied with your Intel PRO/1000 adapter. All hardware requirements listed
@@ -36,12 +36,12 @@ Identifying Your Adapter
 For information on how to identify your adapter, go to the Adapter &
 Driver ID Guide at:
 
-http://support.intel.com/support/network/adapter/pro100/21397.htm
+http://support.intel.com/support/network/sb/cs-012904.htm
 
 
 For the latest Intel network drivers for FreeBSD, see:
 
-http://appsr.intel.com/scripts-df/support_intel.asp
+http://downloadfinder.intel.com/scripts-df-external/support_intel.aspx
 
 
 NOTE: Mobile adapters are not fully supported.
@@ -174,32 +174,62 @@ Additional Configurations
 =========================
 
 The driver supports Transmit/Receive Checksum Offload and Jumbo Frames on
-all but the 82542-based adapters. For specific adapters, refer to the
+all but the 82542-based adapters.  For specific adapters, refer to the
 Identifying Your Adapter section.
 
   Jumbo Frames
   ------------
-  To enable Jumbo Frames, use the ifconfig utility to increase the MTU
-  beyond 1500 bytes.
+  To enable Jumbo Frames, use the ifconfig utility to set the Maximum
+  Transport Unit (MTU) frame size above its default of 1500 bytes.
 
-  NOTES: Only enable Jumbo Frames if your network infrastructure supports
-         them.
+  The Jumbo Frames MTU range for Intel Adapters is 1500 to 16110. To modify
+  the setting, enter the following:
 
-         The Jumbo Frames setting on the switch must be set to at least
-         22 bytes larger than that of the MTU.
+        ifconfig em<interface_num> <hostname or IP address> mtu 9000
 
-         The Intel PRO/1000 PM Network Connection does not support jumbo
-         frames.
+  To confirm the MTU used between two specific devices, use:
 
+        route get <destination_IP_address>
 
-  The Jumbo Frames MTU range for Intel Adapters is 1500 to 16114. The default
-  MTU range is 1500. To modify the setting, enter the following:
+  Notes:
 
-        ifconfig em<interface_num> <hostname or IP address> mtu 9000
+  - Only enable Jumbo Frames if your network infrastructure supports them.
 
- To confirm the MTU used between two specific devices, use:
+  - To enable Jumbo Frames, increase the MTU size on the interface beyond
+    1500.
+
+  - The Jumbo Frames setting on the switch must be set to at least 22 bytes
+    larger than that of the MTU.
+
+  - The maximum MTU setting for Jumbo Frames is 16110.  This value coincides
+    with the maximum Jumbo Frames size of 16128.
+
+  - Some Intel gigabit adapters that support Jumbo Frames have a frame size
+    limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
+    The adapters with this limitation are based on the Intel(R) 82571EB,
+    82572EI, 82573L and 80003ES2LAN controller.  These correspond to the
+    following product names:
+     Intel(R) PRO/1000 PT Server Adapter
+     Intel(R) PRO/1000 PT Desktop Adapter
+     Intel(R) PRO/1000 PT Network Connection
+     Intel(R) PRO/1000 PT Dual Port Server Adapter
+     Intel(R) PRO/1000 PT Dual Port Network Connection
+     Intel(R) PRO/1000 PF Server Adapter
+     Intel(R) PRO/1000 PF Network Connection
+     Intel(R) PRO/1000 PF Dual Port Server Adapter
+     Intel(R) PRO/1000 PB Server Connection
+     Intel(R) PRO/1000 PL Network Connection
+     Intel(R) PRO/1000 EB Network Connection with I/O Acceleration
+     Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration
+
+  - Adapters based on the Intel(R) 82542 and 82573V/E controller do not
+    support Jumbo Frames. These correspond to the following product names:
+     Intel(R) PRO/1000 Gigabit Server Adapter
+     Intel(R) PRO/1000 PM Network Connection
+
+  - Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
+    loss of link.
 
-        route get <destination_IP_address>
 
   VLANs
   -----
@@ -224,6 +254,7 @@ Identifying Your Adapter section.
 
         ifconfig <vlan_name> destroy
 
+
   Polling
   -------
   To enable polling in the driver, add the following options to the kernel
@@ -233,9 +264,10 @@ Identifying Your Adapter section.
         options HZ=1000
 
   At runtime use:
-        sysctl kern.polling.enable=1 to turn polling on
+        ifconfig em0 polling to turn polling on
   Use:
-        sysctl kern.polling.enable=0 to turn polling off
+        ifconfig em0 -polling to turn polling off
+
 
   Checksum Offload
   ----------------
@@ -266,9 +298,15 @@ Identifying Your Adapter section.
 
   See the ifconfig man page for further information.
 
+
 Known Limitations
 =================
 
+  In FreeBSD version 4.x with Symmetric MultiProcessing (SMP), there is a known
+  issue on some newer hardware.  The problem is generic kernel and only in SMP
+  mode.  The workaround is to either use FreeBSD version 4.x in single processor
+  mode, or use FreeBSD 5.4 or later.
+
   There are known performance issues with this driver when running UDP traffic
   with Jumbo Frames.
 
@@ -313,6 +351,7 @@ For general information and support, go to the Intel support website at:
 If an issue is identified, support is through email only at:
 freebsdnic@mailbox.intel.com
 
+
 License
 =======
 
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index c189eb2..9867351 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -85,7 +85,7 @@ int	em_display_debug_stats = 0;
  *  Driver version
  *********************************************************************/
 
-char em_driver_version[] = "Version - 3.2.18";
+char em_driver_version[] = "Version - 5.1.5";
 
 
 /*********************************************************************
@@ -139,6 +139,8 @@ static em_vendor_info_t em_vendor_info_array[] =
 	{ 0x8086, E1000_DEV_ID_82546GB_SERDES,	PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82546GB_PCIE,	PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+	{ 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3,
+						PCI_ANY_ID, PCI_ANY_ID, 0},
 
 	{ 0x8086, E1000_DEV_ID_82547EI,		PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82547EI_MOBILE,	PCI_ANY_ID, PCI_ANY_ID, 0},
@@ -151,10 +153,15 @@ static em_vendor_info_t em_vendor_info_array[] =
 	{ 0x8086, E1000_DEV_ID_82572EI_COPPER,	PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82572EI_FIBER,	PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82572EI_SERDES,	PCI_ANY_ID, PCI_ANY_ID, 0},
+	{ 0x8086, E1000_DEV_ID_82572EI,		PCI_ANY_ID, PCI_ANY_ID, 0},
 
 	{ 0x8086, E1000_DEV_ID_82573E,		PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82573E_IAMT,	PCI_ANY_ID, PCI_ANY_ID, 0},
 	{ 0x8086, E1000_DEV_ID_82573L,		PCI_ANY_ID, PCI_ANY_ID, 0},
+	{ 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_DPT,
+						PCI_ANY_ID, PCI_ANY_ID, 0},
+	{ 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_DPT,
+						PCI_ANY_ID, PCI_ANY_ID, 0},
 
 	/* required last entry */
 	{ 0, 0, 0, 0, 0}
@@ -536,6 +543,11 @@ em_attach(device_t dev)
 	sc->hw.get_link_status = 1;
 	em_update_link_status(sc);
 
+	/* Indicate SOL/IDER usage */
+	if (em_check_phy_reset_block(&sc->hw))
+		device_printf(dev,
+		    "PHY reset is blocked due to SOL/IDER session.\n");
+
 	/* Identify 82544 on PCIX */
 	em_get_bus_info(&sc->hw);
 	if(sc->hw.bus_type == em_bus_type_pcix && sc->hw.mac_type == em_82544)
@@ -730,7 +742,7 @@ static int
 em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct em_softc	*sc = ifp->if_softc;
-	struct ifreq	*ifr = (struct ifreq *)data;
+	struct ifreq *ifr = (struct ifreq *)data;
 	int error = 0;
 
 	if (sc->in_detach)
@@ -745,17 +757,27 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 	case SIOCSIFMTU:
 	    {
 		int max_frame_size;
+		uint16_t eeprom_data = 0;
 
 		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
 
 		switch (sc->hw.mac_type) {
+		case em_82573:
+			/*
+			 * 82573 only supports jumbo frames
+			 * if ASPM is disabled.
+			 */
+			em_read_eeprom(&sc->hw, EEPROM_INIT_3GIO_3, 1,
+			    &eeprom_data);
+			if (eeprom_data & EEPROM_WORD1A_ASPM_MASK) {
+				max_frame_size = ETHER_MAX_LEN;
+				break;
+			}
+			/* Allow Jumbo frames - fall thru */
 		case em_82571:
 		case em_82572:
-			max_frame_size = 10500;
-			break;
-		case em_82573:
-			/* 82573 does not support jumbo frames. */
-			max_frame_size = ETHER_MAX_LEN;
+		case em_80003es2lan:	/* Limit Jumbo Frame size */
+			max_frame_size = 9234;
 			break;
 		default:
 			max_frame_size = MAX_JUMBO_FRAME_SIZE;
@@ -933,6 +955,7 @@ em_init_locked(struct em_softc *sc)
 		sc->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
 		sc->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
 		break;
+	case em_80003es2lan: /* 80003es2lan: Total Packet Buffer is 48K */
 	case em_82571: /* 82571: Total Packet Buffer is 48K */
 	case em_82572: /* 82572: Total Packet Buffer is 48K */
 			pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */
@@ -2078,7 +2101,10 @@ em_hardware_init(struct em_softc *sc)
 	sc->hw.fc_high_water = rx_buffer_size -
 	    roundup2(sc->hw.max_frame_size, 1024);
 	sc->hw.fc_low_water = sc->hw.fc_high_water - 1500;
-	sc->hw.fc_pause_time = 0x1000;
+	if (sc->hw.mac_type == em_80003es2lan)
+		sc->hw.fc_pause_time = 0xFFFF;
+	else
+		sc->hw.fc_pause_time = 0x1000;
 	sc->hw.fc_send_xon = TRUE;
 	sc->hw.fc = em_fc_full;
 
@@ -2402,7 +2428,7 @@ fail:
 static void
 em_initialize_transmit_unit(struct em_softc *sc)
 {
-	uint32_t	reg_tctl;
+	uint32_t	reg_tctl, tarc;
 	uint32_t	reg_tipg = 0;
 	uint64_t	bus_addr;
 
@@ -2430,6 +2456,11 @@ em_initialize_transmit_unit(struct em_softc *sc)
 		reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
 		reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
 		break;
+	case em_80003es2lan:
+		reg_tipg = DEFAULT_82543_TIPG_IPGR1;
+		reg_tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 <<
+		    E1000_TIPG_IPGR2_SHIFT;
+		break;
 	default:
 		if (sc->hw.media_type == em_media_type_fiber)
 			reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
@@ -2456,6 +2487,28 @@ em_initialize_transmit_unit(struct em_softc *sc)
 	}
 	E1000_WRITE_REG(&sc->hw, TCTL, reg_tctl);
 
+	if (sc->hw.mac_type == em_82571 || sc->hw.mac_type == em_82572) {
+		tarc = E1000_READ_REG(&sc->hw, TARC0);
+		tarc |= ((1 << 25) | (1 << 21));
+		E1000_WRITE_REG(&sc->hw, TARC0, tarc);
+		tarc = E1000_READ_REG(&sc->hw, TARC1);
+		tarc |= (1 << 25);
+		if (reg_tctl & E1000_TCTL_MULR)
+			tarc &= ~(1 << 28);
+		else
+			tarc |= (1 << 28);
+		E1000_WRITE_REG(&sc->hw, TARC1, tarc);
+	} else if (sc->hw.mac_type == em_80003es2lan) {
+		tarc = E1000_READ_REG(&sc->hw, TARC0);
+		tarc |= 1;
+		if (sc->hw.media_type == em_media_type_internal_serdes)
+			tarc |= (1 << 20);
+		E1000_WRITE_REG(&sc->hw, TARC0, tarc);
+		tarc = E1000_READ_REG(&sc->hw, TARC1);
+		tarc |= 1;
+		E1000_WRITE_REG(&sc->hw, TARC1, tarc);
+	}
+
 	/* Setup Transmit Descriptor Settings for this adapter */
 	sc->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS;
 
diff --git a/sys/dev/em/if_em_hw.c b/sys/dev/em/if_em_hw.c
index 179a2ee..377d853 100644
--- a/sys/dev/em/if_em_hw.c
+++ b/sys/dev/em/if_em_hw.c
@@ -76,6 +76,8 @@ static int32_t em_polarity_reversal_workaround(struct em_hw *hw);
 static int32_t em_set_phy_mode(struct em_hw *hw);
 static int32_t em_host_if_read_cookie(struct em_hw *hw, uint8_t *buffer);
 static uint8_t em_calculate_mng_checksum(char *buffer, uint32_t length);
+static int32_t em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex);
+static int32_t em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex);
 
 /* IGP cable length table */
 static const
@@ -91,14 +93,15 @@ uint16_t em_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
 
 static const
 uint16_t em_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
-      { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
-	0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
-	6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
-	21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
-	40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
-	60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
-	83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
-	104, 109, 114, 118, 121, 124};
+    { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+      0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+      6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+      21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
+      40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
+      60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
+      83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
+      104, 109, 114, 118, 121, 124};
+
 
 /******************************************************************************
  * Set the phy type member in the hw struct.
@@ -128,6 +131,11 @@ em_set_phy_type(struct em_hw *hw)
             hw->phy_type = em_phy_igp;
             break;
         }
+    case GG82563_E_PHY_ID:
+        if (hw->mac_type == em_80003es2lan) {
+            hw->phy_type = em_phy_gg82563;
+            break;
+        }
         /* Fall Through */
     default:
         /* Should never have loaded on this device */
@@ -294,6 +302,7 @@ em_set_mac_type(struct em_hw *hw)
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82546GB_PCIE:
     case E1000_DEV_ID_82546GB_QUAD_COPPER:
+    case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
         hw->mac_type = em_82546_rev_3;
         break;
     case E1000_DEV_ID_82541EI:
@@ -317,24 +326,32 @@ em_set_mac_type(struct em_hw *hw)
     case E1000_DEV_ID_82571EB_COPPER:
     case E1000_DEV_ID_82571EB_FIBER:
     case E1000_DEV_ID_82571EB_SERDES:
-	hw->mac_type = em_82571;
-	break;
+            hw->mac_type = em_82571;
+        break;
     case E1000_DEV_ID_82572EI_COPPER:
     case E1000_DEV_ID_82572EI_FIBER:
     case E1000_DEV_ID_82572EI_SERDES:
-	hw->mac_type = em_82572;
-	break;
+    case E1000_DEV_ID_82572EI:
+        hw->mac_type = em_82572;
+        break;
     case E1000_DEV_ID_82573E:
     case E1000_DEV_ID_82573E_IAMT:
     case E1000_DEV_ID_82573L:
         hw->mac_type = em_82573;
         break;
+    case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+    case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+        hw->mac_type = em_80003es2lan;
+        break;
     default:
         /* Should never have loaded on this device */
         return -E1000_ERR_MAC_TYPE;
     }
 
     switch(hw->mac_type) {
+    case em_80003es2lan:
+        hw->swfw_sync_present = TRUE;
+        /* fall through */
     case em_82571:
     case em_82572:
     case em_82573:
@@ -345,8 +362,9 @@ em_set_mac_type(struct em_hw *hw)
     case em_82541_rev_2:
     case em_82547_rev_2:
         hw->asf_firmware_present = TRUE;
+        break;
     default:
-	break;
+        break;
     }
 
     return E1000_SUCCESS;
@@ -374,29 +392,31 @@ em_set_media_type(struct em_hw *hw)
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82571EB_SERDES:
     case E1000_DEV_ID_82572EI_SERDES:
+    case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
         hw->media_type = em_media_type_internal_serdes;
         break;
     default:
-	switch (hw->mac_type) {
-	case em_82542_rev2_0:
-	case em_82542_rev2_1:
-		hw->media_type = em_media_type_fiber;
-		break;
-	case em_82573:
-		/*
-		 * The STATUS_TBIMODE bit is reserved or reused for
-		 * this device.
-		 */
-		hw->media_type = em_media_type_copper;
-		break;
-	default:
-		status = E1000_READ_REG(hw, STATUS);
-		if (status & E1000_STATUS_TBIMODE) {
-			hw->media_type = em_media_type_fiber;
-			/* tbi_compatibility not valid on fiber */
-			hw->tbi_compatibility_en = FALSE;
-		} else
-			hw->media_type = em_media_type_copper;
+        switch (hw->mac_type) {
+        case em_82542_rev2_0:
+        case em_82542_rev2_1:
+            hw->media_type = em_media_type_fiber;
+            break;
+        case em_82573:
+            /* The STATUS_TBIMODE bit is reserved or reused for the this
+             * device.
+             */
+            hw->media_type = em_media_type_copper;
+            break;
+        default:
+            status = E1000_READ_REG(hw, STATUS);
+            if (status & E1000_STATUS_TBIMODE) {
+                hw->media_type = em_media_type_fiber;
+                /* tbi_compatibility not valid on fiber */
+                hw->tbi_compatibility_en = FALSE;
+            } else {
+                hw->media_type = em_media_type_copper;
+            }
+            break;
         }
     }
 }
@@ -496,9 +516,7 @@ em_reset_hw(struct em_hw *hw)
         case em_82544:
         case em_82540:
         case em_82545:
-#ifndef __arm__
         case em_82546:
-#endif
         case em_82541:
         case em_82541_rev_2:
             /* These controllers can't ack the 64-bit write when issuing the
@@ -540,23 +558,24 @@ em_reset_hw(struct em_hw *hw)
             /* Wait for EEPROM reload */
             msec_delay(20);
             break;
-	case em_82573:
-		if (em_is_onboard_nvm_eeprom(hw) == FALSE) {
-			usec_delay(10);
-			ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
-			ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-			E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-			E1000_WRITE_FLUSH(hw);
-		}
-		/* fall through */
-	case em_82571:
-	case em_82572:
-		ret_val = em_get_auto_rd_done(hw);
-		if(ret_val)
-			/* We don't want to continue accessing MAC registers. */
-			return ret_val;
-		break;
-	default:
+        case em_82573:
+            if (em_is_onboard_nvm_eeprom(hw) == FALSE) {
+                usec_delay(10);
+                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+                E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+                E1000_WRITE_FLUSH(hw);
+            }
+            /* fall through */
+        case em_82571:
+        case em_82572:
+        case em_80003es2lan:
+            ret_val = em_get_auto_rd_done(hw);
+            if(ret_val)
+                /* We don't want to continue accessing MAC registers. */
+                return ret_val;
+            break;
+        default:
             /* Wait for EEPROM reload (it happens automatically) */
             msec_delay(5);
             break;
@@ -617,6 +636,8 @@ em_init_hw(struct em_hw *hw)
     uint16_t cmd_mmrbc;
     uint16_t stat_mmrbc;
     uint32_t mta_size;
+    uint32_t reg_data;
+    uint32_t ctrl_ext;
 
     DEBUGFUNC("em_init_hw");
 
@@ -708,14 +729,15 @@ em_init_hw(struct em_hw *hw)
     if(hw->mac_type > em_82544) {
         ctrl = E1000_READ_REG(hw, TXDCTL);
         ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
-	switch (hw->mac_type) {
-	case em_82571:
+        switch (hw->mac_type) {
+        default:
+            break;
+        case em_82571:
         case em_82572:
-		ctrl |= (1 << 22);
         case em_82573:
-		ctrl |= E1000_TXDCTL_COUNT_DESC;
-        default:
-		break;
+        case em_80003es2lan:
+            ctrl |= E1000_TXDCTL_COUNT_DESC;
+            break;
         }
         E1000_WRITE_REG(hw, TXDCTL, ctrl);
     }
@@ -725,21 +747,46 @@ em_init_hw(struct em_hw *hw)
     }
 
     switch (hw->mac_type) {
+    default:
+        break;
+    case em_80003es2lan:
+        /* Enable retransmit on late collisions */
+        reg_data = E1000_READ_REG(hw, TCTL);
+        reg_data |= E1000_TCTL_RTLC;
+        E1000_WRITE_REG(hw, TCTL, reg_data);
+
+        /* Configure Gigabit Carry Extend Padding */
+        reg_data = E1000_READ_REG(hw, TCTL_EXT);
+        reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
+        reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
+        E1000_WRITE_REG(hw, TCTL_EXT, reg_data);
+
+        /* Configure Transmit Inter-Packet Gap */
+        reg_data = E1000_READ_REG(hw, TIPG);
+        reg_data &= ~E1000_TIPG_IPGT_MASK;
+        reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
+        E1000_WRITE_REG(hw, TIPG, reg_data);
+
+        reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
+        reg_data &= ~0x00100000;
+        E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data);
+        /* Fall through */
     case em_82571:
     case em_82572:
-	ctrl = E1000_READ_REG(hw, TXDCTL1);
-	ctrl &= ~E1000_TXDCTL_WTHRESH;
-	ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
-	ctrl |= (1 << 22);
-	E1000_WRITE_REG(hw, TXDCTL1, ctrl);
-    default:
-	break;
+        ctrl = E1000_READ_REG(hw, TXDCTL1);
+        ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
+        if(hw->mac_type >= em_82571)
+            ctrl |= E1000_TXDCTL_COUNT_DESC;
+        E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+        break;
     }
 
+
+
     if (hw->mac_type == em_82573) {
-	uint32_t gcr = E1000_READ_REG(hw, GCR);
-	gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
-	E1000_WRITE_REG(hw, GCR, gcr);
+        uint32_t gcr = E1000_READ_REG(hw, GCR);
+        gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+        E1000_WRITE_REG(hw, GCR, gcr);
     }
 
     /* Clear all of the statistics registers (clear on read).  It is
@@ -749,6 +796,15 @@ em_init_hw(struct em_hw *hw)
      */
     em_clear_hw_cntrs(hw);
 
+    if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+        hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        /* Relaxed ordering must be disabled to avoid a parity
+         * error crash in a PCI slot. */
+        ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+    }
+
     return ret_val;
 }
 
@@ -815,7 +871,7 @@ em_setup_link(struct em_hw *hw)
     /* In the case of the phy reset being blocked, we already have a link.
      * We do not have to set it up again. */
     if (em_check_phy_reset_block(hw))
-	return E1000_SUCCESS;
+        return E1000_SUCCESS;
 
     /* Read and store word 0x0F of the EEPROM. This word contains bits
      * that determine the hardware's default PAUSE (flow control) mode,
@@ -826,26 +882,26 @@ em_setup_link(struct em_hw *hw)
      * be initialized based on a value in the EEPROM.
      */
     if (hw->fc == em_fc_default) {
-	switch (hw->mac_type) {
-	case em_82573:
-		hw->fc = em_fc_full;
-		break;
-	default:
-		ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
-		    1, &eeprom_data);
-		if (ret_val) {
-			DEBUGOUT("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
-
-		if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
-			hw->fc = em_fc_none;
-		else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
-		    EEPROM_WORD0F_ASM_DIR)
-			hw->fc = em_fc_tx_pause;
-		else
-			hw->fc = em_fc_full;
-	}
+        switch (hw->mac_type) {
+        case em_82573:
+            hw->fc = em_fc_full;
+            break;
+        default:
+            ret_val = em_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+                                        1, &eeprom_data);
+            if (ret_val) {
+                DEBUGOUT("EEPROM Read Error\n");
+                return -E1000_ERR_EEPROM;
+            }
+            if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+                hw->fc = em_fc_none;
+            else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
+                    EEPROM_WORD0F_ASM_DIR)
+                hw->fc = em_fc_tx_pause;
+            else
+                hw->fc = em_fc_full;
+            break;
+        }
     }
 
     /* We want to save off the original Flow Control configuration just
@@ -944,7 +1000,7 @@ em_setup_fiber_serdes_link(struct em_hw *hw)
      * loopback mode is disabled during initialization.
      */
     if (hw->mac_type == em_82571 || hw->mac_type == em_82572)
-	E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+        E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
 
     /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
      * set when the optics detect a signal. On older adapters, it will be
@@ -1266,11 +1322,159 @@ em_copper_link_igp_setup(struct em_hw *hw)
         ret_val = em_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
         if(ret_val)
             return ret_val;
-        }
+    }
 
-   return E1000_SUCCESS;
+    return E1000_SUCCESS;
 }
 
+/********************************************************************
+* Copper link setup for em_phy_gg82563 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+em_copper_link_ggp_setup(struct em_hw *hw)
+{
+    int32_t ret_val;
+    uint16_t phy_data;
+    uint32_t reg_data;
+
+    DEBUGFUNC("em_copper_link_ggp_setup");
+
+    if(!hw->phy_reset_disable) {
+        
+        /* Enable CRS on TX for half-duplex operation. */
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                     &phy_data);
+        if(ret_val)
+            return ret_val;
+
+        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+        /* Use 25MHz for both link down and 1000BASE-T for Tx clock */
+        phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
+
+        ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                      phy_data);
+        if(ret_val)
+            return ret_val;
+
+        /* Options:
+         *   MDI/MDI-X = 0 (default)
+         *   0 - Auto for all speeds
+         *   1 - MDI mode
+         *   2 - MDI-X mode
+         *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+         */
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
+        if(ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
+
+        switch (hw->mdix) {
+        case 1:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
+            break;
+        case 2:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
+            break;
+        case 0:
+        default:
+            phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
+            break;
+        }
+
+        /* Options:
+         *   disable_polarity_correction = 0 (default)
+         *       Automatic Correction for Reversed Cable Polarity
+         *   0 - Disabled
+         *   1 - Enabled
+         */
+        phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+        if(hw->disable_polarity_correction == 1)
+            phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+        ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+
+        if(ret_val)
+            return ret_val;
+
+        /* SW Reset the PHY so all changes take effect */
+        ret_val = em_phy_reset(hw);
+        if (ret_val) {
+            DEBUGOUT("Error Resetting the PHY\n");
+            return ret_val;
+        }
+    } /* phy_reset_disable */
+
+    if (hw->mac_type == em_80003es2lan) {
+        /* Bypass RX and TX FIFO's */
+        ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL,
+                                       E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
+                                       E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
+        if (ret_val)
+            return ret_val;
+
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
+        ret_val = em_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data);
+
+        if (ret_val)
+            return ret_val;
+
+        reg_data = E1000_READ_REG(hw, CTRL_EXT);
+        reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
+        E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                          &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        /* Do not init these registers when the HW is in IAMT mode, since the
+         * firmware will have already initialized them.  We only initialize
+         * them if the HW is not in IAMT mode.
+         */
+        if (em_check_mng_mode(hw) == FALSE) {
+            /* Enable Electrical Idle on the PHY */
+            phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+            ret_val = em_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                          phy_data);
+            if (ret_val)
+                return ret_val;
+
+            ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                         &phy_data);
+            if (ret_val)
+                return ret_val;
+
+            /* Disable Pass False Carrier on the PHY */
+            phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+            ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          phy_data);
+            if (ret_val)
+                return ret_val;
+        }
+
+        /* Workaround: Disable padding in Kumeran interface in the MAC
+         * and in the PHY to avoid CRC errors.
+         */
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
+                                     &phy_data);
+        if (ret_val)
+            return ret_val;
+        phy_data |= GG82563_ICR_DIS_PADDING;
+        ret_val = em_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
+                                      phy_data);
+        if (ret_val)
+            return ret_val;
+    }
+
+    return E1000_SUCCESS;
+}
 
 /********************************************************************
 * Copper link setup for em_phy_m88 series.
@@ -1481,14 +1685,50 @@ em_setup_copper_link(struct em_hw *hw)
     int32_t ret_val;
     uint16_t i;
     uint16_t phy_data;
+    uint16_t reg_data;
 
     DEBUGFUNC("em_setup_copper_link");
 
+    switch (hw->mac_type) {
+    case em_80003es2lan:
+        /* Set the mac to wait the maximum time between each
+         * iteration and increase the max iterations when
+         * polling the phy; this fixes erroneous timeouts at 10Mbps. */
+        ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+        if (ret_val)
+            return ret_val;
+        ret_val = em_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+        if (ret_val)
+            return ret_val;
+        reg_data |= 0x3F;
+        ret_val = em_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+        if (ret_val)
+            return ret_val;
+    default:
+        break;
+    }
+
     /* Check if it is a valid PHY and set PHY mode if necessary. */
     ret_val = em_copper_link_preconfig(hw);
     if(ret_val)
         return ret_val;
 
+    switch (hw->mac_type) {
+    case em_80003es2lan:
+        ret_val = em_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                      &reg_data);
+        if (ret_val)
+            return ret_val;
+        reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
+        ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                       reg_data);
+        if (ret_val)
+            return ret_val;
+        break;
+    default:
+        break;
+    }
+
     if (hw->phy_type == em_phy_igp ||
         hw->phy_type == em_phy_igp_2) {
         ret_val = em_copper_link_igp_setup(hw);
@@ -1498,6 +1738,10 @@ em_setup_copper_link(struct em_hw *hw)
         ret_val = em_copper_link_mgp_setup(hw);
         if(ret_val)
             return ret_val;
+    } else if (hw->phy_type == em_phy_gg82563) {
+        ret_val = em_copper_link_ggp_setup(hw);
+        if(ret_val)
+            return ret_val;
     }
 
     if(hw->autoneg) {
@@ -1545,6 +1789,86 @@ em_setup_copper_link(struct em_hw *hw)
 }
 
 /******************************************************************************
+* Configure the MAC-to-PHY interface for 10/100Mbps
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+em_configure_kmrn_for_10_100(struct em_hw *hw, uint16_t duplex)
+{
+    int32_t ret_val = E1000_SUCCESS;
+    uint32_t tipg;
+    uint16_t reg_data;
+
+    DEBUGFUNC("em_configure_kmrn_for_10_100");
+
+    reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT;
+    ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
+                                   reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Configure Transmit Inter-Packet Gap */
+    tipg = E1000_READ_REG(hw, TIPG);
+    tipg &= ~E1000_TIPG_IPGT_MASK;
+    tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
+    E1000_WRITE_REG(hw, TIPG, tipg);
+
+    ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                 &reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Enable pass false carrier when in half duplex mode. */
+    if (duplex == HALF_DUPLEX)
+        reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+    else
+        reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+
+    ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                  reg_data);
+    
+    return ret_val;
+}
+
+static int32_t
+em_configure_kmrn_for_1000(struct em_hw *hw, uint16_t duplex)
+{
+    int32_t ret_val = E1000_SUCCESS;
+    uint16_t reg_data;
+    uint32_t tipg;
+
+    DEBUGFUNC("em_configure_kmrn_for_1000");
+
+    reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT;
+    ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
+                                   reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Configure Transmit Inter-Packet Gap */
+    tipg = E1000_READ_REG(hw, TIPG);
+    tipg &= ~E1000_TIPG_IPGT_MASK;
+    tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
+    E1000_WRITE_REG(hw, TIPG, tipg);
+
+
+    ret_val = em_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                 &reg_data);
+    if (ret_val)
+        return ret_val;
+
+    /* Disable Pass False Carrier on the PHY */
+    reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+    ret_val = em_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                  reg_data);
+    
+    return ret_val;
+}
+
+/******************************************************************************
 * Configures PHY autoneg and flow control advertisement settings
 *
 * hw - Struct containing variables accessed by shared code
@@ -1563,10 +1887,10 @@ em_phy_setup_autoneg(struct em_hw *hw)
     if(ret_val)
         return ret_val;
 
-        /* Read the MII 1000Base-T Control Register (Address 9). */
-        ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
-        if(ret_val)
-            return ret_val;
+    /* Read the MII 1000Base-T Control Register (Address 9). */
+    ret_val = em_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+    if(ret_val)
+        return ret_val;
 
     /* Need to parse both autoneg_advertised and fc and set up
      * the appropriate PHY registers.  First we will parse for
@@ -1765,7 +2089,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
     /* Write the configured values back to the Device Control Reg. */
     E1000_WRITE_REG(hw, CTRL, ctrl);
 
-    if (hw->phy_type == em_phy_m88) {
+    if ((hw->phy_type == em_phy_m88) ||
+        (hw->phy_type == em_phy_gg82563)) {
         ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
         if(ret_val)
             return ret_val;
@@ -1834,7 +2159,8 @@ em_phy_force_speed_duplex(struct em_hw *hw)
             msec_delay(100);
         }
         if((i == 0) &&
-           (hw->phy_type == em_phy_m88)) {
+           ((hw->phy_type == em_phy_m88) ||
+            (hw->phy_type == em_phy_gg82563))) {
             /* We didn't get link.  Reset the DSP and wait again for link. */
             ret_val = em_phy_reset_dsp(hw);
             if(ret_val) {
@@ -1893,6 +2219,27 @@ em_phy_force_speed_duplex(struct em_hw *hw)
             if(ret_val)
                 return ret_val;
         }
+    } else if (hw->phy_type == em_phy_gg82563) {
+        /* The TX_CLK of the Extended PHY Specific Control Register defaults
+         * to 2.5MHz on a reset.  We need to re-force it back to 25MHz, if
+         * we're not in a forced 10/duplex configuration. */
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
+        if (ret_val)
+            return ret_val;
+
+        phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
+        if ((hw->forced_speed_duplex == em_10_full) ||
+            (hw->forced_speed_duplex == em_10_half))
+            phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ;
+        else
+            phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ;
+
+        /* Also due to the reset, we need to enable CRS on Tx. */
+        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+
+        ret_val = em_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
+        if (ret_val)
+            return ret_val;
     }
     return E1000_SUCCESS;
 }
@@ -1908,14 +2255,19 @@ em_phy_force_speed_duplex(struct em_hw *hw)
 void
 em_config_collision_dist(struct em_hw *hw)
 {
-    uint32_t tctl;
+    uint32_t tctl, coll_dist;
 
     DEBUGFUNC("em_config_collision_dist");
 
+    if (hw->mac_type < em_82543)
+        coll_dist = E1000_COLLISION_DISTANCE_82542;
+    else
+        coll_dist = E1000_COLLISION_DISTANCE;
+
     tctl = E1000_READ_REG(hw, TCTL);
 
     tctl &= ~E1000_TCTL_COLD;
-    tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+    tctl |= coll_dist << E1000_COLD_SHIFT;
 
     E1000_WRITE_REG(hw, TCTL, tctl);
     E1000_WRITE_FLUSH(hw);
@@ -2159,10 +2511,10 @@ em_config_fc_after_link_up(struct em_hw *hw)
                  */
                 if(hw->original_fc == em_fc_full) {
                     hw->fc = em_fc_full;
-                    DEBUGOUT("Flow Control = FULL.\r\n");
+                    DEBUGOUT("Flow Control = FULL.\n");
                 } else {
                     hw->fc = em_fc_rx_pause;
-                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
                 }
             }
             /* For receiving PAUSE frames ONLY.
@@ -2178,7 +2530,7 @@ em_config_fc_after_link_up(struct em_hw *hw)
                     (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = em_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
             }
             /* For transmitting PAUSE frames ONLY.
              *
@@ -2193,7 +2545,7 @@ em_config_fc_after_link_up(struct em_hw *hw)
                     !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = em_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
             /* Per the IEEE spec, at this point flow control should be
              * disabled.  However, we want to consider that we could
@@ -2219,10 +2571,10 @@ em_config_fc_after_link_up(struct em_hw *hw)
                      hw->original_fc == em_fc_tx_pause) ||
                     hw->fc_strict_ieee) {
                 hw->fc = em_fc_none;
-                DEBUGOUT("Flow Control = NONE.\r\n");
+                DEBUGOUT("Flow Control = NONE.\n");
             } else {
                 hw->fc = em_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
 
             /* Now we need to do one last check...  If we auto-
@@ -2247,7 +2599,7 @@ em_config_fc_after_link_up(struct em_hw *hw)
                 return ret_val;
             }
         } else {
-            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
         }
     }
     return E1000_SUCCESS;
@@ -2430,7 +2782,7 @@ em_check_for_link(struct em_hw *hw)
             hw->autoneg_failed = 1;
             return 0;
         }
-        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
 
         /* Disable auto-negotiation in the TXCW register */
         E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
@@ -2455,7 +2807,7 @@ em_check_for_link(struct em_hw *hw)
     else if(((hw->media_type == em_media_type_fiber) ||
              (hw->media_type == em_media_type_internal_serdes)) &&
             (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -2518,13 +2870,13 @@ em_get_speed_and_duplex(struct em_hw *hw,
 
         if(status & E1000_STATUS_FD) {
             *duplex = FULL_DUPLEX;
-            DEBUGOUT("Full Duplex\r\n");
+            DEBUGOUT("Full Duplex\n");
         } else {
             *duplex = HALF_DUPLEX;
-            DEBUGOUT(" Half Duplex\r\n");
+            DEBUGOUT(" Half Duplex\n");
         }
     } else {
-        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        DEBUGOUT("1000 Mbs, Full Duplex\n");
         *speed = SPEED_1000;
         *duplex = FULL_DUPLEX;
     }
@@ -2550,6 +2902,16 @@ em_get_speed_and_duplex(struct em_hw *hw,
         }
     }
 
+    if ((hw->mac_type == em_80003es2lan) && 
+        (hw->media_type == em_media_type_copper)) {
+        if (*speed == SPEED_1000)
+            ret_val = em_configure_kmrn_for_1000(hw, *duplex);
+        else
+            ret_val = em_configure_kmrn_for_10_100(hw, *duplex);
+        if (ret_val)
+            return ret_val;
+    }
+
     return E1000_SUCCESS;
 }
 
@@ -2725,6 +3087,72 @@ em_shift_in_mdi_bits(struct em_hw *hw)
     return data;
 }
 
+int32_t
+em_swfw_sync_acquire(struct em_hw *hw, uint16_t mask)
+{
+    uint32_t swfw_sync = 0;
+    uint32_t swmask = mask;
+    uint32_t fwmask = mask << 16;
+    int32_t timeout = 200;
+
+    DEBUGFUNC("em_swfw_sync_acquire");
+
+    if (!hw->swfw_sync_present)
+        return em_get_hw_eeprom_semaphore(hw);
+
+    while(timeout) {
+            if (em_get_hw_eeprom_semaphore(hw))
+                return -E1000_ERR_SWFW_SYNC;
+
+            swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+            if (!(swfw_sync & (fwmask | swmask))) {
+                break;
+            }
+
+            /* firmware currently using resource (fwmask) */
+            /* or other software thread currently using resource (swmask) */
+            em_put_hw_eeprom_semaphore(hw);
+            msec_delay_irq(5);
+            timeout--;
+    }
+
+    if (!timeout) {
+        DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+        return -E1000_ERR_SWFW_SYNC;
+    }
+
+    swfw_sync |= swmask;
+    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+
+    em_put_hw_eeprom_semaphore(hw);
+    return E1000_SUCCESS;
+}
+
+void
+em_swfw_sync_release(struct em_hw *hw, uint16_t mask)
+{
+    uint32_t swfw_sync;
+    uint32_t swmask = mask;
+
+    DEBUGFUNC("em_swfw_sync_release");
+
+    if (!hw->swfw_sync_present) {
+        em_put_hw_eeprom_semaphore(hw);
+        return;
+    }
+
+    /* if (em_get_hw_eeprom_semaphore(hw))
+     *    return -E1000_ERR_SWFW_SYNC; */
+    while (em_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
+        /* empty */
+
+    swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+    swfw_sync &= ~swmask;
+    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+
+    em_put_hw_eeprom_semaphore(hw);
+}
+
 /*****************************************************************************
 * Reads the value from a PHY register, if the value is on a specific non zero
 * page, sets the page first.
@@ -2737,22 +3165,55 @@ em_read_phy_reg(struct em_hw *hw,
                    uint16_t *phy_data)
 {
     uint32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("em_read_phy_reg");
 
+    if ((hw->mac_type == em_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (em_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
     if((hw->phy_type == em_phy_igp || 
         hw->phy_type == em_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
         if(ret_val) {
+            em_swfw_sync_release(hw, swfw);
             return ret_val;
         }
+    } else if (hw->phy_type == em_phy_gg82563) {
+        if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
+            (hw->mac_type == em_80003es2lan)) {
+            /* Select Configuration Page */
+            if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            } else {
+                /* Use Alternative Page Select register to access
+                 * registers 30 and 31
+                 */
+                ret_val = em_write_phy_reg_ex(hw,
+                                                 GG82563_PHY_PAGE_SELECT_ALT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            }
+
+            if (ret_val) {
+                em_swfw_sync_release(hw, swfw);
+                return ret_val;
+            }
+        }
     }
 
     ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                     phy_data);
 
+    em_swfw_sync_release(hw, swfw);
     return ret_val;
 }
 
@@ -2843,22 +3304,55 @@ em_write_phy_reg(struct em_hw *hw,
                     uint16_t phy_data)
 {
     uint32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("em_write_phy_reg");
 
+    if ((hw->mac_type == em_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (em_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
     if((hw->phy_type == em_phy_igp || 
         hw->phy_type == em_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
         if(ret_val) {
+            em_swfw_sync_release(hw, swfw);
             return ret_val;
         }
+    } else if (hw->phy_type == em_phy_gg82563) {
+        if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
+            (hw->mac_type == em_80003es2lan)) {
+            /* Select Configuration Page */
+            if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                ret_val = em_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            } else {
+                /* Use Alternative Page Select register to access
+                 * registers 30 and 31
+                 */
+                ret_val = em_write_phy_reg_ex(hw,
+                                                 GG82563_PHY_PAGE_SELECT_ALT,
+                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
+            }
+
+            if (ret_val) {
+                em_swfw_sync_release(hw, swfw);
+                return ret_val;
+            }
+        }
     }
 
     ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                      phy_data);
 
+    em_swfw_sync_release(hw, swfw);
     return ret_val;
 }
 
@@ -2891,7 +3385,7 @@ em_write_phy_reg_ex(struct em_hw *hw,
         E1000_WRITE_REG(hw, MDIC, mdic);
 
         /* Poll the ready bit to see if the MDI read completed */
-        for(i = 0; i < 640; i++) {
+        for(i = 0; i < 641; i++) {
             usec_delay(5);
             mdic = E1000_READ_REG(hw, MDIC);
             if(mdic & E1000_MDIC_READY) break;
@@ -2925,6 +3419,65 @@ em_write_phy_reg_ex(struct em_hw *hw,
     return E1000_SUCCESS;
 }
 
+int32_t
+em_read_kmrn_reg(struct em_hw *hw,
+                    uint32_t reg_addr,
+                    uint16_t *data)
+{
+    uint32_t reg_val;
+    uint16_t swfw;
+    DEBUGFUNC("em_read_kmrn_reg");
+
+    if ((hw->mac_type == em_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (em_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
+    /* Write register address */
+    reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+              E1000_KUMCTRLSTA_OFFSET) |
+              E1000_KUMCTRLSTA_REN;
+    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    usec_delay(2);
+
+    /* Read the data returned */
+    reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+    *data = (uint16_t)reg_val;
+
+    em_swfw_sync_release(hw, swfw);
+    return E1000_SUCCESS;
+}
+
+int32_t
+em_write_kmrn_reg(struct em_hw *hw,
+                     uint32_t reg_addr,
+                     uint16_t data)
+{
+    uint32_t reg_val;
+    uint16_t swfw;
+    DEBUGFUNC("em_write_kmrn_reg");
+
+    if ((hw->mac_type == em_80003es2lan) &&
+        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        swfw = E1000_SWFW_PHY1_SM;
+    } else {
+        swfw = E1000_SWFW_PHY0_SM;
+    }
+    if (em_swfw_sync_acquire(hw, swfw))
+        return -E1000_ERR_SWFW_SYNC;
+
+    reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+              E1000_KUMCTRLSTA_OFFSET) | data;
+    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    usec_delay(2);
+
+    em_swfw_sync_release(hw, swfw);
+    return E1000_SUCCESS;
+}
 
 /******************************************************************************
 * Returns the PHY to the power-on reset state
@@ -2937,6 +3490,7 @@ em_phy_hw_reset(struct em_hw *hw)
     uint32_t ctrl, ctrl_ext;
     uint32_t led_ctrl;
     int32_t ret_val;
+    uint16_t swfw;
 
     DEBUGFUNC("em_phy_hw_reset");
 
@@ -2949,22 +3503,37 @@ em_phy_hw_reset(struct em_hw *hw)
     DEBUGOUT("Resetting Phy...\n");
 
     if(hw->mac_type > em_82543) {
-	/*
-	 * Read the device control register and assert the E1000_CTRL_PHY_RST
-	 * bit. Then, take it out of reset.
-	 * For pre-em_82571 hardware, we delay for 10ms between the assert 
-	 * and deassert.  For em_82571 hardware and later, we instead delay
-	 * for 10ms after the deassertion.
-	 */
-	ctrl = E1000_READ_REG(hw, CTRL);
-	E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
-	E1000_WRITE_FLUSH(hw);
-	if (hw->mac_type < em_82571)
-		msec_delay(10);
-	E1000_WRITE_REG(hw, CTRL, ctrl);
-	E1000_WRITE_FLUSH(hw);
-	if (hw->mac_type >= em_82571)
-		msec_delay(10);
+        if ((hw->mac_type == em_80003es2lan) &&
+            (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+            swfw = E1000_SWFW_PHY1_SM;
+        } else {
+            swfw = E1000_SWFW_PHY0_SM;
+        }
+        if (em_swfw_sync_acquire(hw, swfw)) {
+            em_release_software_semaphore(hw);
+            return -E1000_ERR_SWFW_SYNC;
+        }
+        /* Read the device control register and assert the E1000_CTRL_PHY_RST
+         * bit. Then, take it out of reset.
+         * For pre-em_82571 hardware, we delay for 10ms between the assert 
+         * and deassert.  For em_82571 hardware and later, we instead delay
+         * for 50us between and 10ms after the deassertion.
+         */
+        ctrl = E1000_READ_REG(hw, CTRL);
+        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
+        E1000_WRITE_FLUSH(hw);
+        
+        if (hw->mac_type < em_82571) 
+            msec_delay(10);
+        else
+            usec_delay(100);
+        
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        E1000_WRITE_FLUSH(hw);
+        
+        if (hw->mac_type >= em_82571)
+            msec_delay(10);
+        em_swfw_sync_release(hw, swfw);
     } else {
         /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
          * bit to put the PHY into reset. Then, take it out of reset.
@@ -2991,6 +3560,7 @@ em_phy_hw_reset(struct em_hw *hw)
 
     /* Wait for FW to finish PHY configuration. */
     ret_val = em_get_phy_cfg_done(hw);
+    em_release_software_semaphore(hw);
 
     return ret_val;
 }
@@ -3061,12 +3631,22 @@ em_detect_gig_phy(struct em_hw *hw)
     /* The 82571 firmware may still be configuring the PHY.  In this
      * case, we cannot access the PHY until the configuration is done.  So
      * we explicitly set the PHY values. */
-    if(hw->mac_type == em_82571 || hw->mac_type == em_82572) {
-	hw->phy_id = IGP01E1000_I_PHY_ID;
-	hw->phy_type = em_phy_igp_2;
-	return E1000_SUCCESS;
+    if(hw->mac_type == em_82571 ||
+       hw->mac_type == em_82572) {
+        hw->phy_id = IGP01E1000_I_PHY_ID;
+        hw->phy_type = em_phy_igp_2;
+        return E1000_SUCCESS;
     }
 
+    /* ESB-2 PHY reads require em_phy_gg82563 to be set because of a work-
+     * around that forces PHY page 0 to be set or the reads fail.  The rest of
+     * the code in this routine uses em_read_phy_reg to read the PHY ID.
+     * So for ESB-2 we need to have this set so our reads won't fail.  If the
+     * attached PHY is not a em_phy_gg82563, the routines below will figure
+     * this out as well. */
+    if (hw->mac_type == em_80003es2lan)
+        hw->phy_type = em_phy_gg82563;
+
     /* Read the PHY ID Registers to identify which PHY is onboard. */
     ret_val = em_read_phy_reg(hw, PHY_ID1, &phy_id_high);
     if(ret_val)
@@ -3104,6 +3684,9 @@ em_detect_gig_phy(struct em_hw *hw)
     case em_82573:
         if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
         break;
+    case em_80003es2lan:
+        if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
+        break;
     default:
         DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
         return -E1000_ERR_CONFIG;
@@ -3130,8 +3713,10 @@ em_phy_reset_dsp(struct em_hw *hw)
     DEBUGFUNC("em_phy_reset_dsp");
 
     do {
-        ret_val = em_write_phy_reg(hw, 29, 0x001d);
-        if(ret_val) break;
+        if (hw->phy_type != em_phy_gg82563) {
+            ret_val = em_write_phy_reg(hw, 29, 0x001d);
+            if(ret_val) break;
+        }
         ret_val = em_write_phy_reg(hw, 30, 0x00c1);
         if(ret_val) break;
         ret_val = em_write_phy_reg(hw, 30, 0x0000);
@@ -3263,8 +3848,17 @@ em_phy_m88_get_info(struct em_hw *hw,
         /* Cable Length Estimation and Local/Remote Receiver Information
          * are only valid at 1000 Mbps.
          */
-        phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-                                  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+        if (hw->phy_type != em_phy_gg82563) {
+            phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+                                      M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+        } else {
+            ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
+                                         &phy_data);
+            if (ret_val)
+                return ret_val;
+
+            phy_info->cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH;
+        }
 
         ret_val = em_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
         if(ret_val)
@@ -3345,7 +3939,8 @@ em_validate_mdi_setting(struct em_hw *hw)
 
 /******************************************************************************
  * Sets up eeprom variables in the hw struct.  Must be called after mac_type
- * is configured.
+ * is configured.  Additionally, if this is ICH8, the flash controller GbE
+ * registers must be mapped, or this will crash.
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
@@ -3422,19 +4017,19 @@ em_init_eeprom_params(struct em_hw *hw)
         break;
     case em_82571:
     case em_82572:
-	eeprom->type = em_eeprom_spi;
-	eeprom->opcode_bits = 8;
-	eeprom->delay_usec = 1;
-	if (eecd & E1000_EECD_ADDR_BITS) {
-		eeprom->page_size = 32;
-		eeprom->address_bits = 16;
-	} else {
-		eeprom->page_size = 8;
-		eeprom->address_bits = 8;
-	}
-	eeprom->use_eerd = FALSE;
-	eeprom->use_eewr = FALSE;
-	break;
+        eeprom->type = em_eeprom_spi;
+        eeprom->opcode_bits = 8;
+        eeprom->delay_usec = 1;
+        if (eecd & E1000_EECD_ADDR_BITS) {
+            eeprom->page_size = 32;
+            eeprom->address_bits = 16;
+        } else {
+            eeprom->page_size = 8;
+            eeprom->address_bits = 8;
+        }
+        eeprom->use_eerd = FALSE;
+        eeprom->use_eewr = FALSE;
+        break;
     case em_82573:
         eeprom->type = em_eeprom_spi;
         eeprom->opcode_bits = 8;
@@ -3458,6 +4053,20 @@ em_init_eeprom_params(struct em_hw *hw)
             E1000_WRITE_REG(hw, EECD, eecd);
         }
         break;
+    case em_80003es2lan:
+        eeprom->type = em_eeprom_spi;
+        eeprom->opcode_bits = 8;
+        eeprom->delay_usec = 1;
+        if (eecd & E1000_EECD_ADDR_BITS) {
+            eeprom->page_size = 32;
+            eeprom->address_bits = 16;
+        } else {
+            eeprom->page_size = 8;
+            eeprom->address_bits = 8;
+        }
+        eeprom->use_eerd = TRUE;
+        eeprom->use_eewr = FALSE;
+        break;
     default:
         break;
     }
@@ -3638,32 +4247,31 @@ em_acquire_eeprom(struct em_hw *hw)
 
     DEBUGFUNC("em_acquire_eeprom");
 
-    if(em_get_hw_eeprom_semaphore(hw))
-        return -E1000_ERR_EEPROM;
-
+    if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+        return -E1000_ERR_SWFW_SYNC;
     eecd = E1000_READ_REG(hw, EECD);
 
     if (hw->mac_type != em_82573) {
-    /* Request EEPROM Access */
-    if(hw->mac_type > em_82544) {
-        eecd |= E1000_EECD_REQ;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        eecd = E1000_READ_REG(hw, EECD);
-        while((!(eecd & E1000_EECD_GNT)) &&
-              (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
-            i++;
-            usec_delay(5);
-            eecd = E1000_READ_REG(hw, EECD);
-        }
-        if(!(eecd & E1000_EECD_GNT)) {
-            eecd &= ~E1000_EECD_REQ;
+        /* Request EEPROM Access */
+        if(hw->mac_type > em_82544) {
+            eecd |= E1000_EECD_REQ;
             E1000_WRITE_REG(hw, EECD, eecd);
-            DEBUGOUT("Could not acquire EEPROM grant\n");
-	    em_put_hw_eeprom_semaphore(hw);
-            return -E1000_ERR_EEPROM;
+            eecd = E1000_READ_REG(hw, EECD);
+            while((!(eecd & E1000_EECD_GNT)) &&
+                  (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+                i++;
+                usec_delay(5);
+                eecd = E1000_READ_REG(hw, EECD);
+            }
+            if(!(eecd & E1000_EECD_GNT)) {
+                eecd &= ~E1000_EECD_REQ;
+                E1000_WRITE_REG(hw, EECD, eecd);
+                DEBUGOUT("Could not acquire EEPROM grant\n");
+                em_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
+                return -E1000_ERR_EEPROM;
+            }
         }
     }
-    }
 
     /* Setup EEPROM for Read/Write */
 
@@ -3782,7 +4390,7 @@ em_release_eeprom(struct em_hw *hw)
         E1000_WRITE_REG(hw, EECD, eecd);
     }
 
-    em_put_hw_eeprom_semaphore(hw);
+    em_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
 }
 
 /******************************************************************************
@@ -3857,17 +4465,21 @@ em_read_eeprom(struct em_hw *hw,
         return -E1000_ERR_EEPROM;
     }
 
-    /* FLASH reads without acquiring the semaphore are safe in 82573-based
-     * controllers.
-     */
-    if ((em_is_onboard_nvm_eeprom(hw) == TRUE) ||
-        (hw->mac_type != em_82573)) {
-        /* Prepare the EEPROM for reading  */
-        if(em_acquire_eeprom(hw) != E1000_SUCCESS)
-            return -E1000_ERR_EEPROM;
+    /* FLASH reads without acquiring the semaphore are safe */
+    if (em_is_onboard_nvm_eeprom(hw) == TRUE &&
+	hw->eeprom.use_eerd == FALSE) {
+        switch (hw->mac_type) {
+        case em_80003es2lan:
+            break;
+        default:
+            /* Prepare the EEPROM for reading  */
+            if (em_acquire_eeprom(hw) != E1000_SUCCESS)
+                return -E1000_ERR_EEPROM;
+            break;
+        }
     }
 
-    if(eeprom->use_eerd == TRUE) {
+    if (eeprom->use_eerd == TRUE) {
         ret_val = em_read_eeprom_eerd(hw, offset, words, data);
         if ((em_is_onboard_nvm_eeprom(hw) == TRUE) ||
             (hw->mac_type != em_82573))
@@ -3976,6 +4588,9 @@ em_write_eeprom_eewr(struct em_hw *hw,
     uint32_t    i              = 0;
     int32_t     error          = 0;
 
+    if (em_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+        return -E1000_ERR_SWFW_SYNC;
+
     for (i = 0; i < words; i++) {
         register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | 
                          ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | 
@@ -3995,6 +4610,7 @@ em_write_eeprom_eewr(struct em_hw *hw,
         }       
     }
     
+    em_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
     return error;
 }
 
@@ -4036,6 +4652,8 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
 {
     uint32_t eecd = 0;
 
+    DEBUGFUNC("em_is_onboard_nvm_eeprom");
+
     if(hw->mac_type == em_82573) {
         eecd = E1000_READ_REG(hw, EECD);
 
@@ -4374,7 +4992,7 @@ em_commit_shadow_ram(struct em_hw *hw)
             return -E1000_ERR_EEPROM;
         }
 
-	/* If STM opcode located in bits 15:8 of flop, reset firmware */
+        /* If STM opcode located in bits 15:8 of flop, reset firmware */
         if ((flop & 0xFF00) == E1000_STM_OPCODE) {
             E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
         }
@@ -4382,7 +5000,7 @@ em_commit_shadow_ram(struct em_hw *hw)
         /* Perform the flash update */
         E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
 
-	for (i=0; i < attempts; i++) {
+        for (i=0; i < attempts; i++) {
             eecd = E1000_READ_REG(hw, EECD);
             if ((eecd & E1000_EECD_FLUPD) == 0) {
                 break;
@@ -4455,14 +5073,17 @@ em_read_mac_addr(struct em_hw * hw)
         hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
         hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
     }
+
     switch (hw->mac_type) {
+    default:
+        break;
     case em_82546:
     case em_82546_rev_3:
     case em_82571:
-	if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
-		hw->perm_mac_addr[5] ^= 0x01;
-    default:
-	break;
+    case em_80003es2lan:
+        if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+            hw->perm_mac_addr[5] ^= 0x01;
+        break;
     }
 
     for(i = 0; i < NODE_ADDRESS_SIZE; i++)
@@ -4498,7 +5119,7 @@ em_init_rx_addrs(struct em_hw *hw)
      * an 82571 issue in which a reset on one port will reload the MAC on
      * the other port. */
     if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE))
-	rar_num -= 1;
+        rar_num -= 1;
     /* Zero out the other 15 receive addresses. */
     DEBUGOUT("Clearing RAR[1-15]\n");
     for(i = 1; i < rar_num; i++) {
@@ -4545,7 +5166,7 @@ em_mc_addr_list_update(struct em_hw *hw,
      * an 82571 issue in which a reset on one port will reload the MAC on
      * the other port. */
     if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE))
-	num_rar_entry -= 1;
+        num_rar_entry -= 1;
 
     for(i = rar_used_count; i < num_rar_entry; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
@@ -4696,8 +5317,37 @@ em_rar_set(struct em_hw *hw,
     rar_low = ((uint32_t) addr[0] |
                ((uint32_t) addr[1] << 8) |
                ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8));
 
-    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV);
+    /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+     * unit hang.
+     *
+     * Description:
+     * If there are any Rx frames queued up or otherwise present in the HW
+     * before RSS is enabled, and then we enable RSS, the HW Rx unit will
+     * hang.  To work around this issue, we have to disable receives and
+     * flush out all Rx frames before we enable RSS. To do so, we modify we
+     * redirect all Rx traffic to manageability and then reset the HW.
+     * This flushes away Rx frames, and (since the redirections to
+     * manageability persists across resets) keeps new ones from coming in
+     * while we work.  Then, we clear the Address Valid AV bit for all MAC
+     * addresses and undo the re-direction to manageability.
+     * Now, frames are coming in again, but the MAC won't accept them, so
+     * far so good.  We now proceed to initialize RSS (if necessary) and
+     * configure the Rx unit.  Last, we re-enable the AV bits and continue
+     * on our merry way.
+     */
+    switch (hw->mac_type) {
+    case em_82571:
+    case em_82572:
+    case em_80003es2lan:
+        if (hw->leave_av_bit_off == TRUE)
+            break;
+    default:
+        /* Indicate to hardware the Address is Valid. */
+        rar_high |= E1000_RAH_AV;
+        break;
+    }
 
     E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
     E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
@@ -5104,7 +5754,6 @@ em_clear_hw_cntrs(struct em_hw *hw)
     temp = E1000_READ_REG(hw, ICTXQEC);
     temp = E1000_READ_REG(hw, ICTXQMTC);
     temp = E1000_READ_REG(hw, ICRXDMTC);
-
 }
 
 /******************************************************************************
@@ -5275,11 +5924,12 @@ em_get_bus_info(struct em_hw *hw)
     case em_82573:
         hw->bus_type = em_bus_type_pci_express;
         hw->bus_speed = em_bus_speed_2500;
-	hw->bus_width = em_bus_width_pciex_1;
-	break;
+        hw->bus_width = em_bus_width_pciex_1;
+        break;
     case em_82571:
-	hw->bus_type = em_bus_type_pci_express;
-	hw->bus_speed = em_bus_speed_2500;
+    case em_80003es2lan:
+        hw->bus_type = em_bus_type_pci_express;
+        hw->bus_speed = em_bus_speed_2500;
         hw->bus_width = em_bus_width_pciex_4;
         break;
     default:
@@ -5420,6 +6070,34 @@ em_get_cable_length(struct em_hw *hw,
             return -E1000_ERR_PHY;
             break;
         }
+    } else if (hw->phy_type == em_phy_gg82563) {
+        ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
+                                     &phy_data);
+        if (ret_val)
+            return ret_val;
+        cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH;
+
+        switch (cable_length) {
+        case em_gg_cable_length_60:
+            *min_length = 0;
+            *max_length = em_igp_cable_length_60;
+            break;
+        case em_gg_cable_length_60_115:
+            *min_length = em_igp_cable_length_60;
+            *max_length = em_igp_cable_length_115;
+            break;
+        case em_gg_cable_length_115_150:
+            *min_length = em_igp_cable_length_115;
+            *max_length = em_igp_cable_length_150;
+            break;
+        case em_gg_cable_length_150:
+            *min_length = em_igp_cable_length_150;
+            *max_length = em_igp_cable_length_180;
+            break;
+        default:
+            return -E1000_ERR_PHY;
+            break;
+        }
     } else if(hw->phy_type == em_phy_igp) { /* For IGP PHY */
         uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
                                                          {IGP01E1000_PHY_AGC_A,
@@ -5466,50 +6144,39 @@ em_get_cable_length(struct em_hw *hw,
         *max_length = em_igp_cable_length_table[agc_value] +
                       IGP01E1000_AGC_RANGE;
     } else if (hw->phy_type == em_phy_igp_2) {
-		uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
-		   {IGP02E1000_PHY_AGC_A,
-		    IGP02E1000_PHY_AGC_B,
-		    IGP02E1000_PHY_AGC_C,
-		    IGP02E1000_PHY_AGC_D};
-
-		/* Read the AGC registers for all channels */
-		for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
-			ret_val = em_read_phy_reg(hw, agc_reg_array[i],
-			    &phy_data);
-			if (ret_val)
-				return ret_val;
-
-			/*
-			 * Getting bits 15:9, which represent the combination
-			 * of course and fine gain values. The result is a
-			 * number that can be put into the lookup table to
-			 * obtain the approximate cable length.
-			 */
-			cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
-			    IGP02E1000_AGC_LENGTH_MASK;
-
-			/* Remove min & max AGC values from calculation. */
-			if (em_igp_2_cable_length_table[min_agc] >
-			    em_igp_2_cable_length_table[cur_agc])
-				min_agc = cur_agc;
-			if (em_igp_2_cable_length_table[max_agc] <
-			    em_igp_2_cable_length_table[cur_agc])
-				max_agc = cur_agc;
-
-			agc_value += em_igp_2_cable_length_table[cur_agc];
-		}
-
-		agc_value -= (em_igp_2_cable_length_table[min_agc] +
-		    em_igp_2_cable_length_table[max_agc]);
-		agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
-
-		/*
-		 * Calculate cable length with the error range
-		 * of +/- 10 meters.
-		 */
-		*min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
-		     (agc_value - IGP02E1000_AGC_RANGE) : 0;
-		*max_length = agc_value + IGP02E1000_AGC_RANGE;
+        uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+                                                         {IGP02E1000_PHY_AGC_A,
+                                                          IGP02E1000_PHY_AGC_B,
+                                                          IGP02E1000_PHY_AGC_C,
+                                                          IGP02E1000_PHY_AGC_D};
+        /* Read the AGC registers for all channels */
+        for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
+            ret_val = em_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+            if (ret_val)
+                return ret_val;
+
+	    /* Getting bits 15:9, which represent the combination of course and
+             * fine gain values.  The result is a number that can be put into
+             * the lookup table to obtain the approximate cable length. */
+            cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+                      IGP02E1000_AGC_LENGTH_MASK;
+
+            /* Remove min & max AGC values from calculation. */
+            if (em_igp_2_cable_length_table[min_agc] > em_igp_2_cable_length_table[cur_agc])
+                min_agc = cur_agc;
+	    if (em_igp_2_cable_length_table[max_agc] < em_igp_2_cable_length_table[cur_agc])
+                max_agc = cur_agc;
+
+            agc_value += em_igp_2_cable_length_table[cur_agc];
+        }
+
+        agc_value -= (em_igp_2_cable_length_table[min_agc] + em_igp_2_cable_length_table[max_agc]);
+        agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
+
+        /* Calculate cable length with the error range of +/- 10 meters. */
+        *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+                       (agc_value - IGP02E1000_AGC_RANGE) : 0;
+        *max_length = agc_value + IGP02E1000_AGC_RANGE;
     }
 
     return E1000_SUCCESS;
@@ -5540,7 +6207,8 @@ em_check_polarity(struct em_hw *hw,
 
     DEBUGFUNC("em_check_polarity");
 
-    if(hw->phy_type == em_phy_m88) {
+    if ((hw->phy_type == em_phy_m88) ||
+        (hw->phy_type == em_phy_gg82563)) {
         /* return the Polarity bit in the Status register. */
         ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
@@ -5609,7 +6277,8 @@ em_check_downshift(struct em_hw *hw)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
-    } else if(hw->phy_type == em_phy_m88) {
+    } else if ((hw->phy_type == em_phy_m88) ||
+               (hw->phy_type == em_phy_gg82563)) {
         ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
         if(ret_val)
@@ -6634,9 +7303,13 @@ em_get_auto_rd_done(struct em_hw *hw)
     DEBUGFUNC("em_get_auto_rd_done");
 
     switch (hw->mac_type) {
-    case em_82573:
+    default:
+        msec_delay(5);
+        break;
     case em_82571:
     case em_82572:
+    case em_82573:
+    case em_80003es2lan:
         while(timeout) {
             if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
             else msec_delay(1);
@@ -6648,15 +7321,13 @@ em_get_auto_rd_done(struct em_hw *hw)
             return -E1000_ERR_RESET;
         }
         break;
-    default:
-        msec_delay(5);
     }
 
     /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
      * Need to wait for PHY configuration completion before accessing NVM
      * and PHY. */
     if (hw->mac_type == em_82573)
-	msec_delay(25);
+        msec_delay(25);
 
     return E1000_SUCCESS;
 }
@@ -6673,32 +7344,38 @@ em_get_auto_rd_done(struct em_hw *hw)
 int32_t
 em_get_phy_cfg_done(struct em_hw *hw)
 {
-	int32_t timeout = PHY_CFG_TIMEOUT;
-	uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
-
-	DEBUGFUNC("em_get_phy_cfg_done");
-
-	switch (hw->mac_type) {
-	case em_82571:
-	case em_82572:
-		while (timeout) {
-			if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
-				break;
-			else
-				msec_delay(1);
-			timeout--;
-		}
-
-		if (!timeout) {
-			DEBUGOUT("MNG configuration cycle has not completed.\n");
-			return -E1000_ERR_RESET;
-		}
-		break;
-	default:
-		msec_delay(10);
-	}
-
-	return E1000_SUCCESS;
+    int32_t timeout = PHY_CFG_TIMEOUT;
+    uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
+
+    DEBUGFUNC("em_get_phy_cfg_done");
+
+    switch (hw->mac_type) {
+    default:
+        msec_delay(10);
+        break;
+    case em_80003es2lan:
+        /* Separate *_CFG_DONE_* bit for each port */
+        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+            cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
+        /* Fall Through */
+    case em_82571:
+    case em_82572:
+        while (timeout) {
+            if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+                break;
+            else
+                msec_delay(1);
+            timeout--;
+        }
+
+        if (!timeout) {
+            DEBUGOUT("MNG configuration cycle has not completed.\n");
+            return -E1000_ERR_RESET;
+        }
+        break;
+    }
+
+    return E1000_SUCCESS;
 }
 
 /***************************************************************************
@@ -6723,6 +7400,11 @@ em_get_hw_eeprom_semaphore(struct em_hw *hw)
     if(!hw->eeprom_semaphore_present)
         return E1000_SUCCESS;
 
+    if (hw->mac_type == em_80003es2lan) {
+        /* Get the SW semaphore. */
+        if (em_get_software_semaphore(hw) != E1000_SUCCESS)
+            return -E1000_ERR_EEPROM;
+    }
 
     /* Get the FW semaphore. */
     timeout = hw->eeprom.word_size + 1;
@@ -6768,7 +7450,72 @@ em_put_hw_eeprom_semaphore(struct em_hw *hw)
         return;
 
     swsm = E1000_READ_REG(hw, SWSM);
-    swsm &= ~(E1000_SWSM_SWESMBI);
+    if (hw->mac_type == em_80003es2lan) {
+        /* Release both semaphores. */
+        swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+    } else
+        swsm &= ~(E1000_SWSM_SWESMBI);
+    E1000_WRITE_REG(hw, SWSM, swsm);
+}
+
+/***************************************************************************
+ *
+ * Obtaining software semaphore bit (SMBI) before resetting PHY.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to obtain semaphore.
+ *            E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+em_get_software_semaphore(struct em_hw *hw)
+{
+    int32_t timeout = hw->eeprom.word_size + 1;
+    uint32_t swsm;
+
+    DEBUGFUNC("em_get_software_semaphore");
+
+    if (hw->mac_type != em_80003es2lan)
+        return E1000_SUCCESS;
+
+    while(timeout) {
+        swsm = E1000_READ_REG(hw, SWSM);
+        /* If SMBI bit cleared, it is now set and we hold the semaphore */
+        if(!(swsm & E1000_SWSM_SMBI))
+            break;
+        msec_delay_irq(1);
+        timeout--;
+    }
+
+    if(!timeout) {
+        DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
+        return -E1000_ERR_RESET;
+    }
+
+    return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Release semaphore bit (SMBI).
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+void
+em_release_software_semaphore(struct em_hw *hw)
+{
+    uint32_t swsm;
+
+    DEBUGFUNC("em_release_software_semaphore");
+
+    if (hw->mac_type != em_80003es2lan)
+        return;
+
+    swsm = E1000_READ_REG(hw, SWSM);
+    /* Release the SW semaphores.*/
+    swsm &= ~E1000_SWSM_SMBI;
     E1000_WRITE_REG(hw, SWSM, swsm);
 }
 
@@ -6787,6 +7534,7 @@ int32_t
 em_check_phy_reset_block(struct em_hw *hw)
 {
     uint32_t manc = 0;
+
     if (hw->mac_type > em_82547_rev_2)
         manc = E1000_READ_REG(hw, MANC);
     return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
@@ -6807,6 +7555,7 @@ em_arc_subsystem_valid(struct em_hw *hw)
     case em_82571:
     case em_82572:
     case em_82573:
+    case em_80003es2lan:
         fwsm = E1000_READ_REG(hw, FWSM);
         if((fwsm & E1000_FWSM_MODE_MASK) != 0)
             return TRUE;
diff --git a/sys/dev/em/if_em_hw.h b/sys/dev/em/if_em_hw.h
index d23d2b6..c040469 100644
--- a/sys/dev/em/if_em_hw.h
+++ b/sys/dev/em/if_em_hw.h
@@ -66,6 +66,7 @@ typedef enum {
     em_82571,
     em_82572,
     em_82573,
+    em_80003es2lan,
     em_num_macs
 } em_mac_type;
 
@@ -145,6 +146,13 @@ typedef enum {
 } em_cable_length;
 
 typedef enum {
+    em_gg_cable_length_60 = 0,
+    em_gg_cable_length_60_115 = 1,
+    em_gg_cable_length_115_150 = 2,
+    em_gg_cable_length_150 = 4
+} em_gg_cable_length;
+
+typedef enum {
     em_igp_cable_length_10  = 10,
     em_igp_cable_length_20  = 20,
     em_igp_cable_length_30  = 30,
@@ -214,6 +222,7 @@ typedef enum {
     em_phy_m88 = 0,
     em_phy_igp,
     em_phy_igp_2,
+    em_phy_gg82563,
     em_phy_undefined = 0xFF
 } em_phy_type;
 
@@ -287,6 +296,7 @@ typedef enum {
 #define E1000_ERR_MASTER_REQUESTS_PENDING 10
 #define E1000_ERR_HOST_INTERFACE_COMMAND 11
 #define E1000_BLK_PHY_RESET   12
+#define E1000_ERR_SWFW_SYNC 13
 
 /* Function prototypes */
 /* Initialization */
@@ -319,6 +329,9 @@ int32_t em_get_cable_length(struct em_hw *hw, uint16_t *min_length, uint16_t *ma
 int32_t em_check_polarity(struct em_hw *hw, uint16_t *polarity);
 int32_t em_check_downshift(struct em_hw *hw);
 int32_t em_validate_mdi_setting(struct em_hw *hw);
+int32_t em_read_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *data);
+int32_t em_write_kmrn_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t data);
+int32_t em_duplex_reversal(struct em_hw *hw);
 
 /* EEPROM Functions */
 int32_t em_init_eeprom_params(struct em_hw *hw);
@@ -357,18 +370,6 @@ struct em_host_mng_command_info {
     struct em_host_mng_command_header command_header;  /* Command Head/Command Result Head has 4 bytes */
     uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH];   /* Command data can length 0..0x658*/
 };
-#ifdef __BIG_ENDIAN
-struct em_host_mng_dhcp_cookie{
-    uint32_t signature;
-    uint16_t vlan_id;
-    uint8_t reserved0;
-    uint8_t status;
-    uint32_t reserved1;
-    uint8_t checksum;
-    uint8_t reserved3;
-    uint16_t reserved2;
-};
-#else
 struct em_host_mng_dhcp_cookie{
     uint32_t signature;
     uint8_t status;
@@ -379,7 +380,6 @@ struct em_host_mng_dhcp_cookie{
     uint8_t reserved3;
     uint8_t checksum;
 };
-#endif
 
 int32_t em_mng_write_dhcp_info(struct em_hw *hw, uint8_t *buffer, 
 							uint16_t length);
@@ -447,6 +447,7 @@ int32_t em_get_hw_eeprom_semaphore(struct em_hw *hw);
 void em_put_hw_eeprom_semaphore(struct em_hw *hw);
 int32_t em_commit_shadow_ram(struct em_hw *hw);
 uint8_t em_arc_subsystem_valid(struct em_hw *hw);
+int32_t em_set_pci_ex_no_snoop(struct em_hw *hw, uint32_t no_snoop);
 
 #define E1000_BAR_TYPE(v)		((v) & E1000_BAR_TYPE_MASK)
 #define E1000_BAR_TYPE_MASK		0x00000001
@@ -457,10 +458,12 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw);
 #define E1000_BAR_MEM_TYPE_32BIT	0x00000000
 #define E1000_BAR_MEM_TYPE_64BIT	0x00000004
 
+#ifndef E1000_READ_REG_IO
 #define E1000_READ_REG_IO(a, reg) \
     em_read_reg_io((a), E1000_##reg)
 #define E1000_WRITE_REG_IO(a, reg, val) \
     em_write_reg_io((a), E1000_##reg, val)
+#endif
 
 /* PCI Device IDs */
 #define E1000_DEV_ID_82542               0x1000
@@ -495,6 +498,7 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw);
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
 #define E1000_DEV_ID_82547EI             0x1019
 #define E1000_DEV_ID_82547EI_MOBILE      0x101A
 #define E1000_DEV_ID_82571EB_COPPER      0x105E
@@ -503,11 +507,14 @@ uint8_t em_arc_subsystem_valid(struct em_hw *hw);
 #define E1000_DEV_ID_82572EI_COPPER      0x107D
 #define E1000_DEV_ID_82572EI_FIBER       0x107E
 #define E1000_DEV_ID_82572EI_SERDES      0x107F
+#define E1000_DEV_ID_82572EI             0x10B9
 #define E1000_DEV_ID_82573E              0x108B
 #define E1000_DEV_ID_82573E_IAMT         0x108C
 #define E1000_DEV_ID_82573L              0x109A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT     0x1098
 
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -866,7 +873,8 @@ struct em_ffvt_entry {
 #define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
 #define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 #define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-#define E1000_DISABLE_SERDES_LOOPBACK	0x0400
+
+#define E1000_DISABLE_SERDES_LOOPBACK   0x0400
 
 /* Register Set. (82543, 82544)
  *
@@ -910,6 +918,7 @@ struct em_ffvt_entry {
 #define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
 #define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
 #define E1000_TCTL     0x00400  /* TX Control - RW */
+#define E1000_TCTL_EXT 0x00404  /* Extended TX Control - RW */
 #define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
 #define E1000_TBT      0x00448  /* TX Burst Timer - RW */
 #define E1000_AIT      0x00458  /* Adaptive Interframe Spacing Throttle - RW */
@@ -962,14 +971,14 @@ struct em_ffvt_entry {
 #define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
 #define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
 #define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0    0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1   0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1   0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1   0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1     0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1     0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1  0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1    0x03940 /* TX Arbitration Count (1) */
+#define E1000_TARC0    0x03840  /* TX Arbitration Count (0) */
+#define E1000_TDBAL1   0x03900  /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1   0x03904  /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1   0x03908  /* TX Desc Length (1) - RW */
+#define E1000_TDH1     0x03910  /* TX Desc Head (1) - RW */
+#define E1000_TDT1     0x03918  /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1  0x03928  /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1    0x03940  /* TX Arbitration Count (1) */
 #define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
 #define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
 #define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
@@ -1056,6 +1065,11 @@ struct em_ffvt_entry {
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
 
+#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
+#define E1000_MDPHYA     0x0003C  /* PHY address - RW */
+#define E1000_MANC2H     0x05860  /* Managment Control To Host - RW */
+#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
+
 #define E1000_GCR       0x05B00 /* PCI-Ex Control */
 #define E1000_GSCL_1    0x05B10 /* PCI-Ex Statistic Control #1 */
 #define E1000_GSCL_2    0x05B14 /* PCI-Ex Statistic Control #2 */
@@ -1125,6 +1139,7 @@ struct em_ffvt_entry {
 #define E1000_82542_RXCW     E1000_RXCW
 #define E1000_82542_MTA      0x00200
 #define E1000_82542_TCTL     E1000_TCTL
+#define E1000_82542_TCTL_EXT E1000_TCTL_EXT
 #define E1000_82542_TIPG     E1000_TIPG
 #define E1000_82542_TDBAL    0x00420
 #define E1000_82542_TDBAH    0x00424
@@ -1272,6 +1287,8 @@ struct em_ffvt_entry {
 #define E1000_82542_RSSRK       E1000_RSSRK
 #define E1000_82542_RSSIM       E1000_RSSIM
 #define E1000_82542_RSSIR       E1000_RSSIR
+#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
+#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC
 
 /* Statistics counters collected by the MAC */
 struct em_hw_stats {
@@ -1363,6 +1380,7 @@ struct em_hw {
     em_ffe_config ffe_config_state;
     uint32_t asf_firmware_present;
     uint32_t eeprom_semaphore_present;
+    uint32_t swfw_sync_present;
     unsigned long io_base;
     uint32_t phy_id;
     uint32_t phy_revision;
@@ -1421,6 +1439,7 @@ struct em_hw {
     boolean_t ifs_params_forced;
     boolean_t in_ifs_mode;
     boolean_t mng_reg_access_disabled;
+    boolean_t leave_av_bit_off;
 };
 
 
@@ -1453,6 +1472,8 @@ struct em_hw {
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
 #define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
 #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
@@ -1489,6 +1510,16 @@ struct em_hw {
 #define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
 #define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
 #define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
+#define E1000_STATUS_BMC_SKU_0  0x00100000 /* BMC USB redirect disabled */
+#define E1000_STATUS_BMC_SKU_1  0x00200000 /* BMC SRAM disabled */
+#define E1000_STATUS_BMC_SKU_2  0x00400000 /* BMC SDRAM disabled */
+#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
+#define E1000_STATUS_BMC_LITE   0x01000000 /* BMC external code execution disabled */
+#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
+#define E1000_STATUS_FUSE_8       0x04000000
+#define E1000_STATUS_FUSE_9       0x08000000
+#define E1000_STATUS_SERDES0_DIS  0x10000000 /* SERDES disabled on port 0 */
+#define E1000_STATUS_SERDES1_DIS  0x20000000 /* SERDES disabled on port 1 */
 
 /* Constants used to intrepret the masked PCI-X bus speed. */
 #define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
@@ -1562,9 +1593,12 @@ struct em_hw {
 #define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
 #define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
 #define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
 #define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_KMRN    0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_SERDES  0x00C00000
 #define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
 #define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
 #define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
@@ -1574,6 +1608,9 @@ struct em_hw {
 #define E1000_CTRL_EXT_DRV_LOAD       0x10000000  /* Driver loaded bit for FW */
 #define E1000_CTRL_EXT_IAME           0x08000000  /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000  /* Clear Interrupt timers after IMS clear */
+#define E1000_CRTL_EXT_PB_PAREN       0x01000000 /* packet buffer parity error detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN       0x02000000 /* descriptor FIFO parity error detection enable */
+#define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
 
 /* MDI Control */
 #define E1000_MDIC_DATA_MASK 0x0000FFFF
@@ -1587,6 +1624,32 @@ struct em_hw {
 #define E1000_MDIC_INT_EN    0x20000000
 #define E1000_MDIC_ERROR     0x40000000
 
+#define E1000_KUMCTRLSTA_MASK           0x0000FFFF
+#define E1000_KUMCTRLSTA_OFFSET         0x001F0000
+#define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
+#define E1000_KUMCTRLSTA_REN            0x00200000
+
+#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL      0x00000000
+#define E1000_KUMCTRLSTA_OFFSET_CTRL           0x00000001
+#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL       0x00000002
+#define E1000_KUMCTRLSTA_OFFSET_DIAG           0x00000003
+#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS       0x00000004
+#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM      0x00000009
+#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL        0x00000010
+#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES     0x0000001E
+#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES      0x0000001F
+
+/* FIFO Control */
+#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS   0x00000008
+#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS   0x00000800
+
+/* In-Band Control */
+#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING  0x00000010
+
+/* Half-Duplex Control */
+#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT  0x00000000
+
 /* LED Control */
 #define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
 #define E1000_LEDCTL_LED0_MODE_SHIFT      0
@@ -1649,6 +1712,13 @@ struct em_hw {
 #define E1000_ICR_MNG           0x00040000 /* Manageability event */
 #define E1000_ICR_DOCK          0x00080000 /* Dock/Undock */
 #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR  0x00400000 /* host arb read buffer parity error */
+#define E1000_ICR_PB_PAR        0x00800000 /* packet buffer parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_ICR_ALL_PARITY    0x03F00000 /* all parity error bits */
 
 /* Interrupt Cause Set */
 #define E1000_ICS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1669,6 +1739,12 @@ struct em_hw {
 #define E1000_ICS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_ICS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_ICS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Interrupt Mask Set */
 #define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1689,6 +1765,12 @@ struct em_hw {
 #define E1000_IMS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMS_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Interrupt Mask Clear */
 #define E1000_IMC_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
@@ -1709,6 +1791,12 @@ struct em_hw {
 #define E1000_IMC_ACK       E1000_ICR_ACK       /* Receive Ack frame */
 #define E1000_IMC_MNG       E1000_ICR_MNG       /* Manageability event */
 #define E1000_IMC_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMC_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer parity error */
+#define E1000_IMC_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity error */
+#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
 
 /* Receive Control */
 #define E1000_RCTL_RST            0x00000001    /* Software reset */
@@ -1778,6 +1866,12 @@ struct em_hw {
 #define E1000_PSRCTL_BSIZE2_SHIFT  6            /* Shift _left_ 6 */
 #define E1000_PSRCTL_BSIZE3_SHIFT 14            /* Shift _left_ 14 */
 
+/* SW_W_SYNC definitions */
+#define E1000_SWFW_EEP_SM     0x0001
+#define E1000_SWFW_PHY0_SM    0x0002
+#define E1000_SWFW_PHY1_SM    0x0004
+#define E1000_SWFW_MAC_CSR_SM 0x0008
+
 /* Receive Descriptor */
 #define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
 #define E1000_RDT_FPDB  0x80000000      /* Flush descriptor block */
@@ -1823,7 +1917,6 @@ struct em_hw {
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
 #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
                                               still to be processed. */
-
 /* Transmit Configuration Word */
 #define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
 #define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
@@ -1857,6 +1950,11 @@ struct em_hw {
 #define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
 #define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
 #define E1000_TCTL_MULR   0x10000000    /* Multiple request support */
+/* Extended Transmit Control */
+#define E1000_TCTL_EXT_BST_MASK  0x000003FF /* Backoff Slot Time */
+#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
+
+#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX   0x00010000
 
 /* Receive Checksum Control */
 #define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
@@ -1934,6 +2032,7 @@ struct em_hw {
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_RCV_ALL       0x00080000 /* Receive All Enabled */
 #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
 #define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000 /* Enable MAC address
                                                     * filtering */
@@ -2019,6 +2118,23 @@ struct em_host_command_info {
 
 #define E1000_MDALIGN          4096
 
+/* PCI-Ex registers*/
+
+/* PCI-Ex Control Register */
+#define E1000_GCR_RXD_NO_SNOOP          0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP       0x00000004
+#define E1000_GCR_TXD_NO_SNOOP          0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP       0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP       0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP         | \
+                             E1000_GCR_RXDSCW_NO_SNOOP      | \
+                             E1000_GCR_RXDSCR_NO_SNOOP      | \
+                             E1000_GCR_TXD_NO_SNOOP         | \
+                             E1000_GCR_TXDSCW_NO_SNOOP      | \
+                             E1000_GCR_TXDSCR_NO_SNOOP)
+
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
@@ -2078,12 +2194,14 @@ struct em_host_command_info {
 #define EEPROM_INIT_CONTROL1_REG      0x000A
 #define EEPROM_INIT_CONTROL2_REG      0x000F
 #define EEPROM_INIT_CONTROL3_PORT_B   0x0014
+#define EEPROM_INIT_3GIO_3            0x001A
 #define EEPROM_INIT_CONTROL3_PORT_A   0x0024
 #define EEPROM_CFG                    0x0012
 #define EEPROM_FLASH_VERSION          0x0032
 #define EEPROM_CHECKSUM_REG           0x003F
 
 #define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */
+#define E1000_EEPROM_CFG_DONE_PORT_1  0x00080000   /* ...for second port */
 
 /* Word definitions for ID LED Settings */
 #define ID_LED_RESERVED_0000 0x0000
@@ -2127,6 +2245,9 @@ struct em_host_command_info {
 #define EEPROM_WORD0F_ANE        0x0800
 #define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
 
+/* Mask bits for fields in Word 0x1a of the EEPROM */
+#define EEPROM_WORD1A_ASPM_MASK  0x000C
+
 /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
 #define EEPROM_SUM 0xBABA
 
@@ -2142,7 +2263,10 @@ struct em_host_command_info {
 /* Collision related configuration parameters */
 #define E1000_COLLISION_THRESHOLD       15
 #define E1000_CT_SHIFT                  4
-#define E1000_COLLISION_DISTANCE        64
+/* Collision distance is a 0-based value that applies to
+ * half-duplex-capable hardware only. */
+#define E1000_COLLISION_DISTANCE        63
+#define E1000_COLLISION_DISTANCE_82542  64
 #define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
 #define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
 #define E1000_COLD_SHIFT                12
@@ -2166,8 +2290,11 @@ struct em_host_command_info {
 
 #define DEFAULT_82542_TIPG_IPGR2 10
 #define DEFAULT_82543_TIPG_IPGR2 6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
 #define E1000_TIPG_IPGR2_SHIFT  20
 
+#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009
+#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000   0x00000008
 #define E1000_TXDMAC_DPP 0x00000001
 
 /* Adaptive IFS defines */
@@ -2408,6 +2535,79 @@ struct em_host_command_info {
 
 #define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
 
+/* Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define GG82563_PAGE_SHIFT        5
+#define GG82563_REG(page, reg)    \
+        (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG       30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL           \
+        GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS         \
+        GG82563_REG(0, 17) /* PHY Specific Status */
+#define GG82563_PHY_INT_ENABLE          \
+        GG82563_REG(0, 18) /* Interrupt Enable */
+#define GG82563_PHY_SPEC_STATUS_2       \
+        GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_RX_ERR_CNTR         \
+        GG82563_REG(0, 21) /* Receive Error Counter */
+#define GG82563_PHY_PAGE_SELECT         \
+        GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2         \
+        GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_PAGE_SELECT_ALT     \
+        GG82563_REG(0, 29) /* Alternate Page Select */
+#define GG82563_PHY_TEST_CLK_CTRL       \
+        GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
+
+#define GG82563_PHY_MAC_SPEC_CTRL       \
+        GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2     \
+        GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+#define GG82563_PHY_DSP_DISTANCE    \
+        GG82563_REG(5, 26) /* DSP Distance */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL   \
+        GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_PORT_RESET          \
+        GG82563_REG(193, 17) /* Port Reset */
+#define GG82563_PHY_REVISION_ID         \
+        GG82563_REG(193, 18) /* Revision ID */
+#define GG82563_PHY_DEVICE_ID           \
+        GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL       \
+        GG82563_REG(193, 20) /* Power Management Control */
+#define GG82563_PHY_RATE_ADAPT_CTRL     \
+        GG82563_REG(193, 25) /* Rate Adaptation Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
+        GG82563_REG(194, 16) /* FIFO's Control/Status */
+#define GG82563_PHY_KMRN_CTRL           \
+        GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL         \
+        GG82563_REG(194, 18) /* Inband Control */
+#define GG82563_PHY_KMRN_DIAGNOSTIC     \
+        GG82563_REG(194, 19) /* Diagnostic */
+#define GG82563_PHY_ACK_TIMEOUTS        \
+        GG82563_REG(194, 20) /* Acknowledge Timeouts */
+#define GG82563_PHY_ADV_ABILITY         \
+        GG82563_REG(194, 21) /* Advertised Ability */
+#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
+        GG82563_REG(194, 23) /* Link Partner Advertised Ability */
+#define GG82563_PHY_ADV_NEXT_PAGE       \
+        GG82563_REG(194, 24) /* Advertised Next Page */
+#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
+        GG82563_REG(194, 25) /* Link Partner Advertised Next page */
+#define GG82563_PHY_KMRN_MISC           \
+        GG82563_REG(194, 26) /* Misc. */
+
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
 #define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
@@ -2720,6 +2920,113 @@ struct em_host_command_info {
 #define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
 #define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
+/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
+#define GG82563_PSCR_DISABLE_JABBER             0x0001 /* 1=Disable Jabber */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Polarity Reversal Disabled */
+#define GG82563_PSCR_POWER_DOWN                 0x0004 /* 1=Power Down */
+#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE  0x0008 /* 1=Transmitter Disabled */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK        0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI         0x0000 /* 00=Manual MDI configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX        0x0020 /* 01=Manual MDIX configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Automatic crossover */
+#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE   0x0080 /* 1=Enable Extended Distance */
+#define GG82563_PSCR_ENERGY_DETECT_MASK         0x0300
+#define GG82563_PSCR_ENERGY_DETECT_OFF          0x0000 /* 00,01=Off */
+#define GG82563_PSCR_ENERGY_DETECT_RX           0x0200 /* 10=Sense on Rx only (Energy Detect) */
+#define GG82563_PSCR_ENERGY_DETECT_RX_TM        0x0300 /* 11=Sense and Tx NLP */
+#define GG82563_PSCR_FORCE_LINK_GOOD            0x0400 /* 1=Force Link Good */
+#define GG82563_PSCR_DOWNSHIFT_ENABLE           0x0800 /* 1=Enable Downshift */
+#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK     0x7000
+#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT    12
+
+/* PHY Specific Status Register (Page 0, Register 17) */
+#define GG82563_PSSR_JABBER                0x0001 /* 1=Jabber */
+#define GG82563_PSSR_POLARITY              0x0002 /* 1=Polarity Reversed */
+#define GG82563_PSSR_LINK                  0x0008 /* 1=Link is Up */
+#define GG82563_PSSR_ENERGY_DETECT         0x0010 /* 1=Sleep, 0=Active */
+#define GG82563_PSSR_DOWNSHIFT             0x0020 /* 1=Downshift */
+#define GG82563_PSSR_CROSSOVER_STATUS      0x0040 /* 1=MDIX, 0=MDI */
+#define GG82563_PSSR_RX_PAUSE_ENABLED      0x0100 /* 1=Receive Pause Enabled */
+#define GG82563_PSSR_TX_PAUSE_ENABLED      0x0200 /* 1=Transmit Pause Enabled */
+#define GG82563_PSSR_LINK_UP               0x0400 /* 1=Link Up */
+#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */
+#define GG82563_PSSR_PAGE_RECEIVED         0x1000 /* 1=Page Received */
+#define GG82563_PSSR_DUPLEX                0x2000 /* 1-Full-Duplex */
+#define GG82563_PSSR_SPEED_MASK            0xC000
+#define GG82563_PSSR_SPEED_10MBPS          0x0000 /* 00=10Mbps */
+#define GG82563_PSSR_SPEED_100MBPS         0x4000 /* 01=100Mbps */
+#define GG82563_PSSR_SPEED_1000MBPS        0x8000 /* 10=1000Mbps */
+
+/* PHY Specific Status Register 2 (Page 0, Register 19) */
+#define GG82563_PSSR2_JABBER                0x0001 /* 1=Jabber */
+#define GG82563_PSSR2_POLARITY_CHANGED      0x0002 /* 1=Polarity Changed */
+#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */
+#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT   0x0020 /* 1=Downshift Detected */
+#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE  0x0040 /* 1=Crossover Changed */
+#define GG82563_PSSR2_FALSE_CARRIER         0x0100 /* 1=False Carrier */
+#define GG82563_PSSR2_SYMBOL_ERROR          0x0200 /* 1=Symbol Error */
+#define GG82563_PSSR2_LINK_STATUS_CHANGED   0x0400 /* 1=Link Status Changed */
+#define GG82563_PSSR2_AUTO_NEG_COMPLETED    0x0800 /* 1=Auto-Neg Completed */
+#define GG82563_PSSR2_PAGE_RECEIVED         0x1000 /* 1=Page Received */
+#define GG82563_PSSR2_DUPLEX_CHANGED        0x2000 /* 1=Duplex Changed */
+#define GG82563_PSSR2_SPEED_CHANGED         0x4000 /* 1=Speed Changed */
+#define GG82563_PSSR2_AUTO_NEG_ERROR        0x8000 /* 1=Auto-Neg Error */
+
+/* PHY Specific Control Register 2 (Page 0, Register 26) */
+#define GG82563_PSCR2_10BT_POLARITY_FORCE           0x0002 /* 1=Force Negative Polarity */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK       0x000C
+#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL     0x0000 /* 00,01=Normal Operation */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS      0x0008 /* 10=Select 112ns Sequence */
+#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS       0x000C /* 11=Select 16ns Sequence */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG              0x2000 /* 1=Reverse Auto-Negotiation */
+#define GG82563_PSCR2_1000BT_DISABLE                0x4000 /* 1=Disable 1000BASE-T */
+#define GG82563_PSCR2_TRANSMITER_TYPE_MASK          0x8000
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B      0x0000 /* 0=Class B */
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A      0x8000 /* 1=Class A */
+
+/* MAC Specific Control Register (Page 2, Register 21) */
+/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
+#define GG82563_MSCR_TX_CLK_MASK                    0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ           0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ           0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ         0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ          0x0007
+
+#define GG82563_MSCR_ASSERT_CRS_ON_TX               0x0010 /* 1=Assert */
+
+/* DSP Distance Register (Page 5, Register 26) */
+#define GG82563_DSPD_CABLE_LENGTH               0x0007 /* 0 = <50M;
+							      1 = 50-80M;
+							      2 = 80-110M;
+							      3 = 110-140M;
+							      4 = >140M */
+
+/* Kumeran Mode Control Register (Page 193, Register 16) */
+#define GG82563_KMCR_PHY_LEDS_EN                    0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
+#define GG82563_KMCR_FORCE_LINK_UP                  0x0040 /* 1=Force Link Up */
+#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT         0x0080
+#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK     0x0400
+#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT          0x0400 /* 1=6.25MHz, 0=0.8MHz */
+#define GG82563_KMCR_PASS_FALSE_CARRIER             0x0800
+
+/* Power Management Control Register (Page 193, Register 20) */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE         0x0001 /* 1=Enalbe SERDES Electrical Idle */
+#define GG82563_PMCR_DISABLE_PORT                   0x0002 /* 1=Disable Port */
+#define GG82563_PMCR_DISABLE_SERDES                 0x0004 /* 1=Disable SERDES */
+#define GG82563_PMCR_REVERSE_AUTO_NEG               0x0008 /* 1=Enable Reverse Auto-Negotiation */
+#define GG82563_PMCR_DISABLE_1000_NON_D0            0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */
+#define GG82563_PMCR_DISABLE_1000                   0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */
+#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A           0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */
+#define GG82563_PMCR_FORCE_POWER_STATE              0x0080 /* 1=Force Power State */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK    0x0300
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR      0x0000 /* 00=Dr */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U     0x0100 /* 01=D0u */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A     0x0200 /* 10=D0a */
+#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3      0x0300 /* 11=D3 */
+
+/* In-Band Control Register (Page 194, Register 18) */
+#define GG82563_ICR_DIS_PADDING                     0x0010 /* Disable Padding Use */
+
 
 /* Bit definitions for valid PHY IDs. */
 /* I = Integrated
@@ -2734,6 +3041,7 @@ struct em_host_command_info {
 #define M88E1011_I_REV_4   0x04
 #define M88E1111_I_PHY_ID  0x01410CC0
 #define L1LXT971A_PHY_ID   0x001378E0
+#define GG82563_E_PHY_ID   0x01410CA0
 
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
-- 
cgit v1.1