summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/e1000/e1000_hw.c53
-rw-r--r--src/drivers/net/e1000/e1000_hw.h1
2 files changed, 51 insertions, 3 deletions
diff --git a/src/drivers/net/e1000/e1000_hw.c b/src/drivers/net/e1000/e1000_hw.c
index f90f8712..1871dfc9 100644
--- a/src/drivers/net/e1000/e1000_hw.c
+++ b/src/drivers/net/e1000/e1000_hw.c
@@ -728,6 +728,17 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
icr = E1000_READ_REG(hw, ICR);
+ if (hw->mac_type == e1000_82571 && hw->laa_is_present == TRUE) {
+ /*
+ * Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed, the actual LAA is in one of the RARs and no
+ * incoming packets directed to this port are dropped.
+ * Eventually the LAA will be in RAR[0] and RAR[14].
+ */
+ e1000_rar_set(hw, hw->mac_addr, E1000_RAR_ENTRIES - 1);
+ }
+
/* If MWI was previously enabled, reenable it. */
if (hw->mac_type == e1000_82542_rev2_0) {
if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
@@ -5774,13 +5785,48 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
int32_t
e1000_read_mac_addr(struct e1000_hw * hw)
{
- uint16_t offset;
+ uint16_t offset, mac_addr_offset = 0;
uint16_t eeprom_data, i;
+ int32_t ret_val;
DEBUGFUNC("e1000_read_mac_addr");
+ if (hw->mac_type == e1000_82571) {
+ /* Check for an alternate MAC address. An alternate MAC
+ * address can be setup by pre-boot software and must be
+ * treated like a permanent address and must override the
+ * actual permanent MAC address.*/
+ ret_val = e1000_read_eeprom(hw, EEPROM_ALT_MAC_ADDR_PTR, 1,
+ &mac_addr_offset);
+ if (ret_val) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ if (mac_addr_offset == 0xFFFF)
+ mac_addr_offset = 0;
+
+ if (mac_addr_offset) {
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ mac_addr_offset += NODE_ADDRESS_SIZE/sizeof(u16);
+
+ /* make sure we have a valid mac address here
+ * before using it */
+ ret_val = e1000_read_eeprom(hw, mac_addr_offset, 1,
+ &eeprom_data);
+ if (ret_val) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ if (eeprom_data & 0x0001)
+ mac_addr_offset = 0;
+ }
+
+ if (mac_addr_offset)
+ hw->laa_is_present = TRUE;
+ }
+
for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
- offset = i >> 1;
+ offset = mac_addr_offset + (i >> 1);
if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
@@ -5797,7 +5843,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
case e1000_82571:
case e1000_82576:
case e1000_80003es2lan:
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (!mac_addr_offset &&
+ E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
hw->perm_mac_addr[5] ^= 0x01;
break;
}
diff --git a/src/drivers/net/e1000/e1000_hw.h b/src/drivers/net/e1000/e1000_hw.h
index 7ecac6cb..628b2e37 100644
--- a/src/drivers/net/e1000/e1000_hw.h
+++ b/src/drivers/net/e1000/e1000_hw.h
@@ -2299,6 +2299,7 @@ struct e1000_host_command_info {
#define EEPROM_INIT_CONTROL3_PORT_A 0x0024
#define EEPROM_CFG 0x0012
#define EEPROM_FLASH_VERSION 0x0032
+#define EEPROM_ALT_MAC_ADDR_PTR 0x0037
#define EEPROM_CHECKSUM_REG 0x003F
#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */