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:
parent
12632ebf71
commit
db8bf6a623
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user