-/* $OpenBSD: if_es.c,v 1.4 1996/05/02 06:44:05 niklas Exp $ */
-/* $NetBSD: if_es.c,v 1.11 1996/04/21 21:11:46 veego Exp $ */
+/* $OpenBSD: if_es.c,v 1.5 1996/05/04 14:04:04 niklas Exp $ */
+/* $NetBSD: if_es.c,v 1.12 1996/05/01 15:55:28 mhitch Exp $ */
/*
* Copyright (c) 1995 Michael L. Hitch
#define SWAP(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff))
-#define ESDEBUG
#define USEPKTBUF
/*
struct device sc_dev;
struct isr sc_isr;
struct arpcom sc_arpcom; /* common Ethernet structures */
- void *sc_base; /* base address of board */
+ void *sc_base; /* base address of board */
short sc_iflags;
unsigned short sc_intctl;
#ifdef ESDEBUG
int sc_debug;
- short sc_intbusy;
- short sc_smcbusy;
+ short sc_intbusy; /* counter for interrupt rentered */
+ short sc_smcbusy; /* counter for other rentry checks */
#endif
};
unsigned long ser;
sc->sc_base = zap->va;
-#ifdef ESDEBUG
- /* MLHDEBUG
- * MLHDEBUG remove first 4 and last 3 pages of the A4066 memory
- * MLHDEBUG and use the 5th page to access the SMC
- */
- sc->sc_base = zap->va + 0x8000; /* MLHDEBUG */
- physunaccess(zap->va, 0x8000); /* MLHDEBUG */
- physunaccess(zap->va + 0xa000, 0x6000); /* MLHDEBUG */
-#endif
/*
* Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID.
char *where;
union smcregs *smc;
{
- u_short cur_bank = smc->b0.bsr & 0x0300;
+ u_short cur_bank = smc->b0.bsr & BSR_MASK;
printf("SMC registers %p from %s bank %04x\n", smc, where,
smc->b0.bsr);
smc = sc->sc_base;
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2 &&
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2 &&
sc->sc_arpcom.ac_if.if_flags & IFF_RUNNING) {
printf("%s: intr BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
printf("%s: esintr re-entered\n", sc->sc_dev.dv_xname);
panic("esintr re-entered");
}
+ if (sc->sc_smcbusy)
+ printf("%s: esintr interrupted busy %d\n", sc->sc_dev.dv_xname,
+ sc->sc_smcbusy);
#endif
smc->b2.msk = 0;
#ifdef ESDEBUG
#endif
}
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: intr+ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
esrint(sc);
}
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: intr++ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
++estxint3; /* count # IST_TX */
#endif
zzzz:
+#ifdef ESDEBUG
++estxint4; /* count # ~TEMPTY */
+#endif
smc->b0.bsr = BSR_BANK0;
ephsr = smc->b0.ephsr; /* get EPHSR */
tcr = smc->b0.tcr; /* and TCR */
/* output packets */
estint(sc);
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: intr+++ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
struct es_softc *sc;
{
union smcregs *smc = sc->sc_base;
- int i;
u_short len;
short cnt;
u_short pktctlw, pktlen, *buf;
#ifdef USEPKTBUF
u_char *b, pktbuf[1530];
#endif
+#ifdef ESDEBUG
+ int i;
+#endif
#ifdef ESDEBUG
if (esdebug)
printf("%s: esrint re-entered\n", sc->sc_dev.dv_xname);
panic("esrint re-entered");
}
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: rint BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
sc->sc_dev.dv_xname, pktctlw, pktlen, len, smc->b2.bsr);
/* XXX ignore packet, or just truncate? */
#if defined(ESDEBUG) && defined(DDB)
- if ((smc->b2.bsr & 0x0300) != BSR_BANK2)
+ if ((smc->b2.bsr & BSR_MASK) != BSR_BANK2)
Debugger();
#endif
smc->b2.bsr = BSR_BANK2;
printf("%s: esstart re-entered\n", sc->sc_dev.dv_xname);
panic("esstart re-entred");
}
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: esstart BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
}
#endif
for (;;) {
-int xxx;
+#ifdef ESDEBUG
+ u_short start_ptr, end_ptr;
+#endif
/*
* Sneak a peek at the next packet to get the length
* and see if the SMC 91C90 can accept it.
if (!m)
break;
#ifdef ESDEBUG
-if (esdebug && (m->m_next || m->m_len & 1))
- printf("%s: esstart m_next %p m_len %d\n", sc->sc_dev.dv_xname,
- m->m_next, m->m_len);
+ if (esdebug && (m->m_next || m->m_len & 1))
+ printf("%s: esstart m_next %p m_len %d\n",
+ sc->sc_dev.dv_xname, m->m_next, m->m_len);
#endif
for (m0 = m, pktlen = 0; m0; m0 = m0->m_next)
pktlen += m0->m_len;
active_pnr = smc->b2.pnr = smc->b2.arr;
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: esstart+ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
}
#endif
IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
-xxx = splhigh();
smc->b2.ptr = PTR_AUTOINCR;
(void) smc->b2.mmucr;
data = (u_short *)&smc->b2.data;
*data = SWAP(pktctlw);
*data = SWAP(pktlen);
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: esstart++ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;
pktbuf[i/2] = 0;
pktlen -= 4;
#ifdef ESDEBUG
- if (pktlen > sizeof(pktbuf))
+ if (pktlen > sizeof(pktbuf) && i > (sizeof(pktbuf) * 2))
printf("%s: esstart packet longer than pktbuf\n",
sc->sc_dev.dv_xname);
#endif
*data = *buf;
}
#else
+#ifdef ESDEBUG
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
+ printf("%s: esstart++2 BSR not 2: %04x\n", sc->sc_dev.dv_xname,
+ smc->b2.bsr);
+ smc->b2.bsr = BSR_BANK2;
+ }
+ start_ptr = SWAP(smc->b2.ptr); /* save PTR before copy */
+#endif
buf = pktbuf;
cnt = pktlen / 2;
while (cnt--)
*data = *buf++;
+#ifdef ESDEBUG
+ end_ptr = SWAP(smc->b2.ptr); /* save PTR after copy */
+#endif
#endif
#else /* USEPKTBUF */
pktctlw = 0;
}
*data = pktctlw;
#endif /* USEPKTBUF */
-splx(xxx);
-#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
- printf("%s: esstart+++ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
- smc->b2.bsr);
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
+ /*
+ * The bank select register has changed. This seems
+ * to happen with my A2000/Zeus once in a while. It
+ * appears that the Ethernet chip resets while
+ * copying the transmit buffer. Requeue the current
+ * transmit buffer and reinitialize the interface.
+ * The initialize routine will take care of
+ * retransmitting the buffer. mhitch
+ */
+#ifdef DIAGNOSTIC
+ printf("%s: esstart+++ BSR not 2: %04x\n",
+ sc->sc_dev.dv_xname, smc->b2.bsr);
+#endif
smc->b2.bsr = BSR_BANK2;
- }
+#ifdef ESDEBUG
+ printf("start_ptr %04x end_ptr %04x cur ptr %04x\n",
+ start_ptr, end_ptr, SWAP(smc->b2.ptr));
+ --sc->sc_smcbusy;
#endif
+ IF_PREPEND(&sc->sc_arpcom.ac_if.if_snd, m0);
+ esinit(sc); /* It's really hosed - reset */
+ return;
+ }
smc->b2.mmucr = MMUCR_ENQ_TX;
if (smc->b2.pnr != active_pnr)
printf("%s: esstart - PNR changed %x->%x\n",
}
smc->b2.msk = sc->sc_intctl;
#ifdef ESDEBUG
- while ((smc->b2.bsr & 0x0300) != BSR_BANK2) {
+ while ((smc->b2.bsr & BSR_MASK) != BSR_BANK2) {
printf("%s: esstart++++ BSR not 2: %04x\n", sc->sc_dev.dv_xname,
smc->b2.bsr);
smc->b2.bsr = BSR_BANK2;