Subject: Re: Setting alternate MAC addresses on e1000

From: "Kok, Auke" <[email-masked]>
Date: Tue, 08 Apr 2008 10:26:07 -0700

Andy Gospodarek wrote:
> On Tue, Apr 01, 2008 at 03:15:54PM +0200, Carsten Aulbert wrote:
>> Hi,
>>
>> I know that quite a few e1000 experts are reading here, so I hope to 
>> have some luck here:
>>
>> I need to reprogram the MAC addresses of several 82573E/L NICs. I tried 
>> the obvious approach first using ethtool -E to write the numbers into 
>> the first six bytes and this works quite ok [1], except that I need to 
>> specifically change the second MAC not necessarily the first one. This 
>> approach only changed the first NIC and left the second unchanged.
>>
>> I've browsed http://download.intel.com/design/network/manuals/31608004.pdf
>> quite a bit, but except finding that I seem to need to set word 0x37 to 
>> point to 12 free bytes I have not come up with much. For example, I 
>> don't know where I would find those 12 free bytes.
>>
>> Anyone with a different approach or a hint how to succeed?
>>
>> TIA
>>
>> Carsten
>>
> 
> Bill posted a patch for this a while back (but it was not accepted since
> support for that hardware is offically moving to e1000e).  This may be
> what you want....

yeah I thought of that as well and after digging through the documentation I don't
think this will work for 82573's - it seems that only 82571 hardware supports this
feature, which is not what Carsten needs.

as stated above, the alternate eeprom layout of the 82573 seems to also indicate that.

Auke

> Port alternate MAC address support from the sourceforge 
> e1000 driver to the upstream e1000 driver.
> 
> Signed-off-by: Bill Hayes <[email-masked]>
> ---
> 
>  drivers/net/e1000/e1000_hw.c |   42 +++++++++++++++++++++++++++++++++++++++---
>  drivers/net/e1000/e1000_hw.h |    2 ++
>  2 files changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
> index 8fa0fe4..07e3178 100644
> --- a/drivers/net/e1000/e1000_hw.c
> +++ b/drivers/net/e1000/e1000_hw.c
> @@ -719,6 +719,11 @@ e1000_reset_hw(struct e1000_hw *hw)
>      DEBUGOUT("Masking off all interrupts\n");
>      E1000_WRITE_REG(hw, IMC, 0xffffffff);
>  
> +    if (hw->mac_type == e1000_82571 && hw->alt_mac_addr_is_present) {
> +    	hw->laa_is_present = 1;
> +    	e1000_rar_set(hw, hw->mac_addr, E1000_RAR_ENTRIES - 1);
> +    }
> +
>      /* Clear any pending interrupt events. */
>      icr = E1000_READ_REG(hw, ICR);
>  
> @@ -5693,11 +5698,41 @@ e1000_read_mac_addr(struct e1000_hw * hw)
>  {
>      uint16_t offset;
>      uint16_t eeprom_data, i;
> +    u16 mac_addr_offset = 0;
>  
>      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. */
> +        if (e1000_read_eeprom(hw, EEPROM_ALT_MAC_ADDR_PTR, 1,
> +                              &mac_addr_offset) < 0) {
> +            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 */
> +            if (e1000_read_eeprom(hw, mac_addr_offset, 1, &eeprom_data) < 0) {
> +                DEBUGOUT("EEPROM Read Error\n");
> +                return -E1000_ERR_EEPROM;
> +            }
> +            if (eeprom_data & 0x0001)
> +                mac_addr_offset = 0;
> +	}
> +
> +        if (mac_addr_offset) 
> +                hw->alt_mac_addr_is_present = 1;
> +    }
> +
>      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;
> @@ -5713,8 +5748,9 @@ e1000_read_mac_addr(struct e1000_hw * hw)
>      case e1000_82546_rev_3:
>      case e1000_82571:
>      case e1000_80003es2lan:
> -        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
> -            hw->perm_mac_addr[5] ^= 0x01;
> +        if (!mac_addr_offset &&
> +            (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
> +                hw->perm_mac_addr[5] ^= 0x01;
>          break;
>      }
>  
> diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
> index a2a86c5..e18760d 100644
> --- a/drivers/net/e1000/e1000_hw.h
> +++ b/drivers/net/e1000/e1000_hw.h
> @@ -1456,6 +1456,7 @@ struct e1000_hw {
>  	boolean_t		tbi_compatibility_en;
>  	boolean_t		tbi_compatibility_on;
>  	boolean_t		laa_is_present;
> +	boolean_t		alt_mac_addr_is_present;
>  	boolean_t		phy_reset_disable;
>  	boolean_t		initialize_hw_bits_disable;
>  	boolean_t		fc_send_xon;
> @@ -2286,6 +2287,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 */
> 
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [email-masked]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [email-masked]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html