Etherboot 5.0.10 problems + patchfile

Dave Ashley linuxbios at xdr.com
Fri Feb 13 13:24:01 CET 2004


I'm going to post this patch to the etherboot mailing list but it is
relevant here as well. This is our current patch against etherboot 5.0.10
to fix various problems:
1) RTL8139 interrupt handling was wrong
2) VIA-RHINE support needs workaround for the 3065 chip version. When
resetting the chip, the act of shutting down the receive machinery can
cause a problem, and when the chip is reset it never gets out of reset. So
etherboot would hang when trying to send out a packet, such as a bootp
request. This fix is from via's linuxfet driver. Google searches tracked
down other people with the same problem and the eventual solution.
3) Some issue with initializing the timer, which without it was causing a
divide by zero at some point.

The #2 was an especially bad problem and affected our epia-m solution.
The boxes would stop sending out BOOTP requests after a while.

-Dave

diff -Nur etherboot-5.0.10/src/misc.c etherboot-5.0.10-new/src/misc.c
--- etherboot-5.0.10/src/misc.c	Sun Mar  9 03:17:15 2003
+++ etherboot-5.0.10-new/src/misc.c	Wed Jul 16 09:45:26 2003
@@ -282,7 +282,7 @@
 enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
 	Query_A20_Support = 0x2403 } Int0x15Arg;
 
-#if defined(PCBIOS) && !defined(IBM_L40)
+#if defined(TAGGED_IMAGE) || (defined(PCBIOS) && !defined(IBM_L40))
 static void empty_8042(void)
 {
 	unsigned long time;
diff -Nur etherboot-5.0.10/src/rtl8139.c etherboot-5.0.10-new/src/rtl8139.c
--- etherboot-5.0.10/src/rtl8139.c	Tue Jul 23 17:50:53 2002
+++ etherboot-5.0.10-new/src/rtl8139.c	Wed Jul 16 09:45:42 2003
@@ -183,7 +183,6 @@
 static int rtl_poll(struct nic *nic);
 static void rtl_disable(struct nic*);
 
-
 struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
 	struct pci_device *pci)
 {
@@ -252,6 +251,16 @@
 #define EE_READ_CMD     (6)
 #define EE_ERASE_CMD    (7)
 
+static unsigned short cintr=0;
+static unsigned short getstatus(void)
+{
+	return cintr|=inw(ioaddr + IntrStatus);
+}
+static void setstatus(unsigned short val)
+{
+	cintr&=~val;
+}
+
 static int read_eeprom(int location, int addr_len)
 {
 	int i;
@@ -340,7 +349,7 @@
 static void rtl_transmit(struct nic *nic, const char *destaddr,
 	unsigned int type, unsigned int len, const char *data)
 {
-	unsigned int status, to, nstype;
+	unsigned int status, to, nstype, st;
 	unsigned long txstatus;
 
 	/* nstype assignment moved up here to avoid gcc 3.0.3 compiler bug */
@@ -365,14 +374,15 @@
 	outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len,
 		ioaddr + TxStatus0 + cur_tx*4);
 
+	st= currticks();
 	to = currticks() + RTL_TIMEOUT;
 
 	do {
-		status = inw(ioaddr + IntrStatus);
+		status = getstatus();
 		/* Only acknlowledge interrupt sources we can properly handle
 		 * here - the RxOverflow/RxFIFOOver MUST be handled in the
 		 * rtl_poll() function.  */
-		outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus);
+		setstatus(status & (TxOK | TxErr | PCIErr));
 		if ((status & (TxOK | TxErr | PCIErr)) != 0) break;
 	} while (currticks() < to);
 
@@ -382,12 +392,12 @@
 		cur_tx = (cur_tx + 1) % NUM_TX_DESC;
 #ifdef	DEBUG_TX
 		printf("tx done (%d ticks), status %hX txstatus %X\n",
-			to-currticks(), status, txstatus);
+			currticks()-st, status, txstatus);
 #endif
 	} else {
 #ifdef	DEBUG_TX
 		printf("tx timeout/error (%d ticks), status %hX txstatus %X\n",
-			currticks()-to, status, txstatus);
+			currticks()-st, status, txstatus);
 #endif
 		rtl_reset(nic);
 	}
@@ -403,9 +413,9 @@
 		return 0;
 	}
 
-	status = inw(ioaddr + IntrStatus);
+	status = getstatus();
 	/* See below for the rest of the interrupt acknowledges.  */
-	outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);
+	setstatus(status & ~(RxFIFOOver | RxOverflow | RxOK));
 
 #ifdef	DEBUG_RX
 	printf("rtl_poll: int %hX ", status);
@@ -449,7 +459,7 @@
 	/* See RTL8139 Programming Guide V0.1 for the official handling of
 	 * Rx overflow situations.  The document itself contains basically no
 	 * usable information, except for a few exception handling rules.  */
-	outw(status & (RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);
+	setstatus(status & (RxFIFOOver | RxOverflow | RxOK));
 	return 1;
 }
 
