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;