static int dmac_error(void *arg) { struct dmac_channel_stat *chan = arg; struct dmac_softc *sc = chan->ch_softc; uint8_t csr, cer; csr = bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR); cer = bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CER); #ifndef DMAC_DEBUG /* Software abort (CER=0x11) could happen on normal xfer termination */ if (cer != 0x11) #endif { printf("DMAC transfer error CSR=%02x, CER=%02x\n", csr, cer); } DDUMPREGS(3, ("registers were:\n")); /* Clear the status bits */ bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); #ifdef DMAC_ARRAYCHAIN chan->ch_xfer.dx_done = 0; #endif return (*chan->ch_error)(chan->ch_errorarg); }
/* * interrupt handlers. */ static int dmac_done(void *arg) { struct dmac_channel_stat *chan = arg; struct dmac_softc *sc = chan->ch_softc; #ifdef DMAC_ARRAYCHAIN struct dmac_dma_xfer *xf = &chan->ch_xfer; struct x68k_bus_dmamap *map = xf->dx_dmamap; int c; #endif DPRINTF(3, ("dmac_done\n")); bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); #ifdef DMAC_ARRAYCHAIN if (xf->dx_done == map->dm_nsegs) { xf->dx_done = 0; #endif /* Done */ return (*chan->ch_normal)(chan->ch_normalarg); #ifdef DMAC_ARRAYCHAIN } #endif #ifdef DMAC_ARRAYCHAIN /* Continue transfer */ DPRINTF(3, ("reprograming\n")); c = dmac_program_arraychain(sc->sc_dev, xf, 0, map->dm_mapsize); bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); bus_space_write_4(sc->sc_bst, chan->ch_bht, DMAC_REG_BAR, (int) chan->ch_map); bus_space_write_4(sc->sc_bst, chan->ch_bht, DMAC_REG_DAR, (int) xf->dx_device); bus_space_write_2(sc->sc_bst, chan->ch_bht, DMAC_REG_BTCR, c); /* START!! */ DDUMPREGS(3, ("restart\n")); bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CCR, DMAC_CCR_STR|DMAC_CCR_INT); return 1; #endif }
static int dmac_error(void *arg) { struct dmac_channel_stat *chan = arg; struct dmac_softc *sc = chan->ch_softc; printf("DMAC transfer error CSR=%02x, CER=%02x\n", bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR), bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CER)); DDUMPREGS(3, ("registers were:\n")); /* Clear the status bits */ bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); #ifdef DMAC_ARRAYCHAIN chan->ch_xfer.dx_done = 0; #endif return (*chan->ch_error)(chan->ch_errorarg); }
int dmac_start_xfer_offset(struct dmac_softc *dmac, struct dmac_dma_xfer *xf, u_int offset, u_int size) { struct dmac_channel_stat *chan = xf->dx_channel; struct x68k_bus_dmamap *dmamap = xf->dx_dmamap; int go = DMAC_CCR_STR|DMAC_CCR_INT; #ifdef DMAC_ARRAYCHAIN int c; #endif DPRINTF(3, ("dmac_start_xfer\n")); #ifdef DMAC_DEBUG debugchan=chan; #endif if (size == 0) { #ifdef DIAGNOSTIC if (offset != 0) panic("dmac_start_xfer_offset: invalid offset %x", offset); #endif size = dmamap->dm_mapsize; } #ifdef DMAC_ARRAYCHAIN #ifdef DIAGNOSTIC if (xf->dx_done) panic("dmac_start_xfer: DMA transfer in progress"); #endif #endif DPRINTF(3, ("First program:\n")); #ifdef DIAGNOSTIC if ((offset >= dmamap->dm_mapsize) || (offset + size > dmamap->dm_mapsize)) panic("dmac_start_xfer_offset: invalid offset: " "offset=%d, size=%d, mapsize=%ld", offset, size, dmamap->dm_mapsize); #endif /* program DMAC in single block mode or array chainning mode */ if (dmamap->dm_nsegs == 1) { DPRINTF(3, ("single block mode\n")); #ifdef DIAGNOSTIC if (dmamap->dm_mapsize != dmamap->dm_segs[0].ds_len) panic("dmac_start_xfer_offset: dmamap curruption"); #endif if (offset == xf->dx_nextoff && size == xf->dx_nextsize) { /* Use continued operation */ go |= DMAC_CCR_CNT; xf->dx_nextoff += size; } else { bus_space_write_4(dmac->sc_bst, chan->ch_bht, DMAC_REG_MAR, (int) dmamap->dm_segs[0].ds_addr + offset); bus_space_write_2(dmac->sc_bst, chan->ch_bht, DMAC_REG_MTCR, (int) size); xf->dx_nextoff = offset; xf->dx_nextsize = size; } #ifdef DMAC_ARRAYCHAIN xf->dx_done = 1; #endif } else { #ifdef DMAC_ARRAYCHAIN c = dmac_program_arraychain(self, xf, offset, size); bus_space_write_4(dmac->sc_bst, chan->ch_bht, DMAC_REG_BAR, (int) chan->ch_seg[0].ds_addr); bus_space_write_2(dmac->sc_bst, chan->ch_bht, DMAC_REG_BTCR, c); #else panic("DMAC: unexpected use of arraychaining mode"); #endif } bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); /* START!! */ DDUMPREGS(3, ("first start\n")); #ifdef DMAC_ARRAYCHAIN #if defined(M68040) || defined(M68060) /* flush data cache for the map */ if (dmamap->dm_nsegs != 1 && mmutype == MMU_68040) dma_cachectl((void *) xf->dx_array, sizeof(struct dmac_sg_array) * c); #endif #endif bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CCR, go); if (xf->dx_nextoff != ~0) { bus_space_write_4(dmac->sc_bst, chan->ch_bht, DMAC_REG_BAR, xf->dx_nextoff); bus_space_write_2(dmac->sc_bst, chan->ch_bht, DMAC_REG_BTCR, xf->dx_nextsize); } return 0; }