diff -Nur etherboot-5.0.10/src/timer.c etherboot-5.0.10-new/src/timer.c
--- etherboot-5.0.10/src/timer.c	Sat Mar 22 11:52:25 2003
+++ etherboot-5.0.10-new/src/timer.c	Wed Jul 16 09:45:46 2003
@@ -138,6 +138,8 @@
 {
 	unsigned long clocks_high, clocks_low;
 	unsigned long currticks;
+
+setup_timers();
 	/* Read the Time Stamp Counter */
 	rdtsc(clocks_low, clocks_high);


--- etherboot-5.0.10/src/Makefile	2003-03-09 17:39:21.000000000 -0800
+++ etherboot-5.0.10/src/Makefile.new	2003-11-06 06:22:26.000000000 -0800
@@ -98,8 +98,8 @@
 
 include Config
 
-GCC=		gcc
-CPP=		gcc -E -Wp,-Wall
+GCC=		$(CC)
+CPP=		$(CC) -E -Wp,-Wall
 STRIP=		strip
 OBJCOPY=	objcopy
 # MAKEROM=	bin/makerom
diff -Nur etherboot-5.0.10/src/via-rhine.c etherboot-5.0.10-new/src/via-rhine.c
--- etherboot-5.0.10/src/via-rhine.c	2003-02-07 15:07:56.000000000 -0800
+++ etherboot-5.0.10-new/src/via-rhine.c	2004-02-06 07:24:50.000000000 -0800
@@ -106,6 +106,10 @@
 #define byCFGD				ioaddr + 0x7b
 #define wTallyCntMPA			ioaddr + 0x7c
 #define wTallyCntCRC			ioaddr + 0x7d
+#define bySTICKHW			ioaddr + 0x83
+#define byWOLcrClr			ioaddr + 0xA4
+#define byWOLcgClr			ioaddr + 0xA7
+#define byPwrcsrClr			ioaddr + 0xAC
 /*---------------------  Exioaddr Definitions -------------------------*/
 
 /*
@@ -873,6 +877,19 @@
     return nic;
 }
 
+static void set_rx_mode(struct nic *nic) {
+    	struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
+	unsigned char rx_mode;
+    	int ioaddr = tp->ioaddr;
+
+	/* ! IFF_PROMISC */
+	outl(0xffffffff, byMAR0);
+	outl(0xffffffff, byMAR4);
+	rx_mode = 0x0C;
+
+	outb(0x60 /* thresh */ | rx_mode, byRCR );
+}
+
 static struct nic *
 rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
 {
@@ -885,6 +902,29 @@
 
     if (rhine_debug > 0 && did_version++ == 0)
 	printf (version);
+
+    /* D-Link provided reset code (with comment additions) */
+    if((chip_id != 0x3043) && (chip_id != 0x6100)) {
+	unsigned char byOrgValue;
+	
+	if(rhine_debug > 0)
+		printf("Enabling Sticky Bit Workaround for Chip_id: 0x%hX\n"
+				, chip_id);
+	/* clear sticky bit before reset & read ethernet address */
+	byOrgValue = inb(bySTICKHW);
+	byOrgValue = byOrgValue & 0xFC;
+	outb(byOrgValue, bySTICKHW);
+
+	/* (bits written are cleared?) */
+	/* disable force PME-enable */
+	outb(0x80, byWOLcgClr);
+	/* disable power-event config bit */
+	outb(0xFF, byWOLcrClr);
+	/* clear power status (undocumented in vt6102 docs?) */
+	outb(0xFF, byPwrcsrClr);
+	
+    }
+
     /* Perhaps this should be read from the EEPROM? */
     for (i = 0; i < ETH_ALEN; i++)
 	nic->node_addr[i] = inb (byPAR0 + i);
@@ -980,6 +1020,9 @@
     struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
     int ioaddr = tp->ioaddr;
 
+    /* merge reset and disable */
+    rhine_reset(nic);
+
     printf ("rhine disable\n");
     /* Switch to loopback mode to avoid hardware races. */
     writeb(0x60 | 0x01, byTCR);
@@ -1018,6 +1061,45 @@
     /* Soft reset the chip. */
     /*outb(CmdReset, ioaddr + ChipCmd); */
 
+    /* if the chip is 3065, we must patch shutdown bug*/
+//	if ((np->revision >= 0x40) && (np->revision <= 0x80))
+	{ 
+		int ww;
+        //Nic Loop Back On
+
+        outb(inb(byTCR) | 0x01, byTCR);
+        
+       //Tx Off
+        outb(inb(byCR0) & 0xEF, byCR0);
+
+#define W_MAX_TIMEOUT	0x0FFF
+        // W_MAX_TIMEOUT is the timeout period
+		for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+			if((inb(byCR0) & 0x10) == 0)
+			break; 
+		}
+
+        //Rx Off
+        outb(inb(byCR0) & 0xF7, byCR0);
+        
+        // W_MAX_TIMEOUT is the timeout period
+        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
+            if((inb(byCR0) & 0x08) == 0)
+                break; 
+        }
+
+        if (ww == W_MAX_TIMEOUT) {
+    
+            // Turn on fifo test
+            outw(inw(dwNextTDSE1) | 0x0001, dwNextTDSE1);
+            // Turn on fifo reject
+            outw(inw(dwNextTDSE1) | 0x0800, dwNextTDSE1);
+            // Turn off fifo test
+            outw(inw(dwNextTDSE1) & 0xFFFE, dwNextTDSE1);
+        }
+	}
+
+
     tx_bufs_tmp = (int) buf1;
     tx_ring_tmp = (int) desc1;
     rx_bufs_tmp = (int) buf2;
@@ -1069,6 +1151,9 @@
     outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr);
     outl (virt_to_bus (tp->tx_ring), dwCurrentTxDescAddr);
 
+    /* Setup Multicast */	
+    set_rx_mode(nic);
+
     /* close IMR */
     outw (0x0000, byIMR0);
 



More information about the coreboot mailing list