summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/realtek.c
diff options
context:
space:
mode:
authorMichael Brown2012-08-23 14:35:19 +0200
committerMichael Brown2012-08-23 16:15:43 +0200
commit0dacd54174a78d32f7bfff958dd120f04f130f4b (patch)
treea1e9e608d209b6957a4bfe9bf0a2efccbb8cd70d /src/drivers/net/realtek.c
parent[realtek] Use read-modify-write to check for C+ Command register (diff)
downloadipxe-0dacd54174a78d32f7bfff958dd120f04f130f4b.tar.gz
ipxe-0dacd54174a78d32f7bfff958dd120f04f130f4b.tar.xz
ipxe-0dacd54174a78d32f7bfff958dd120f04f130f4b.zip
[realtek] Enable DAC only when built as a 64-bit binary
Some RTL8169 cards (observed with an RTL8169SC) crash and burn if DAC is enabled, even if only 32-bit addresses are used. Observed behaviour includes system lockups and repeated transmission of garbage data onto the wire. This seems to be a known problem. The Linux r8169 driver disables DAC by default and provides a "use_dac" module parameter. There appears to be no known test for determining whether or not DAC will work. As a workaround, enable DAC only if we are built as as 64-bit binary. This at least eliminates the problem in the common case of a 32-bit build, which will never use 64-bit addresses anyway. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/realtek.c')
-rw-r--r--src/drivers/net/realtek.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c
index f63f25f2..98fc02f4 100644
--- a/src/drivers/net/realtek.c
+++ b/src/drivers/net/realtek.c
@@ -878,10 +878,15 @@ static void realtek_detect ( struct realtek_nic *rtl ) {
/* The C+ Command register is present only on 8169 and 8139C+.
* Try to enable C+ mode and PCI Dual Address Cycle (for
* 64-bit systems), if supported.
+ *
+ * Note that enabling DAC seems to cause bizarre behaviour
+ * (lockups, garbage data on the wire) on some systems, even
+ * if only 32-bit addresses are used.
*/
cpcr = readw ( rtl->regs + RTL_CPCR );
- cpcr |= ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX |
- RTL_CPCR_CPTX );
+ cpcr |= ( RTL_CPCR_MULRW | RTL_CPCR_CPRX | RTL_CPCR_CPTX );
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
+ cpcr |= RTL_CPCR_DAC;
writew ( cpcr, rtl->regs + RTL_CPCR );
check_cpcr = readw ( rtl->regs + RTL_CPCR );