em(4) patch for qemu/kvm/vbox guests (was: Re: flash10 vs f10; em(4) now broken in -current in qemu/vbox)

Juergen Lock nox at jelal.kn-bremen.de
Sun Jun 7 17:30:46 UTC 2009


In article <4A2BC96B.9010209 at 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;
 }
 
 /**


More information about the freebsd-emulation mailing list