Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/qbus Fix a transmit bug and get a little more out fr...
details: https://anonhg.NetBSD.org/src/rev/7e6c218f1abc
branches: trunk
changeset: 487501:7e6c218f1abc
user: ragge <ragge%NetBSD.org@localhost>
date: Thu Jun 08 19:58:49 2000 +0000
description:
Fix a transmit bug and get a little more out from the receive logic.
diffstat:
sys/dev/qbus/if_de.c | 289 ++++++++++++++++++--------------------------------
1 files changed, 105 insertions(+), 184 deletions(-)
diffs (truncated from 508 to 300 lines):
diff -r 38da123dc256 -r 7e6c218f1abc sys/dev/qbus/if_de.c
--- a/sys/dev/qbus/if_de.c Thu Jun 08 19:01:44 2000 +0000
+++ b/sys/dev/qbus/if_de.c Thu Jun 08 19:58:49 2000 +0000
@@ -1,4 +1,5 @@
-/* $NetBSD: if_de.c,v 1.4 2000/06/05 00:09:18 matt Exp $ */
+/* $NetBSD: if_de.c,v 1.5 2000/06/08 19:58:49 ragge Exp $ */
+
/*
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Copyright (c) 2000 Ludd, University of Lule}, Sweden.
@@ -49,7 +50,6 @@
*/
#include "opt_inet.h"
-#include "opt_iso.h"
#include "bpfilter.h"
#include <sys/param.h>
@@ -127,16 +127,12 @@
bus_dmamap_t sc_cmap;
struct de_cdata *sc_dedata; /* Control structure */
struct de_cdata *sc_pdedata; /* Bus-mapped control structure */
-#ifdef notdef
- bus_dmamap_t sc_xmtmap[NXMT]; /* unibus xmit maps */
- struct mbuf *sc_txmbuf[NXMT];
-#endif
bus_dmamap_t sc_rcvmap[NRCV]; /* unibus receive maps */
struct mbuf *sc_rxmbuf[NRCV];
- int sc_nexttx; /* next tx descriptor to put data on */
- int sc_nextrx; /* next rx descriptor for recv */
- int sc_inq; /* # if xmit packets in queue */
- int sc_lastack; /* Last handled rx descriptor */
+ int sc_xindex; /* UNA index into transmit chain */
+ int sc_rindex; /* UNA index into receive chain */
+ int sc_xfree; /* index for next transmit buffer */
+ int sc_nxmit; /* # of transmits in progress */
void *sc_sh; /* shutdownhook cookie */
};
@@ -148,10 +144,8 @@
static void dereset(struct device *);
static void destart(struct ifnet *);
static void derecv(struct de_softc *);
-static void dexmit(struct de_softc *);
static void deintr(void *);
static int de_add_rxbuf(struct de_softc *, int);
-static void desetup(struct de_softc *sc);
static void deshutdown(void *);
struct cfattach de_ca = {
@@ -244,23 +238,6 @@
bzero(sc->sc_dedata, sizeof(struct de_cdata));
sc->sc_pdedata = (struct de_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
-#ifdef notdef
- /*
- * Create the transmit descriptor DMA maps.
- *
- * XXX - should allocate transmit map pages when needed, not here.
- */
- for (i = 0; i < NXMT; i++) {
- if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
- MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
- &sc->sc_xmtmap[i]))) {
- printf(": unable to create tx DMA map %d, error = %d\n",
- i, error);
- goto fail_4;
- }
- }
-#endif
-
/*
* Create receive buffer DMA maps.
*/
@@ -301,15 +278,15 @@
printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname, c,
ether_sprintf(myaddr));
- uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr,
- sc, &sc->sc_intrcnt);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc,
+ &sc->sc_intrcnt);
uba_reset_establish(dereset, &sc->sc_dev);
evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
- sc->sc_dev.dv_xname, "intr");
+ sc->sc_dev.dv_xname, "intr");
strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
+ ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI;
ifp->if_ioctl = deioctl;
ifp->if_start = destart;
if_attach(ifp);
@@ -336,14 +313,7 @@
if (sc->sc_rcvmap[i] != NULL)
bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
}
-#ifdef notdef
-fail_4:
- for (i = 0; i < NXMT; i++) {
- if (sc->sc_xmtmap[i] != NULL)
- bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
- }
- bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
-#endif
+
fail_3:
bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
fail_2:
@@ -364,6 +334,7 @@
struct de_softc *sc = (void *)dev;
sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ sc->sc_pdedata = NULL; /* All mappings lost */
DE_WCSR(DE_PCSR0, PCSR0_RSET);
dewait(sc, "reset");
deinit(sc);
@@ -410,9 +381,12 @@
DE_WLOW(CMD_GETCMD);
dewait(sc, "wtring");
- desetup(sc);
+ sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
+ sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
+ DE_WLOW(CMD_GETCMD);
+ dewait(sc, "wtmode");
- /* Link the transmit buffers to the descriptors */
+ /* set up the receive and transmit ring entries */
for (i = 0; i < NXMT; i++) {
dc->dc_xrent[i].r_flags = 0;
dc->dc_xrent[i].r_segbl = LOWORD(&pdc->dc_xbuf[i][0]);
@@ -421,17 +395,14 @@
for (i = 0; i < NRCV; i++)
dc->dc_rrent[i].r_flags = RFLG_OWN;
- sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = sc->sc_nextrx = 0;
/* start up the board (rah rah) */
s = splnet();
+ sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
sc->sc_if.if_flags |= IFF_RUNNING;
- DE_WLOW(PCSR0_INTE); /* Change to interrupts */
- DELAY(500);
+ DE_WLOW(PCSR0_INTE); /* avoid interlock */
+ destart(&sc->sc_if); /* queue output packets */
DE_WLOW(CMD_START|PCSR0_INTE);
- dewait(sc, "start");
- DE_WLOW(CMD_PDMD|PCSR0_INTE);
- dewait(sc, "initpoll");
splx(s);
}
@@ -446,54 +417,45 @@
{
struct de_softc *sc = ifp->if_softc;
struct de_cdata *dc;
+ struct de_ring *rp;
struct mbuf *m;
- int idx, s, running;
+ int nxmit;
/*
* the following test is necessary, since
* the code is not reentrant and we have
* multiple transmission buffers.
*/
- if (ifp->if_flags & IFF_OACTIVE) /* Too much to do already */
+ if (sc->sc_if.if_flags & IFF_OACTIVE)
return;
-
- if (ifp->if_snd.ifq_head == 0) /* Nothing to do at all */
- return;
-
- s = splimp();
dc = sc->sc_dedata;
- running = (sc->sc_inq != 0);
- while (sc->sc_inq < (NXMT - 1)) {
-
- idx = sc->sc_nexttx;
- IF_DEQUEUE(&ifp->if_snd, m);
+ for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == 0)
- goto out;
+ break;
+ rp = &dc->dc_xrent[sc->sc_xfree];
+ if (rp->r_flags & XFLG_OWN)
+ panic("deuna xmit in progress");
+ m_copydata(m, 0, m->m_pkthdr.len, &dc->dc_xbuf[sc->sc_xfree][0]);
+ rp->r_slen = m->m_pkthdr.len;
+ rp->r_tdrerr = 0;
+ rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
- m_copydata(m, 0, m->m_pkthdr.len, &dc->dc_xbuf[idx][0]);
- dc->dc_xrent[idx].r_slen = m->m_pkthdr.len;
- dc->dc_xrent[idx].r_tdrerr = 0;
- dc->dc_xrent[idx].r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
+
m_freem(m);
-
- sc->sc_inq++;
- if (++sc->sc_nexttx == NXMT)
- sc->sc_nexttx = 0;
- ifp->if_timer = 5; /* If transmit logic dies */
+ sc->sc_xfree++;
+ if (sc->sc_xfree == NXMT)
+ sc->sc_xfree = 0;
}
- if (sc->sc_inq == (NXMT - 1))
- ifp->if_flags |= IFF_OACTIVE;
-
-out: if (running == 0) {
- DE_WLOW(PCSR0_INTE|CMD_PDMD);
- dewait(sc, "poll");
+ if (sc->sc_nxmit != nxmit) {
+ sc->sc_nxmit = nxmit;
+ if (ifp->if_flags & IFF_RUNNING)
+ DE_WLOW(PCSR0_INTE|CMD_PDMD);
}
-
- splx(s);
}
/*
@@ -502,79 +464,59 @@
void
deintr(void *arg)
{
+ struct de_cdata *dc;
struct de_softc *sc = arg;
- short csr0, csr1;
+ struct de_ring *rp;
+ short csr0;
/* save flags right away - clear out interrupt bits */
csr0 = DE_RCSR(DE_PCSR0);
- csr1 = DE_RCSR(DE_PCSR1);
DE_WHIGH(csr0 >> 8);
- if (csr0 & PCSR0_RXI)
- derecv(sc);
- if (csr0 & PCSR0_TXI)
- dexmit(sc);
-
- /* Should never end up here */
- if (csr0 & PCSR0_PCEI) {
- printf("%s: Port command error interrupt\n",
- sc->sc_dev.dv_xname);
- }
-
- if (csr0 & PCSR0_SERI) {
- printf("%s: Status error interrupt\n", sc->sc_dev.dv_xname);
- }
-
- if (csr0 & PCSR0_RCBI) {
- printf("%s: Receive buffer unavail interrupt\n",
- sc->sc_dev.dv_xname);
- DE_WLOW(PCSR0_INTE|CMD_PDMD);
- dewait(sc, "repoll");
- }
- destart(&sc->sc_if);
-}
-
-void
-dexmit(struct de_softc *sc)
-{
- struct ifnet *ifp = &sc->sc_if;
- struct de_ring *rp;
+ sc->sc_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */
+ /*
+ * if receive, put receive buffer on mbuf
+ * and hang the request again
+ */
+ derecv(sc);
/*
* Poll transmit ring and check status.
+ * Be careful about loopback requests.
* Then free buffer space and check for
* more transmit requests.
*/
- rp = &sc->sc_dedata->dc_xrent[sc->sc_lastack];
- while ((rp->r_flags & XFLG_OWN) == 0) {
- int idx = sc->sc_lastack;
-
- if (idx == sc->sc_nexttx)
+ dc = sc->sc_dedata;
+ for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
+ rp = &dc->dc_xrent[sc->sc_xindex];
+ if (rp->r_flags & XFLG_OWN)
break;
- if (rp->r_flags & XFLG_ENP)
- ifp->if_opackets++;
Home |
Main Index |
Thread Index |
Old Index