Esempio n. 1
0
static void
ata_dbdma_setprd(void *xarg, bus_dma_segment_t *segs, int nsegs, int error)
{
	struct ata_dbdma_dmaload_args *arg = xarg;
	struct ata_dbdma_channel *sc = arg->sc;
	int branch_type, command;
	int prev_stop;
	int i;

	mtx_lock(&sc->dbdma_mtx);

	prev_stop = sc->next_dma_slot-1;
	if (prev_stop < 0)
		prev_stop = 0xff;

	for (i = 0; i < nsegs; i++) {
		/* Loop back to the beginning if this is our last slot */
		if (sc->next_dma_slot == 0xff)
			branch_type = DBDMA_ALWAYS;
		else
			branch_type = DBDMA_NEVER;

		if (arg->write) {
			command = (i + 1 < nsegs) ? DBDMA_OUTPUT_MORE : 
			    DBDMA_OUTPUT_LAST;
		} else {
			command = (i + 1 < nsegs) ? DBDMA_INPUT_MORE : 
			    DBDMA_INPUT_LAST;
		}

		dbdma_insert_command(sc->dbdma, sc->next_dma_slot++,
		    command, 0, segs[i].ds_addr, segs[i].ds_len,
		    DBDMA_NEVER, branch_type, DBDMA_NEVER, 0);

		if (branch_type == DBDMA_ALWAYS)
			sc->next_dma_slot = 0;
	}

	/* We have a corner case where the STOP command is the last slot,
	 * but you can't branch in STOP commands. So add a NOP branch here
	 * and the STOP in slot 0. */

	if (sc->next_dma_slot == 0xff) {
		dbdma_insert_branch(sc->dbdma, sc->next_dma_slot, 0);
		sc->next_dma_slot = 0;
	}

#if 0
	dbdma_insert_command(sc->dbdma, sc->next_dma_slot++,
	    DBDMA_NOP, 0, 0, 0, DBDMA_ALWAYS, DBDMA_NEVER, DBDMA_NEVER, 0);
#endif
	dbdma_insert_stop(sc->dbdma, sc->next_dma_slot++);
	dbdma_insert_nop(sc->dbdma, prev_stop);

	dbdma_sync_commands(sc->dbdma, BUS_DMASYNC_PREWRITE);

	mtx_unlock(&sc->dbdma_mtx);

	arg->nsegs = nsegs;
}
Esempio n. 2
0
void
dbdma_insert_branch(dbdma_channel_t *chan, int slot, int to_slot)
{

    dbdma_insert_command(chan, slot, DBDMA_NOP, 0, 0, 0, DBDMA_NEVER,
                         DBDMA_ALWAYS, DBDMA_NEVER, to_slot);
}
Esempio n. 3
0
void
dbdma_insert_nop(dbdma_channel_t *chan, int slot)
{

    dbdma_insert_command(chan, slot, DBDMA_NOP, 0, 0, 0, DBDMA_NEVER,
                         DBDMA_NEVER, DBDMA_NEVER, 0);
}