Handle the `ESC gate array' variant of the DMA engine, including an

essential bug work-around. Graciously supplied by David Miller.

Also re-arrange the macros that do the dma drain song-and-dance for
better clarity.
This commit is contained in:
pk 1996-11-27 21:48:19 +00:00
parent f5f35b104f
commit c7f438cd11
1 changed files with 57 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dma.c,v 1.35 1996/11/13 06:13:41 thorpej Exp $ */
/* $NetBSD: dma.c,v 1.36 1996/11/27 21:48:19 pk Exp $ */
/*
* Copyright (c) 1994 Paul Kranenburg. All rights reserved.
@ -193,6 +193,8 @@ dmaattach(parent, self, aux)
case DMAREV_0:
printf("0");
break;
case DMAREV_ESC:
printf("esc");
case DMAREV_1:
printf("1");
break;
@ -203,7 +205,7 @@ dmaattach(parent, self, aux)
printf("2");
break;
default:
printf("unknown");
printf("unknown (0x%x)", sc->sc_rev);
}
printf("\n");
@ -272,21 +274,59 @@ espsearch:
}
}
#define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \
int count = 500000; \
while ((COND) && --count > 0) DELAY(1); \
if (count == 0) { \
printf("%s: line %d: CSR = %lx\n", __FILE__, __LINE__, \
(SC)->sc_regs->csr); \
if (DONTPANIC) \
printf(MSG); \
else \
panic(MSG); \
} \
} while (0)
#define DMA_DRAIN(sc, dontpanic) do { \
/* \
* DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
* and "drain" bits while it is still thinking about a \
* request. \
* other revs: D_R_PEND bit reads as 0 \
*/ \
DMAWAIT(sc, sc->sc_regs->csr & D_R_PEND, "R_PEND", dontpanic); \
/* \
* select drain bit based on revision \
* also clears errors and D_TC flag \
*/ \
if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \
DMACSR(sc) |= D_DRAIN; \
else \
DMACSR(sc) |= D_INVALIDATE; \
/* \
* Wait for draining to finish \
* rev0 & rev1 call this PACKCNT \
*/ \
DMAWAIT(sc, sc->sc_regs->csr & D_DRAINING, "DRAINING", dontpanic);\
} while(0)
void
dma_reset(sc)
struct dma_softc *sc;
{
DMAWAIT(sc);
DMA_DRAIN(sc); /* Drain (DMA rev 1) */
DMA_DRAIN(sc, 1);
DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */
DMAWAIT1(sc); /* let things drain */
DMACSR(sc) |= D_RESET; /* reset DMA */
DELAY(200); /* what should this be ? */
DMAWAIT1(sc);
/*DMAWAIT1(sc); why was this here? */
DMACSR(sc) &= ~D_RESET; /* de-assert reset line */
DMACSR(sc) |= D_INT_EN; /* enable interrupts */
if (sc->sc_rev > DMAREV_1)
DMACSR(sc) |= D_FASTER;
if (sc->sc_rev == DMAREV_ESC) {
/*DMACSR(sc) |= 0x800; -* 16-byte burst mode */
DMACSR(sc) |= D_AUTODRAIN; /* Auto-drain */
}
sc->sc_active = 0; /* and of course we aren't */
}
@ -321,12 +361,7 @@ dma_setup(sc, addr, len, datain, dmasize)
{
u_long csr;
/* clear errors and D_TC flag */
DMAWAIT(sc);
DMA_DRAIN(sc); /* ? */
DMAWAIT1(sc);
DMACSR(sc) |= D_INVALIDATE;
DMAWAIT1(sc);
DMA_DRAIN(sc, 0);
#if 0
DMACSR(sc) &= ~D_INT_EN;
@ -361,6 +396,14 @@ dma_setup(sc, addr, len, datain, dmasize)
} else
DMADDR(sc) = *sc->sc_dmaaddr;
if (sc->sc_rev == DMAREV_ESC) {
/* DMA ESC chip bug work-around */
register long bcnt = sc->sc_dmasize;
register long eaddr = bcnt + (long)*sc->sc_dmaaddr;
if ((eaddr & PGOFSET) != 0)
bcnt = roundup(bcnt, NBPG);
DMACNT(sc) = bcnt;
}
/* Setup DMA control register */
csr = DMACSR(sc);
if (datain)
@ -408,19 +451,14 @@ espdmaintr(sc)
DMACSR(sc) |= D_INVALIDATE;
printf("%s: error: csr=%s\n", sc->sc_dev.dv_xname,
bitmask_snprintf(csr, DMACSRBITS, bits, sizeof(bits)));
return 0;
return -1;
}
/* This is an "assertion" :) */
if (sc->sc_active == 0)
panic("dmaintr: DMA wasn't active");
/* clear errors and D_TC flag */
DMAWAIT(sc);
DMA_DRAIN(sc); /* ? */
DMAWAIT1(sc);
DMACSR(sc) |= D_INVALIDATE;
DMAWAIT1(sc);
DMA_DRAIN(sc, 0);
/* DMA has stopped */
DMACSR(sc) &= ~D_EN_DMA;