summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2006-04-06 17:09:03 +0000
committerglebius <glebius@FreeBSD.org>2006-04-06 17:09:03 +0000
commit4c89b5bc10de411075e8b1c192f766c27c609e3c (patch)
treed80add45aacfa2cc9fa9730b598952765d5dfde7 /sys/dev
parent48062565def6f202e877dafe111cc5836f4b71b7 (diff)
downloadFreeBSD-src-4c89b5bc10de411075e8b1c192f766c27c609e3c.zip
FreeBSD-src-4c89b5bc10de411075e8b1c192f766c27c609e3c.tar.gz
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/em/LICENSE4
-rw-r--r--sys/dev/em/README83
-rw-r--r--sys/dev/em/if_em.c71
-rw-r--r--sys/dev/em/if_em_hw.c1293
-rw-r--r--sys/dev/em/if_em_hw.h358
5 files changed, 1478 insertions, 331 deletions
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
OpenPOWER on IntegriCloud