Revamped DMA interface to unify chaining and non-chaining dma sequences.

Updated ethernet driver to work with new interface.
Continue work on esp driver.
This commit is contained in:
dbj 1998-12-19 09:31:44 +00:00
parent 12632ebf71
commit db8bf6a623
5 changed files with 236 additions and 155 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: esp.c,v 1.9 1998/11/19 21:47:39 thorpej Exp $ */
/* $NetBSD: esp.c,v 1.10 1998/12/19 09:31:44 dbj Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@ -118,7 +118,8 @@
#endif
#ifdef ESP_DEBUG
#define DPRINTF(x) printf x;
int esp_debug = 0;
#define DPRINTF(x) if (esp_debug) printf x;
#else
#define DPRINTF(x)
#endif
@ -307,7 +308,6 @@ espattach_intio(parent, self, aux)
}
esc->sc_scsi_dma.nd_intr = NEXT_I_SCSI_DMA;
esc->sc_scsi_dma.nd_chaining_flag = 0;
esc->sc_scsi_dma.nd_shutdown_cb = &esp_dmacb_shutdown;
esc->sc_scsi_dma.nd_continue_cb = &esp_dmacb_continue;
esc->sc_scsi_dma.nd_completed_cb = &esp_dmacb_completed;
@ -338,6 +338,7 @@ espattach_intio(parent, self, aux)
esc->sc_slop_end_addr = 0;
esc->sc_slop_end_size = 0;
esc->sc_datain = -1;
esc->sc_dmamap_loaded = 0;
/* Establish interrupt channel */
isrlink_autovec((int(*)__P((void*)))ncr53c9x_intr, sc,
@ -387,7 +388,7 @@ esp_dma_isintr(sc)
int r = (INTR_OCCURRED(NEXT_I_SCSI));
if (r) {
DPRINTF(("esp_dma_isintr = %d\n",r));
DPRINTF(("esp_dma_isintr = 0x%b\n",r,NEXT_INTR_BITS));
if (esc->sc_datain) {
NCR_WRITE_REG(sc, ESP_DCTL,
@ -418,6 +419,7 @@ esp_dma_reset(sc)
esc->sc_slop_end_addr = 0;
esc->sc_slop_end_size = 0;
esc->sc_datain = -1;
esc->sc_dmamap_loaded = 0;
}
int
@ -520,10 +522,12 @@ esp_dma_setup(sc, addr, len, datain, dmasize)
#ifdef DIAGNOSTIC
if ((esc->sc_datain != -1) ||
(esc->sc_dmamap->dm_mapsize != 0)) {
(esc->sc_dmamap->dm_mapsize != 0) ||
(esc->sc_dmamap_loaded != 0)) {
panic("%s: map already loaded in esp_dma_setup\n"
"\tdatain = %d\n\tmapsize=%d",
sc->sc_dev.dv_xname,esc->sc_datain,esc->sc_dmamap->dm_mapsize);
"\tdatain = %d\n\tmapsize=%d\n\tloaed = %d",
sc->sc_dev.dv_xname,esc->sc_datain,esc->sc_dmamap->dm_mapsize,
esc->sc_dmamap_loaded);
}
#endif
@ -546,21 +550,13 @@ esp_dma_setup(sc, addr, len, datain, dmasize)
slop_end_size = end % DMA_ENDALIGNMENT;
}
/* Check to make sure we haven't counted the slop twice
/* Check to make sure we haven't counted extra slop
* as would happen for a very short dma buffer */
if (slop_bgn_size+slop_end_size > *dmasize) {
#if defined(DIAGNOSTIC)
if ((slop_bgn_size != *dmasize) ||
(slop_end_size != *dmasize)) {
panic("%s: confused alignment calculation\n"
"\tslop_bgn_size %d\n\tslop_end_size %d\n\tdmasize %d",
sc->sc_dev.dv_xname,slop_bgn_size,slop_end_size,*dmasize);
}
#endif
if (slop_bgn_size+slop_end_size >= *dmasize) {
slop_bgn_size = *dmasize;
slop_end_size = 0;
}
if (slop_bgn_size+slop_end_size < *dmasize) {
} else {
int error;
error = bus_dmamap_load(esc->sc_scsi_dma.nd_dmat,
esc->sc_dmamap,
@ -572,10 +568,6 @@ esp_dma_setup(sc, addr, len, datain, dmasize)
sc->sc_dev.dv_xname, error);
}
} else {
/* If there's no DMA, then coalesce the fifo buffers */
slop_bgn_size += slop_end_size;
slop_end_size = 0;
}
esc->sc_slop_bgn_addr = *addr;
@ -719,7 +711,18 @@ esp_dmacb_continue(arg)
}
#endif
return(esc->sc_dmamap);
if (esc->sc_dmamap_loaded == 0) {
esc->sc_dmamap_loaded++;
return(esc->sc_dmamap);
} else {
#ifdef DIAGNOSTIC
if (esc->sc_dmamap_loaded != 1) {
panic("%s: Unexpected sc_dmamap_loaded (%d) != 1 in continue_cb",
sc->sc_dev.dv_xname,esc->sc_dmamap_loaded);
}
#endif
return(0);
}
}
void
@ -733,9 +736,11 @@ esp_dmacb_completed(map, arg)
DPRINTF(("esp dma completed\n"));
#ifdef DIAGNOSTIC
if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) {
panic("%s: map not loaded in dma completed callback, datain = %d",
sc->sc_dev.dv_xname,esc->sc_datain);
if ((esc->sc_datain < 0) ||
(esc->sc_datain > 1) ||
(esc->sc_dmamap_loaded != 1)) {
panic("%s: map not loaded in dma completed callback, datain = %d, loaded = %d",
sc->sc_dev.dv_xname,esc->sc_datain,esc->sc_dmamap_loaded);
}
if (map != esc->sc_dmamap) {
panic("%s: unexpected tx completed map", sc->sc_dev.dv_xname);
@ -781,11 +786,13 @@ esp_dmacb_shutdown(arg)
if (esc->sc_datain) {
int i;
#ifdef DIAGNOSTIC
#if 0 /* This is a fine thing to happen. */
int n = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF);
if (n != esc->sc_slop_end_size) {
panic("%s: Unexpected data in fifo n = %d, expecting %d at end",
sc->sc_dev.dv_xname, n, esc->sc_slop_end_size);
}
#endif
#endif
for(i=0;i<esc->sc_slop_end_size;i++) {
esc->sc_slop_end_addr[i]=NCR_READ_REG(sc, NCR_FIFO);
@ -805,4 +812,11 @@ esp_dmacb_shutdown(arg)
esc->sc_slop_bgn_size = 0;
esc->sc_slop_end_addr = 0;
esc->sc_slop_end_size = 0;
esc->sc_dmamap_loaded--;
#ifdef DIAGNOSTIC
if (esc->sc_dmamap_loaded != 0) {
panic("%s: Unexpected sc_dmamap_loaded (%d) != 0 in shutdown_cb",
sc->sc_dev.dv_xname,esc->sc_dmamap_loaded);
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: espvar.h,v 1.4 1998/07/21 06:17:35 dbj Exp $ */
/* $NetBSD: espvar.h,v 1.5 1998/12/19 09:31:44 dbj Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -48,6 +48,7 @@ struct esp_softc {
caddr_t sc_slop_end_addr; /* bytes to be fifo'd at end */
int sc_slop_bgn_size; /* # bytes to be fifo'd at beginning */
int sc_slop_end_size; /* # bytes to be fifo'd at end */
int sc_dmamap_loaded; /* flag as to whether given to continue_cb yet */
caddr_t *sc_dmaaddr;
size_t *sc_dmalen;
size_t sc_dmasize;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mb8795.c,v 1.7 1998/07/19 21:41:16 dbj Exp $ */
/* $NetBSD: mb8795.c,v 1.8 1998/12/19 09:31:44 dbj Exp $ */
/*
* Copyright (c) 1998 Darrin B. Jewell
* All rights reserved.
@ -223,13 +223,11 @@ mb8795_config(sc)
sc->sc_tx_mb_head = NULL;
sc->sc_tx_loaded = 0;
sc->sc_tx_nd->nd_chaining_flag = 0;
sc->sc_tx_nd->nd_shutdown_cb = mb8795_txdma_shutdown;
sc->sc_tx_nd->nd_continue_cb = mb8795_txdma_continue;
sc->sc_tx_nd->nd_completed_cb = mb8795_txdma_completed;
sc->sc_tx_nd->nd_cb_arg = sc;
sc->sc_rx_nd->nd_chaining_flag = 1;
sc->sc_rx_nd->nd_shutdown_cb = mb8795_rxdma_shutdown;
sc->sc_rx_nd->nd_continue_cb = mb8795_rxdma_continue;
sc->sc_rx_nd->nd_completed_cb = mb8795_rxdma_completed;
@ -820,10 +818,9 @@ mb8795_start(ifp)
sc->sc_tx_mb_head = NULL;
return;
}
sc->sc_tx_loaded++;
#ifdef DIAGNOSTIC
if (sc->sc_tx_loaded != 1) {
if (sc->sc_tx_loaded != 0) {
panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
sc->sc_tx_loaded);
}
@ -949,13 +946,7 @@ mb8795_rxdma_shutdown(arg)
{
struct mb8795_softc *sc = arg;
printf("%s: mb8795_rxdma_shutdown(), resetting the interface\n",
sc->sc_dev.dv_xname);
/* we might want to just reset the DMA here instead,
* but this will do.
*/
mb8795_init(sc);
panic("%s: mb8795_rxdma_shutdown() unexpected", sc->sc_dev.dv_xname);
}
@ -1060,14 +1051,21 @@ mb8795_txdma_continue(arg)
void *arg;
{
struct mb8795_softc *sc = arg;
bus_dmamap_t map = sc->sc_tx_dmamap;
bus_dmamap_t map;
DPRINTF(("%s: mb8795_txdma_continue()\n",sc->sc_dev.dv_xname));
if (sc->sc_tx_loaded) {
map = NULL;
} else {
map = sc->sc_tx_dmamap;
sc->sc_tx_loaded++;
}
#ifdef DIAGNOSTIC
if (sc->sc_tx_loaded != 1) {
panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
sc->sc_tx_loaded);
panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
sc->sc_tx_loaded);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: nextdma.c,v 1.6 1998/12/08 09:35:07 dbj Exp $ */
/* $NetBSD: nextdma.c,v 1.7 1998/12/19 09:31:44 dbj Exp $ */
/*
* Copyright (c) 1998 Darrin B. Jewell
* All rights reserved.
@ -251,6 +251,19 @@ next_dma_rotate(nd)
}
nd->_nd_idx_cont = 0;
}
#ifdef DIAGNOSTIC
if (nd->_nd_map_cont) {
if (!DMA_BEGINALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_addr)) {
panic("DMA request unaligned at start\n");
}
if (!DMA_ENDALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_addr +
nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_len)) {
panic("DMA request unaligned at end\n");
}
}
#endif
}
void
@ -284,10 +297,15 @@ next_dma_setup_cont_regs(nd)
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_STOP, 0xdeadbeef);
}
#if 0
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_START));
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_STOP));
#else
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_START, 0xfeedbeef);
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_STOP, 0xfeedbeef);
#endif
}
@ -313,11 +331,16 @@ next_dma_setup_curr_regs(nd)
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT, 0xdeadbeef);
}
#if 0
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF));
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT));
#else
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 0xfeedbeef);
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, 0xfeedbeef);
#endif
} else {
@ -334,10 +357,15 @@ next_dma_setup_curr_regs(nd)
}
#if 0
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT));
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT,
bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT));
#else
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT, 0xfeedbeef);
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT, 0xfeedbeef);
#endif
}
@ -438,127 +466,185 @@ nextdma_intr(arg)
DPRINTF(("DMA interrupt ipl (%ld) intr(0x%b)\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
#ifdef DIAGNOSTIC
if (!nd->_nd_map) {
next_dma_print(nd);
panic("DMA missing current map in interrupt!\n");
}
#endif
{
int state = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_CSR);
state &= (DMACSR_BUSEXC | DMACSR_COMPLETE |
DMACSR_SUPDATE | DMACSR_ENABLE);
if (state & DMACSR_BUSEXC) {
#if 0 /* This bit seems to get set periodically and I don't know why */
next_dma_print(nd);
panic("Bus exception in DMA ipl (%ld) intr(0x%b)\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
#endif
}
#ifdef DIAGNOSTIC
if (!(state & DMACSR_COMPLETE)) {
next_dma_print(nd);
#if 0 /* This bit doesn't seem to get set every once in a while,
* and I don't know why. Let's try treating it as a spurious
* interrupt. ie. report it and ignore the interrupt.
*/
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("DMA ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
#else
printf("DMA ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
return(1);
#endif
}
#endif
/* Set the length of the segment to match actual length.
* @@@ is it okay to resize dma segments here?
* i should probably ask jason about this.
*/
if (nd->_nd_map) {
bus_addr_t next;
bus_addr_t limit;
#if 0
if (state & DMACSR_ENABLE) {
next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
} else {
next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
}
#else
next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
#if 0 /* This bit gets set sometimes & I don't know why. */
#ifdef DIAGNOSTIC
if (state & DMACSR_BUSEXC) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("DMA ipl (%ld) intr(0x%b), DMACSR_COMPLETE not set in intr\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
}
#endif
#endif
limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
if (nd->nd_intr == NEXT_I_ENETX_DMA) {
limit &= ~0x80000000;
}
/* Check to see if we are expecting dma to shut down */
if (!nd->_nd_map_cont) {
#ifdef DIAGNOSTIC
if (next != nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr) {
if (state & (DMACSR_SUPDATE|DMACSR_ENABLE)) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("DMA ipl (%ld) intr(0x%b), unexpected completed address\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS);
panic("unexpected bits set in DMA state at shutdown (0x%b)\n", state,DMACSR_BITS);
}
#endif
/* @@@ I observed a case where DMACSR_ENABLE wasn't set and
* DD_SAVED_LIMIT didn't contain the expected limit value. This
* should be tested, fixed, and removed. */
#ifdef DIAGNOSTIC
#if 0 /* Sometimes the DMA registers have totally bogus values when read.
* Until that's understood, we skip this check
*/
if (((limit-next) > nd->_nd_map->dm_segs[nd->_nd_idx].ds_len)
|| (limit-next < 0)) {
#if 0
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("DMA packlen: next = 0x%08x limit = 0x%08x\n",next,limit);
#else
DPRINTF(("DMA packlen: next = 0x%08x limit = 0x%08x",next,limit));
/* Verify that the registers are laid out as expected */
{
bus_addr_t next;
bus_addr_t limit;
bus_addr_t expected_limit;
expected_limit =
nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr +
nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
if (nd->nd_intr == NEXT_I_ENETX_DMA) {
next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT_INITBUF);
limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT) & ~0x80000000;
} else {
next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_NEXT);
limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_LIMIT);
}
if ((next != limit) || (limit != expected_limit)) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("unexpected DMA limit at shutdown 0x%08x, 0x%08x, 0x%08x",
next,limit,expected_limit);
}
}
#endif
#endif
} else {
nd->_nd_map->dm_segs[nd->_nd_idx].ds_len = limit - next;
}
}
if ((state & DMACSR_ENABLE) == 0) {
/* Non chaining interrupts shutdown immediately */
if (!nd->nd_chaining_flag) {
nd->_nd_map = nd->_nd_map_cont;
nd->_nd_idx = nd->_nd_idx_cont;
nd->_nd_map_cont = 0;
nd->_nd_idx_cont = 0;
}
/* Call the completed callback for the last packet */
if (nd->_nd_map && ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs)) {
if ((nd->_nd_idx+1) == nd->_nd_map->dm_nsegs) {
if (nd->nd_completed_cb)
(*nd->nd_completed_cb)(nd->_nd_map, nd->nd_cb_arg);
}
nd->_nd_map = 0;
nd->_nd_idx = 0;
if (nd->_nd_map_cont) {
DPRINTF(("DMA ipl (%ld) intr(0x%b), restarting\n",
NEXT_I_IPL(nd->nd_intr), NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_CLRCOMPLETE | DMACSR_RESET);
DPRINTF(("DMA: a normal and expected shutdown occurred\n"));
if (nd->nd_shutdown_cb) (*nd->nd_shutdown_cb)(nd->nd_cb_arg);
return(1);
}
#if 0
#ifdef DIAGNOSTIC
if (!(state & DMACSR_SUPDATE)) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("SUPDATE not set with continuing DMA");
}
#endif
#endif
/* Check that the buffer we are interrupted for is the one we expect.
* Shorten the buffer if the dma completed with a short buffer
*/
{
bus_addr_t next;
bus_addr_t limit;
bus_addr_t expected_next;
bus_addr_t expected_limit;
expected_next = nd->_nd_map->dm_segs[nd->_nd_idx].ds_addr;
expected_limit = expected_next + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
#if 0 /* for some unknown reason, somtimes DD_SAVED_NEXT has value from
* nd->_nd_map and sometimes it has value from nd->_nd_map_cont.
* Somtimes, it has a completely different unknown value.
* Until that's understood, we won't sanity check the expected_next value.
*/
next = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_NEXT);
#else
next = expected_next;
#endif
limit = bus_space_read_4(nd->nd_bst, nd->nd_bsh, DD_SAVED_LIMIT);
if (nd->nd_intr == NEXT_I_ENETX_DMA) {
limit &= ~0x80000000;
}
if ((limit-next < 0) ||
(limit-next >= expected_limit-expected_next)) {
#ifdef DIAGNOSTIC
#if 0 /* Sometimes, (under load I think) even DD_SAVED_LIMIT has
* a bogus value. Until that's understood, we don't panic
* here.
*/
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("Unexpected saved registers values.");
#endif
#endif
} else {
/* Set the length of the segment to match actual length.
* @@@ is it okay to resize dma segments here?
* i should probably ask jason about this.
*/
nd->_nd_map->dm_segs[nd->_nd_idx].ds_len = limit-next;
expected_limit = expected_next + nd->_nd_map->dm_segs[nd->_nd_idx].ds_len;
}
#if 0 /* these checks are turned off until the above mentioned weirdness is fixed. */
#ifdef DIAGNOSTIC
if (next != expected_next) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("unexpected DMA next buffer in interrupt (found 0x%08x, expected 0x%08x)",
next,expected_next);
}
if (limit != expected_limit) {
next_dma_print(nd);
printf("DEBUG: state = 0x%b\n", state,DMACSR_BITS);
panic("unexpected DMA limit buffer in interrupt (found 0x%08x, expected 0x%08x)",
limit,expected_limit);
}
#endif
#endif
}
next_dma_rotate(nd);
next_dma_setup_cont_regs(nd);
if (!(state & DMACSR_ENABLE)) {
DPRINTF(("Unexpected DMA shutdownn, restarting."));
if (nd->_nd_map_cont) {
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_SETSUPDATE | DMACSR_SETENABLE);
} else {
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_CLRCOMPLETE | DMACSR_RESET);
DPRINTF(("DMA: enable not set w/o continue map, shutting down dma\n"));
if (nd->nd_shutdown_cb) (*nd->nd_shutdown_cb)(nd->nd_cb_arg);
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_SETENABLE);
}
} else {
next_dma_rotate(nd);
next_dma_setup_cont_regs(nd);
if (nd->_nd_map_cont) {
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
@ -567,7 +653,6 @@ nextdma_intr(arg)
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_CLRCOMPLETE);
}
}
}
@ -620,48 +705,33 @@ nextdma_start(nd, dmadir)
}
#endif
/* preload both the current and the continue maps */
next_dma_rotate(nd);
#ifdef DIAGNOSTIC
if (!nd->_nd_map_cont) {
panic("No map available in nextdma_start()");
}
if (!DMA_BEGINALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_addr)) {
panic("unaligned begin dma at start\n");
}
if (!DMA_ENDALIGNED(nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_addr +
nd->_nd_map_cont->dm_segs[nd->_nd_idx].ds_len)) {
panic("unaligned end dma at start\n");
}
#endif
next_dma_rotate(nd);
DPRINTF(("DMA initiating DMA %s of %d segments on intr(0x%b)\n",
(dmadir == DMACSR_READ ? "read" : "write"), nd->_nd_map_cont->dm_nsegs,
(dmadir == DMACSR_READ ? "read" : "write"), nd->_nd_map->dm_nsegs,
NEXT_I_BIT(nd->nd_intr),NEXT_INTR_BITS));
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR, 0);
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_INITBUF | DMACSR_RESET | dmadir);
next_dma_setup_cont_regs(nd);
/* When starting DMA, we must put the continue map
* into the current register. We reset the nd->_nd_map
* pointer here to avoid duplicated completed callbacks
* for the first buffer.
*/
nd->_nd_map = nd->_nd_map_cont;
nd->_nd_idx = nd->_nd_idx_cont;
next_dma_setup_curr_regs(nd);
nd->_nd_map = 0;
nd->_nd_idx = 0;
next_dma_setup_cont_regs(nd);
#if (defined(ND_DEBUG))
next_dma_print(nd);
#endif
if (nd->nd_chaining_flag) {
if (nd->_nd_map_cont) {
bus_space_write_4(nd->nd_bst, nd->nd_bsh, DD_CSR,
DMACSR_SETSUPDATE | DMACSR_SETENABLE);
} else {

View File

@ -1,4 +1,4 @@
/* $NetBSD: nextdmavar.h,v 1.2 1998/07/05 07:53:45 dbj Exp $ */
/* $NetBSD: nextdmavar.h,v 1.3 1998/12/19 09:31:44 dbj Exp $ */
/*
* Copyright (c) 1998 Darrin B. Jewell
* All rights reserved.
@ -45,8 +45,6 @@ struct nextdma_config {
/* This is called when dma shuts down */
void (*nd_shutdown_cb) __P((void *));
int nd_chaining_flag; /* true if this interface chains */
void *nd_cb_arg; /* callback argument */
struct generic_bus_dma_tag _nd_dmat; /* should probably be elsewhere */