Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-2-0]: src/sys/arch/sgimips/hpc Pull up revisions 1.22-1.23 (reque...
details: https://anonhg.NetBSD.org/src/rev/234162fa3208
branches: netbsd-2-0
changeset: 564756:234162fa3208
user: he <he%NetBSD.org@localhost>
date: Wed Apr 06 17:16:03 2005 +0000
description:
Pull up revisions 1.22-1.23 (requested by rumble in ticket #1054):
Fix the HPC1 transmit logic, which was previously very broken.
diffstat:
sys/arch/sgimips/hpc/if_sq.c | 346 +++++++++++++++++++++++++++---------------
1 files changed, 220 insertions(+), 126 deletions(-)
diffs (truncated from 550 to 300 lines):
diff -r dd22e33598cb -r 234162fa3208 sys/arch/sgimips/hpc/if_sq.c
--- a/sys/arch/sgimips/hpc/if_sq.c Wed Apr 06 17:13:41 2005 +0000
+++ b/sys/arch/sgimips/hpc/if_sq.c Wed Apr 06 17:16:03 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sq.c,v 1.20.2.1 2005/04/06 17:12:07 he Exp $ */
+/* $NetBSD: if_sq.c,v 1.20.2.2 2005/04/06 17:16:03 he Exp $ */
/*
* Copyright (c) 2001 Rafal K. Boni
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.20.2.1 2005/04/06 17:12:07 he Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.20.2.2 2005/04/06 17:16:03 he Exp $");
#include "bpfilter.h"
@@ -113,46 +113,15 @@
static int sq_intr(void *);
static int sq_rxintr(struct sq_softc *);
static int sq_txintr(struct sq_softc *);
+static void sq_txring_hpc1(struct sq_softc *);
+static void sq_txring_hpc3(struct sq_softc *);
static void sq_reset(struct sq_softc *);
static int sq_add_rxbuf(struct sq_softc *, int);
static void sq_dump_buffer(u_int32_t addr, u_int32_t len);
+static void sq_trace_dump(struct sq_softc *);
static void enaddr_aton(const char*, u_int8_t*);
-/* Actions */
-#define SQ_RESET 1
-#define SQ_ADD_TO_DMA 2
-#define SQ_START_DMA 3
-#define SQ_DONE_DMA 4
-#define SQ_RESTART_DMA 5
-#define SQ_TXINTR_ENTER 6
-#define SQ_TXINTR_EXIT 7
-#define SQ_TXINTR_BUSY 8
-
-struct sq_action_trace {
- int action;
- int bufno;
- int status;
- int freebuf;
-};
-
-#define SQ_TRACEBUF_SIZE 100
-int sq_trace_idx = 0;
-struct sq_action_trace sq_trace[SQ_TRACEBUF_SIZE];
-
-void sq_trace_dump(struct sq_softc* sc);
-
-#define SQ_TRACE(act, buf, stat, free) do { \
- sq_trace[sq_trace_idx].action = (act); \
- sq_trace[sq_trace_idx].bufno = (buf); \
- sq_trace[sq_trace_idx].status = (stat); \
- sq_trace[sq_trace_idx].freebuf = (free); \
- if (++sq_trace_idx == SQ_TRACEBUF_SIZE) { \
- memset(&sq_trace, 0, sizeof(sq_trace)); \
- sq_trace_idx = 0; \
- } \
-} while (0)
-
CFATTACH_DECL(sq, sizeof(struct sq_softc),
sq_match, sq_attach, NULL, NULL);
@@ -315,7 +284,7 @@
if_attach(ifp);
ether_ifattach(ifp, sc->sc_enaddr);
- memset(&sq_trace, 0, sizeof(sq_trace));
+ memset(&sc->sq_trace, 0, sizeof(sc->sq_trace));
/* Done! */
return;
@@ -368,7 +337,7 @@
sc->sc_nfreetx = SQ_NTXDESC;
sc->sc_nexttx = sc->sc_prevtx = 0;
- SQ_TRACE(SQ_RESET, 0, 0, sc->sc_nfreetx);
+ SQ_TRACE(SQ_RESET, sc, 0, 0);
/* Set into 8003 mode, bank 0 to program ethernet address */
bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, TXCMD_BANK0);
@@ -405,9 +374,9 @@
/* Set up HPC ethernet DMA config */
if (sc->hpc_regs->revision == 3) {
reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch,
- sc->hpc_regs->enetr_dmacfg);
+ HPC_ENETR_DMACFG);
bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
- sc->hpc_regs->enetr_dmacfg,
+ HPC_ENETR_DMACFG,
reg | ENETR_DMACFG_FIX_RXDC |
ENETR_DMACFG_FIX_INTR |
ENETR_DMACFG_FIX_EOP);
@@ -421,6 +390,14 @@
bus_space_write_4(sc->sc_hpct, sc->sc_hpch, sc->hpc_regs->enetr_ctl,
sc->hpc_regs->enetr_ctl_active);
+ /*
+ * Turn off delayed receive interrupts on HPC1.
+ * (see Hollywood HPC Specification 2.1.4.3)
+ */
+ if (sc->hpc_regs->revision != 3)
+ bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC1_ENET_INTDELAY,
+ HPC1_ENET_INTDELAYVAL);
+
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -472,6 +449,8 @@
{
int s, error = 0;
+ SQ_TRACE(SQ_IOCTL, (struct sq_softc *)ifp->if_softc, 0, 0);
+
s = splnet();
error = ether_ioctl(ifp, cmd, data);
@@ -611,6 +590,8 @@
* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
*/
+ SQ_TRACE(SQ_ENQUEUE, sc, sc->sc_nexttx, 0);
+
/* Sync the DMA map. */
bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -680,7 +661,6 @@
/* Advance the tx pointer. */
sc->sc_nfreetx -= dmamap->dm_nsegs;
sc->sc_nexttx = nexttx;
-
}
/* All transmit descriptors used up, let upper layers know */
@@ -697,8 +677,9 @@
* last packet we enqueued, mark it as the last
* descriptor.
*
- * HDD_CTL_EOPACKET && HDD_CTL_INTR cause an
- * interrupt.
+ * HDD_CTL_INTR will generate an interrupt on
+ * HPC1 by itself. HPC3 will not interrupt unless
+ * HDD_CTL_EOPACKET is set as well.
*/
KASSERT(lasttx != -1);
if (sc->hpc_regs->revision == 3) {
@@ -729,32 +710,52 @@
sc->hpc_regs->enetx_ctl);
if ((status & sc->hpc_regs->enetx_ctl_active) != 0) {
- SQ_TRACE(SQ_ADD_TO_DMA, firsttx, status,
- sc->sc_nfreetx);
+ SQ_TRACE(SQ_ADD_TO_DMA, sc, firsttx, status);
/* NB: hpc3_hdd_ctl is also hpc1_hdd_bufptr */
sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc3_hdd_ctl &=
~HDD_CTL_EOCHAIN;
+ if (sc->hpc_regs->revision != 3)
+ sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc1_hdd_ctl
+ &= ~HPC1_HDD_CTL_INTR;
+
SQ_CDTXSYNC(sc, SQ_PREVTX(firsttx), 1,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- } else {
- SQ_TRACE(SQ_START_DMA, firsttx, status, sc->sc_nfreetx);
+ } else if (sc->hpc_regs->revision == 3) {
+ SQ_TRACE(SQ_START_DMA, sc, firsttx, status);
bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
- sc->hpc_regs->enetx_ndbp, SQ_CDTXADDR(sc, firsttx));
-
- if (sc->hpc_regs->revision != 3) {
- bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
- HPC1_ENETX_CFXBP, SQ_CDTXADDR(sc, firsttx));
- bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
- HPC1_ENETX_CBP, SQ_CDTXADDR(sc, firsttx));
- }
+ HPC_ENETX_NDBP, SQ_CDTXADDR(sc, firsttx));
/* Kick DMA channel into life */
bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
- sc->hpc_regs->enetx_ctl,
- sc->hpc_regs->enetx_ctl_active);
+ HPC_ENETX_CTL, ENETX_CTL_ACTIVE);
+ } else {
+ /*
+ * In the HPC1 case where transmit DMA is
+ * inactive, we can either kick off if
+ * the ring was previously empty, or call
+ * our transmit interrupt handler to
+ * figure out if the ring stopped short
+ * and restart at the right place.
+ */
+ if (ofree == SQ_NTXDESC) {
+ SQ_TRACE(SQ_START_DMA, sc, firsttx, status);
+
+ bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+ HPC1_ENETX_NDBP,
+ SQ_CDTXADDR(sc, firsttx));
+ bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+ HPC1_ENETX_CFXBP, SQ_CDTXADDR(sc, firsttx));
+ bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+ HPC1_ENETX_CBP, SQ_CDTXADDR(sc, firsttx));
+
+ /* Kick DMA channel into life */
+ bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+ HPC1_ENETX_CTL, HPC1_ENETX_CTL_ACTIVE);
+ } else
+ sq_txring_hpc1(sc);
}
/* Set a watchdog timer in case the chip flakes out. */
@@ -801,23 +802,39 @@
sq_trace_dump(sc);
- memset(&sq_trace, 0, sizeof(sq_trace));
- sq_trace_idx = 0;
+ memset(&sc->sq_trace, 0, sizeof(sc->sq_trace));
+ sc->sq_trace_idx = 0;
++ifp->if_oerrors;
sq_init(ifp);
}
-void sq_trace_dump(struct sq_softc* sc)
+static void
+sq_trace_dump(struct sq_softc *sc)
{
int i;
+ char *act;
- for(i = 0; i < sq_trace_idx; i++) {
- printf("%s: [%d] action %d, buf %d, free %d, status %08x\n",
- sc->sc_dev.dv_xname, i, sq_trace[i].action,
- sq_trace[i].bufno, sq_trace[i].freebuf,
- sq_trace[i].status);
+ for (i = 0; i < sc->sq_trace_idx; i++) {
+ switch (sc->sq_trace[i].action) {
+ case SQ_RESET: act = "SQ_RESET"; break;
+ case SQ_ADD_TO_DMA: act = "SQ_ADD_TO_DMA"; break;
+ case SQ_START_DMA: act = "SQ_START_DMA"; break;
+ case SQ_DONE_DMA: act = "SQ_DONE_DMA"; break;
+ case SQ_RESTART_DMA: act = "SQ_RESTART_DMA"; break;
+ case SQ_TXINTR_ENTER: act = "SQ_TXINTR_ENTER"; break;
+ case SQ_TXINTR_EXIT: act = "SQ_TXINTR_EXIT"; break;
+ case SQ_TXINTR_BUSY: act = "SQ_TXINTR_BUSY"; break;
+ case SQ_IOCTL: act = "SQ_IOCTL"; break;
+ case SQ_ENQUEUE: act = "SQ_ENQUEUE"; break;
+ default: act = "UNKNOWN";
+ }
+
+ printf("%s: [%03d] action %-16s buf %03d free %03d "
+ "status %08x line %d\n", sc->sc_dev.dv_xname, i, act,
+ sc->sq_trace[i].bufno, sc->sq_trace[i].freebuf,
+ sc->sq_trace[i].status, sc->sq_trace[i].line);
}
}
@@ -928,6 +945,8 @@
sc->sc_rxmap[i]->dm_mapsize,
BUS_DMASYNC_PREREAD);
SQ_INIT_RXDESC(sc, i);
+ SQ_DPRINTF(("%s: sq_rxintr: buf %d no RXSTAT_GOOD\n",
+ sc->sc_dev.dv_xname, i));
continue;
}
@@ -937,6 +956,8 @@
sc->sc_rxmap[i]->dm_mapsize,
BUS_DMASYNC_PREREAD);
SQ_INIT_RXDESC(sc, i);
+ SQ_DPRINTF(("%s: sq_rxintr: buf %d sq_add_rxbuf() "
+ "failed\n", sc->sc_dev.dv_xname, i));
continue;
}
@@ -995,11 +1016,8 @@
static int
sq_txintr(struct sq_softc *sc)
{
- int i;
int shift = 0;
u_int32_t status;
- u_int32_t hpc1_ready = 0;
- u_int32_t hpc3_not_ready = 1;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
if (sc->hpc_regs->revision != 3)
@@ -1008,10 +1026,9 @@
status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch,
sc->hpc_regs->enetx_ctl) >> shift;
Home |
Main Index |
Thread Index |
Old Index