Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
/*
 * 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
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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;
}