summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson2009-11-19 16:46:30 +0100
committerMarty Connor2009-11-22 13:51:23 +0100
commit470454a79121070fe26ccd55620cd9d434ad895c (patch)
tree0321de7a9787dfa4cead434647a47322bbd97e7d
parent[e1000] Implement zero-copy receive (diff)
downloadipxe-470454a79121070fe26ccd55620cd9d434ad895c.tar.gz
ipxe-470454a79121070fe26ccd55620cd9d434ad895c.tar.xz
ipxe-470454a79121070fe26ccd55620cd9d434ad895c.zip
[e1000] Use the alternate MAC in NVRAM when available
The 82571 supports an alternate MAC address location in NVRAM. When this is set, use this for the MAC rather than the default physical MAC address. Ported from linux-2.6.git 93ca161027eb6a1761fb674ad7b995aedccf5f6e Signed-off-by: Alex Williamson <alex.williamson@hp.com> Tested-by: Thomas Miletich <thomas.miletich@gmail.com> Signed-off-by: Marty Connor <mdc@etherboot.org>
-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 */