From e873cabccd956a8738db1ee6d04dc32c1614c9e3 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sat, 27 Sep 2008 15:41:16 +0000 Subject: Expand the DBDMA API to allow setting device-dependent control bits. While here, clean up and document this a little. Submitted by: Marco Trillo MFC after: 1 week --- sys/powerpc/include/dbdma.h | 40 ++++++++++++++++++++++++++++++++++++---- sys/powerpc/powermac/dbdma.c | 22 ++++++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/powerpc/include/dbdma.h b/sys/powerpc/include/dbdma.h index becfbc8..2095ad3 100644 --- a/sys/powerpc/include/dbdma.h +++ b/sys/powerpc/include/dbdma.h @@ -84,9 +84,6 @@ int dbdma_allocate_channel(struct resource *dbdma_regs, u_int offset, int dbdma_resize_channel(dbdma_channel_t *chan, int newslots); int dbdma_free_channel(dbdma_channel_t *chan); -uint16_t dbdma_get_cmd_status(dbdma_channel_t *chan, int slot); -uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot); - void dbdma_run(dbdma_channel_t *chan); void dbdma_stop(dbdma_channel_t *chan); void dbdma_reset(dbdma_channel_t *chan); @@ -95,8 +92,43 @@ void dbdma_set_current_cmd(dbdma_channel_t *chan, int slot); void dbdma_pause(dbdma_channel_t *chan); void dbdma_wake(dbdma_channel_t *chan); +/* + * DBDMA uses a 16 bit channel control register to describe the current + * state of DMA on the channel. The high-order bits (8-15) contain information + * on the run state and are listed in the DBDMA_STATUS_* constants above. These + * are manipulated with the dbdma_run/stop/reset() routines above. + * + * The low order bits (0-7) are device dependent status bits. These can be set + * and read by both hardware and software. The mask is the set of bits to + * modify; if mask is 0x03 and value is 0, the lowest order 2 bits will be + * zeroed. + */ + uint16_t dbdma_get_chan_status(dbdma_channel_t *chan); -uint8_t dbdma_get_chan_device_status(dbdma_channel_t *chan); + +uint8_t dbdma_get_device_status(dbdma_channel_t *chan); +void dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask, + uint8_t value); + +/* + * Each DBDMA command word has the current channel status register and the + * number of residual bytes (requested - actually transferred) written to it + * at time of command completion. + */ + +uint16_t dbdma_get_cmd_status(dbdma_channel_t *chan, int slot); +uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot); + +void dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot); + +/* + * The interrupt/branch/wait selector let you specify a set of values + * of the device dependent status bits that will cause intterupt/branch/wait + * conditions to be taken if the flags for these are set to one of the + * DBDMA_COND_* values. + * + * The condition is considered true if (status & mask) == value. + */ void dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t value); diff --git a/sys/powerpc/powermac/dbdma.c b/sys/powerpc/powermac/dbdma.c index edae6e2..ebc0122 100644 --- a/sys/powerpc/powermac/dbdma.c +++ b/sys/powerpc/powermac/dbdma.c @@ -127,6 +127,13 @@ dbdma_get_cmd_status(dbdma_channel_t *chan, int slot) return (le16toh(chan->sc_slots[slot].resCount)); } +void +dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot) +{ + /* See endian note above */ + chan->sc_slots[slot].resCount = 0; +} + uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot) { @@ -212,13 +219,24 @@ dbdma_get_chan_status(dbdma_channel_t *chan) } uint8_t -dbdma_get_chan_device_status(dbdma_channel_t *chan) +dbdma_get_device_status(dbdma_channel_t *chan) { - return (dbdma_get_chan_status(chan) & 0x00ff); } void +dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask, uint8_t value) +{ + uint32_t control_reg; + + control_reg = mask; + control_reg <<= 16; + control_reg |= value; + + dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg); +} + +void dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t val) { uint32_t intr_select; -- cgit v1.1