Handle sun4m ledma' and
espdma'.
DMA setup requires services of the IOMMU.
This commit is contained in:
parent
7e45b3449f
commit
954302ae70
@ -1,7 +1,9 @@
|
||||
/* $NetBSD: dma.c,v 1.22 1996/03/26 01:28:50 pk Exp $ */
|
||||
/* $NetBSD: dma.c,v 1.23 1996/03/31 22:32:45 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Paul Kranenburg. All rights reserved.
|
||||
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -58,9 +60,10 @@ int dmamatch __P((struct device *, void *, void *));
|
||||
void dma_reset __P((struct dma_softc *));
|
||||
void dma_enintr __P((struct dma_softc *));
|
||||
int dma_isintr __P((struct dma_softc *));
|
||||
void dma_start __P((struct dma_softc *, caddr_t *, size_t *, int));
|
||||
int dmaintr __P((struct dma_softc *));
|
||||
int dma_setup __P((struct dma_softc *, caddr_t *, size_t *, int, size_t *));
|
||||
int espdmaintr __P((struct dma_softc *));
|
||||
int ledmaintr __P((struct dma_softc *));
|
||||
int dma_setup __P((struct dma_softc *, caddr_t *, size_t *,
|
||||
int, size_t *));
|
||||
void dma_go __P((struct dma_softc *));
|
||||
|
||||
struct cfattach dma_ca = {
|
||||
@ -92,6 +95,11 @@ dmaprint(aux, name)
|
||||
void *aux;
|
||||
char *name;
|
||||
{
|
||||
register struct confargs *ca = aux;
|
||||
|
||||
if (name)
|
||||
printf("[%s at %s]", ca->ca_ra.ra_name, name);
|
||||
printf(" slot 0x%x offset 0x%x", ca->ca_slot, ca->ca_offset);
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
@ -122,32 +130,39 @@ dmaattach(parent, self, aux)
|
||||
{
|
||||
register struct confargs *ca = aux;
|
||||
struct dma_softc *sc = (void *)self;
|
||||
#if defined(SUN4M)
|
||||
int node;
|
||||
struct confargs oca;
|
||||
char *name;
|
||||
#endif
|
||||
|
||||
if (ca->ca_ra.ra_vaddr == NULL)
|
||||
if (ca->ca_ra.ra_vaddr == NULL || ca->ca_ra.ra_nvaddrs == 0)
|
||||
ca->ca_ra.ra_vaddr =
|
||||
mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len,
|
||||
ca->ca_bustype);
|
||||
|
||||
sc->sc_regs = (struct dma_regs *) ca->ca_ra.ra_vaddr;
|
||||
|
||||
/*
|
||||
* find the ESP by poking around the esp device structures
|
||||
*
|
||||
* What happens here is that if the esp driver has not been
|
||||
* configured, then this returns a NULL pointer. Then when the
|
||||
* esp actually gets configured, it does the opposing test, and
|
||||
* if the sc->sc_dma field in it's softc is NULL, then tries to
|
||||
* find the matching dma driver.
|
||||
*
|
||||
*/
|
||||
sc->sc_esp = ((struct esp_softc *)
|
||||
getdevunit("esp", sc->sc_dev.dv_unit));
|
||||
if (!CPU_ISSUN4M) {
|
||||
/*
|
||||
* find the ESP by poking around the esp device structures
|
||||
*
|
||||
* What happens here is that if the esp driver has not been
|
||||
* configured, then this returns a NULL pointer. Then when the
|
||||
* esp actually gets configured, it does the opposing test, and
|
||||
* if the sc->sc_dma field in it's softc is NULL, then tries to
|
||||
* find the matching dma driver.
|
||||
*
|
||||
*/
|
||||
sc->sc_esp = (struct esp_softc *)
|
||||
getdevunit("esp", sc->sc_dev.dv_unit);
|
||||
|
||||
/*
|
||||
* and a back pointer to us, for DMA
|
||||
*/
|
||||
if (sc->sc_esp)
|
||||
sc->sc_esp->sc_dma = sc;
|
||||
/*
|
||||
* and a back pointer to us, for DMA
|
||||
*/
|
||||
if (sc->sc_esp)
|
||||
sc->sc_esp->sc_dma = sc;
|
||||
}
|
||||
|
||||
printf(": rev ");
|
||||
sc->sc_rev = sc->sc_regs->csr & D_DEV_ID;
|
||||
@ -170,12 +185,17 @@ dmaattach(parent, self, aux)
|
||||
printf("\n");
|
||||
|
||||
/* indirect functions */
|
||||
if (sc->sc_dev.dv_cfdata->cf_attach == &espdma_ca ||
|
||||
sc->sc_dev.dv_cfdata->cf_attach == &dma_ca) {
|
||||
sc->intr = espdmaintr;
|
||||
} else {
|
||||
sc->intr = ledmaintr;
|
||||
}
|
||||
sc->enintr = dma_enintr;
|
||||
sc->isintr = dma_isintr;
|
||||
sc->reset = dma_reset;
|
||||
sc->setup = dma_setup;
|
||||
sc->go = dma_go;
|
||||
sc->intr = dmaintr;
|
||||
|
||||
sc->sc_node = ca->ca_ra.ra_node;
|
||||
#if defined(SUN4C) || defined(SUN4M)
|
||||
@ -183,26 +203,28 @@ dmaattach(parent, self, aux)
|
||||
sbus_establish(&sc->sc_sd, &sc->sc_dev);
|
||||
#endif /* SUN4C || SUN4M */
|
||||
|
||||
#ifdef notyet
|
||||
#if defined(SUN4M)
|
||||
/* return if we are a plain "dma" with no children */
|
||||
if (strcmp(getpropstring(node, "name"), "dma") == 0)
|
||||
if (sc->sc_dev.dv_cfdata->cf_attach == &dma_ca)
|
||||
return;
|
||||
|
||||
/* Propagate bootpath */
|
||||
if (ca->ca_ra.ra_bp != NULL &&
|
||||
(strcmp(ca->ca_ra.ra_bp->name, "espdma") == 0 ||
|
||||
strcmp(ca->ca_ra.ra_bp->name, "ledma") == 0))
|
||||
oca.ca_ra.ra_bp = ca->ca_ra.ra_bp + 1;
|
||||
else
|
||||
oca.ca_ra.ra_bp = NULL;
|
||||
|
||||
/* search through children */
|
||||
for (node = firstchild(sc->sc_node); node; node = nextsibling(node)) {
|
||||
name = getpropstring(node, "name");
|
||||
if (!romprop(&ca->ca_ra, name, node))
|
||||
if (!romprop(&oca.ca_ra, name, node))
|
||||
continue;
|
||||
base = (int)ca->ca_ra.ra_paddr;
|
||||
if (SBUS_ABS(base)) {
|
||||
ca->ca_slot = SBUS_ABS_TO_SLOT(base);
|
||||
ca->ca_offset = SBUS_ABS_TO_OFFSET(base);
|
||||
} else {
|
||||
ca->ca_slot = slot = ca->ca_ra.ra_iospace;
|
||||
ca->ca_offset = base;
|
||||
ca->ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base);
|
||||
}
|
||||
(void) config_found(&sc->sc_dev, (void *)&ca, dmaprint);
|
||||
|
||||
sbus_translate(parent, &oca);
|
||||
oca.ca_bustype = BUS_SBUS;
|
||||
(void) config_found(&sc->sc_dev, (void *)&oca, dmaprint);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -242,6 +264,7 @@ dma_isintr(sc)
|
||||
|
||||
#define DMAMAX(a) (0x01000000 - ((a) & 0x00ffffff))
|
||||
|
||||
|
||||
/*
|
||||
* setup a dma transfer
|
||||
*/
|
||||
@ -282,8 +305,7 @@ dma_setup(sc, addr, len, datain, dmasize)
|
||||
ESP_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize));
|
||||
|
||||
/* Program the DMA address */
|
||||
#if defined(SUN4M)
|
||||
if (sc->sc_dmasize && cputyp == CPU_SUN4M) {
|
||||
if (CPU_ISSUN4M && sc->sc_dmasize) {
|
||||
/*
|
||||
* Use dvma mapin routines to map the buffer into DVMA space.
|
||||
*/
|
||||
@ -294,7 +316,6 @@ dma_setup(sc, addr, len, datain, dmasize)
|
||||
panic("dma: cannot allocate DVMA address");
|
||||
DMADDR(sc) = sc->sc_dvmakaddr;
|
||||
} else
|
||||
#endif
|
||||
DMADDR(sc) = *sc->sc_dmaaddr;
|
||||
|
||||
/* Setup DMA control register */
|
||||
@ -327,7 +348,7 @@ dma_go(sc)
|
||||
* return 1 if it was a DMA continue.
|
||||
*/
|
||||
int
|
||||
dmaintr(sc)
|
||||
espdmaintr(sc)
|
||||
struct dma_softc *sc;
|
||||
{
|
||||
int trans = 0, resid = 0;
|
||||
@ -402,11 +423,9 @@ dmaintr(sc)
|
||||
if (csr & D_WRITE)
|
||||
cache_flush(*sc->sc_dmaaddr, trans);
|
||||
|
||||
#if defined(SUN4M)
|
||||
if (cputyp == CPU_SUN4M && sc->sc_dvmakaddr)
|
||||
if (CPU_ISSUN4M && sc->sc_dvmakaddr)
|
||||
dvma_mapout((vm_offset_t)sc->sc_dvmakaddr,
|
||||
(vm_offset_t)sc->sc_dvmaaddr, sc->sc_dmasize);
|
||||
#endif
|
||||
|
||||
*sc->sc_dmalen -= trans;
|
||||
*sc->sc_dmaaddr += trans;
|
||||
@ -422,3 +441,27 @@ dmaintr(sc)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pseudo (chained) interrupt from the le driver to handle DMA
|
||||
* errors.
|
||||
*
|
||||
* XXX: untested
|
||||
*/
|
||||
int
|
||||
ledmaintr(sc)
|
||||
struct dma_softc *sc;
|
||||
{
|
||||
u_long csr;
|
||||
|
||||
csr = DMACSR(sc);
|
||||
|
||||
if (csr & D_ERR_PEND) {
|
||||
printf("Lance DMA error, see your doctor!\n");
|
||||
DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */
|
||||
DMACSR(sc) |= D_INVALIDATE;
|
||||
printf("%s: error: csr=%b\n", sc->sc_dev.dv_xname,
|
||||
(u_int)csr, DMACSRBITS);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dmareg.h,v 1.6 1995/12/11 12:43:21 pk Exp $ */
|
||||
/* $NetBSD: dmareg.h,v 1.7 1996/03/31 22:32:46 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
|
||||
@ -69,5 +69,8 @@ struct dma_regs {
|
||||
#define D_BCNT_MASK 0x00ffffff /* only 24 bits */
|
||||
|
||||
volatile u_long test; /* DMA TEST (in u_longs) */
|
||||
#define en_testcsr addr /* enet registers overlap */
|
||||
#define en_cachev bcnt
|
||||
#define en_bar test
|
||||
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: dmavar.h,v 1.6 1996/03/16 23:28:28 christos Exp $ */
|
||||
/* $NetBSD: dmavar.h,v 1.7 1996/03/31 22:32:48 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
|
||||
@ -32,6 +32,7 @@ struct dma_softc {
|
||||
struct device sc_dev; /* us as a device */
|
||||
struct sbusdev sc_sd; /* sbus device */
|
||||
struct esp_softc *sc_esp; /* my scsi */
|
||||
struct le_softc *sc_le; /* my ethernet */
|
||||
struct dma_regs *sc_regs; /* the registers */
|
||||
int sc_active; /* DMA active ? */
|
||||
int sc_rev; /* revision */
|
||||
@ -77,3 +78,12 @@ struct dma_softc {
|
||||
DMACSR(sc) |= D_DRAIN; \
|
||||
DMAWAIT1(sc); \
|
||||
}
|
||||
|
||||
/* DMA engine functions */
|
||||
#define DMA_ENINTR(r) (((r)->enintr)(r))
|
||||
#define DMA_ISINTR(r) (((r)->isintr)(r))
|
||||
#define DMA_RESET(r) (((r)->reset)(r))
|
||||
#define DMA_INTR(r) (((r)->intr)(r))
|
||||
#define DMA_ISACTIVE(r) ((r)->sc_active)
|
||||
#define DMA_SETUP(a, b, c, d, e) (((a)->setup)(a, b, c, d, e))
|
||||
#define DMA_GO(r) (((r)->go)(r))
|
||||
|
Loading…
Reference in New Issue
Block a user