git: 9front

Download patch

ref: 1f15f469f9a659fe26f2ad3f8c1f9db3d49d79c5
parent: 8137259a19ab016b533db9b924c3df0219d5d9cb
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Feb 23 12:19:38 EST 2025

ether8169: initialize stats counter to prevent scribbling over memory

on the RTL8168EP. when PXE booting, we would get memory corruption
from, apparently, the counters that the PXE rom had set up getting
scribbled over our kernel memory. This resets the counters early,
setting them to the expected DTCC address.

--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -61,7 +61,8 @@
 };
 
 enum {					/* Dtccr */
-	Cmd		= 0x00000008,	/* Command */
+	Reset		= 0x00000001,	/* Reset */
+	Dump		= 0x00000008,	/* Dump */
 };
 
 enum {					/* Cr */
@@ -425,7 +426,7 @@
 		csr8w(ctlr, Ldps, 1);				/* magic */
 		rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
 	}
-	
+
 	if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
 		error("no phy");
 	}
@@ -524,6 +525,7 @@
 rtl8169ifstat(void *arg, char *p, char *e)
 {
 	Ether *edev = arg;
+	u64int pa;
 	Ctlr *ctlr;
 	Dtcc *dtcc;
 	int i, r, timeo;
@@ -535,14 +537,15 @@
 		nexterror();
 	}
 
-	csr32w(ctlr, Dtccr+4, 0);
-	csr32w(ctlr, Dtccr, PCIWADDR(ctlr->dtcc)|Cmd);
+	pa = PCIWADDR(ctlr->dtcc)|Dump;
+	csr32w(ctlr, Dtccr+4, pa >> 32);
+	csr32w(ctlr, Dtccr, pa);
 	for(timeo = 0; timeo < 1000; timeo++){
-		if(!(csr32r(ctlr, Dtccr) & Cmd))
+		if(!(csr32r(ctlr, Dtccr) & (Reset|Dump)))
 			break;
 		delay(1);
 	}
-	if(csr32r(ctlr, Dtccr) & Cmd)
+	if(csr32r(ctlr, Dtccr) & (Reset|Dump))
 		error(Eio);
 	dtcc = ctlr->dtcc;
 
@@ -667,7 +670,7 @@
 static void
 rtl8169init(Ether* edev)
 {
-	int i;
+	int i, timeo;
 	u32int r;
 	Block *bp;
 	Ctlr *ctlr;
@@ -728,6 +731,19 @@
 	pa = PCIWADDR(ctlr->rd);
 	csr32w(ctlr, Rdsar+4, pa>>32);
 	csr32w(ctlr, Rdsar, pa);
+
+	pa = PCIWADDR(ctlr->dtcc)|Reset;
+	csr32w(ctlr, Dtccr+4, pa >> 32);
+	csr32w(ctlr, Dtccr, pa);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Dtccr) & (Reset|Dump)))
+			break;
+		delay(1);
+	}
+	if(csr32r(ctlr, Dtccr) & (Reset|Dump)){
+		iunlock(ctlr);
+		error("reset failed");
+	}
 
 	/* pre-RTL8168G controllers need TX/RX before configuration */
 	switch(ctlr->macv){
--