*BSD News Article 19081


Return to BSD News archive

Xref: sserve comp.os.386bsd.development:976 comp.os.386bsd.misc:650
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!agate!spool.mu.edu!uwm.edu!ogicse!psgrain!agora!implode!davidg
From: davidg@implode.rain.com (David Greenman)
Newsgroups: comp.os.386bsd.development,comp.os.386bsd.misc
Subject: Bug fix for if_ed.c ethernet driver
Message-ID: <CB143v.2tL@implode.rain.com>
Date: 31 Jul 93 12:31:07 GMT
Article-I.D.: implode.CB143v.2tL
Organization: Delta Systems, Portland, OR.
Lines: 181


  What follows is a diff to fix two bugs which caused old WD8003E boards
not to function with the 'ed' device driver that I recently posted. One
of the bugs was exposed because old 8003E boards ignore the IO address
lines >10bits. With that coupled with some incorrect logic in the code
related to enabling/disabling the transceiver for 3c503's, the WD8003E's
would get garbage written to one of the NIC registers. The other bug fix
is really a work-around for a hardware bug in the board related to talley
counter overflow.

-DG

-------------------------------------------------------------------------

*** /tmp/,RCSt1003604	Sat Jul 31 05:16:46 1993
--- /tmp/,RCSt2003604	Sat Jul 31 05:16:46 1993
***************
*** 17,22 ****
--- 17,40 ----
   * Modification history
   *
   * $Log:	if_ed.c,v $
+  * Revision 1.18  93/07/27  03:41:36  davidg
+  * removed unnecessary variable assignment in ed_reset()
+  * 
+  * Revision 1.17  93/07/26  18:40:57  davidg
+  * Added include of systm.h to pick up inlined min/max/bcmp if you have
+  * them in cpufunc.h. Modified wait loop in reset to look a little better.
+  * Added read for talley counters to prevent an infinite loop on old
+  * 8003E's if they (the counters) overflow.
+  * 
+  * Revision 1.16  93/07/25  14:27:12  davidg
+  * added parans to the previous fix so that it can cope with outb
+  * being a macro.
+  * 
+  * Revision 1.15  93/07/25  14:07:56  davidg
+  * fixed logic problem where a 3c503 register was being written
+  * even if the board wasn't a 3Com. Wolfgang Solfrank pointed this
+  * out.
+  * 
   * Revision 1.14  93/07/20  15:24:25  davidg
   * ommision for force 16bit case fixed from last patch
   * 
***************
*** 77,82 ****
--- 95,101 ----
  #include "bpfilter.h"
  
  #include "param.h"
+ #include "systm.h"
  #include "errno.h"
  #include "ioctl.h"
  #include "mbuf.h"
***************
*** 782,788 ****
  	ed_stop(unit);
  	ed_init(unit);
  
! 	s = splx(s);
  }
   
  /*
--- 801,807 ----
  	ed_stop(unit);
  	ed_init(unit);
  
! 	(void) splx(s);
  }
   
  /*
***************
*** 805,814 ****
  	 *	to 'n' (about 5ms). It shouldn't even take 5us on modern
  	 *	DS8390's, but just in case it's an old one.
  	 */
! 	while ((inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RST) == 0) {
! 		if (--n == 0)
! 			break;
! 	}
  }
  
  /*
--- 824,831 ----
  	 *	to 'n' (about 5ms). It shouldn't even take 5us on modern
  	 *	DS8390's, but just in case it's an old one.
  	 */
! 	while (((inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
! 
  }
  
  /*
***************
*** 957,966 ****
  	 * If this is a 3Com board, the tranceiver must be software enabled
  	 *	(there is no settable hardware default).
  	 */
! 	if ((sc->vendor == ED_VENDOR_3COM) && (ifp->if_flags & IFF_LLC0)) {
! 		outb(sc->asic_addr + ED_3COM_CR, 0);
! 	} else {
! 		outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
  	}
  
  	/*
--- 974,985 ----
  	 * If this is a 3Com board, the tranceiver must be software enabled
  	 *	(there is no settable hardware default).
  	 */
! 	if (sc->vendor == ED_VENDOR_3COM) {
! 		if (ifp->if_flags & IFF_LLC0) {
! 			outb(sc->asic_addr + ED_3COM_CR, 0);
! 		} else {
! 			outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
! 		}
  	}
  
  	/*
***************
*** 1463,1475 ****
  		}
  
  		/*
! 		 * return NIC CR to standard state before looping back
! 		 *	to top: page 0, remote DMA complete, start
! 		 * (toggling the TXP bit off, even if was just set in the
! 		 *	transmit routine, is *okay* - it is 'edge' triggered
! 		 *	from low to high)
  		 */
  		outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
  	}
  }
   
--- 1482,1505 ----
  		}
  
  		/*
! 		 * return NIC CR to standard state: page 0, remote DMA complete,
! 		 * 	start (toggling the TXP bit off, even if was just set
! 		 *	in the transmit routine, is *okay* - it is 'edge'
! 		 *	triggered from low to high)
  		 */
  		outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
+ 
+ 		/*
+ 		 * If the Network Talley Counters overflow, read them to
+ 		 *	reset them. It appears that old 8390's won't
+ 		 *	clear the ISR flag otherwise - resulting in an
+ 		 *	infinite loop.
+ 		 */
+ 		if (isr & ED_ISR_CNT) {
+ 			(void) inb(sc->nic_addr + ED_P0_CNTR0);
+ 			(void) inb(sc->nic_addr + ED_P0_CNTR1);
+ 			(void) inb(sc->nic_addr + ED_P0_CNTR2);
+ 		}
  	}
  }
   
***************
*** 1583,1592 ****
  		 *	of the tranceiver for 3Com boards. The LLC0 flag disables
  		 *	the tranceiver if set.
  		 */
! 		if ((sc->vendor == ED_VENDOR_3COM) && (ifp->if_flags & IFF_LLC0)) {
! 			outb(sc->asic_addr + ED_3COM_CR, 0);
! 		} else {
! 			outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
  		}
  
  		break;
--- 1613,1624 ----
  		 *	of the tranceiver for 3Com boards. The LLC0 flag disables
  		 *	the tranceiver if set.
  		 */
! 		if (sc->vendor == ED_VENDOR_3COM) {
! 			if (ifp->if_flags & IFF_LLC0) {
! 				outb(sc->asic_addr + ED_3COM_CR, 0);
! 			} else {
! 				outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
! 			}
  		}
  
  		break;