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;