Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Jun 2009 19:27:12 +0200 (CEST)
From:      Juergen Lock <nox@jelal.kn-bremen.de>
To:        sebosik@demax.sk
Cc:        freebsd-emulation@freebsd.org
Subject:   em(4) patch for qemu/kvm/vbox guests (was: Re: flash10 vs f10; em(4) now broken in -current in qemu/vbox)
Message-ID:  <200906071727.n57HRCZK012510@triton.kn-bremen.de>
In-Reply-To: <4A2BC96B.9010209@demax.sk>

next in thread | previous in thread | raw e-mail | index | archive | help
In article <4A2BC96B.9010209@demax.sk> you write:
>Hi
>
>I think its caused by internal control of MAC address validity in 
>freebsd-sources ( sys/dev/e1000/if_em.c ) on line 4950.
>You can safely remove references to that function + function itself and than 
>happily use if_em undex VBox as before.

Actually that wasn't it, in fact commit 190872 changed the way mac addresses
are read (e1000_read_mac_addr_generic() in sys/dev/e1000/e1000_nvm.c) - if I
add the old way back for the case that the new code gets all zeros em(4)
works again:

Index: sys/dev/e1000/e1000_nvm.c
@@ -820,20 +820,45 @@
 	u32 rar_high;
 	u32 rar_low;
 	u16 i;
+	s32 ret_val = E1000_SUCCESS;
+
+	DEBUGFUNC("e1000_read_mac_addr");
 
 	rar_high = E1000_READ_REG(hw, E1000_RAH(0));
 	rar_low = E1000_READ_REG(hw, E1000_RAL(0));
 
-	for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
-		hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
+	/* Fall back to reading from actual EEPROM like this code used to do
+	 * in case we got all zeroes.  (This fixes qemu/kvm/vbox guests.)
+	 */
+	if (!rar_low && !rar_high) {
+		u16 offset, nvm_data;
+
+		for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+			offset = i >> 1;
+			ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+			if (ret_val) {
+				DEBUGOUT("NVM Read Error\n");
+				goto out;
+			}
+			hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
+			hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
+		}
 
-	for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
-		hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
+		/* Flip last bit of mac address if we're on second port */
+		if (hw->bus.func == E1000_FUNC_1)
+			hw->mac.perm_addr[5] ^= 1;
+	} else {
+		for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
+			hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
 
+		for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
+			hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
+	}
 	for (i = 0; i < ETH_ADDR_LEN; i++)
 		hw->mac.addr[i] = hw->mac.perm_addr[i];
 
-	return E1000_SUCCESS;
+out:
+	return ret_val;
 }
 
 /**



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906071727.n57HRCZK012510>