diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2008-09-27 15:41:16 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2008-09-27 15:41:16 +0000 |
commit | e873cabccd956a8738db1ee6d04dc32c1614c9e3 (patch) | |
tree | 0c72c5408fd08c24fca5f4bd5fbe09226eaa9862 /sys/powerpc | |
parent | 3177393070971da5219f5f2ef9b2e19b00821465 (diff) | |
download | FreeBSD-src-e873cabccd956a8738db1ee6d04dc32c1614c9e3.zip FreeBSD-src-e873cabccd956a8738db1ee6d04dc32c1614c9e3.tar.gz |
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
Diffstat (limited to 'sys/powerpc')
-rw-r--r-- | sys/powerpc/include/dbdma.h | 40 | ||||
-rw-r--r-- | sys/powerpc/powermac/dbdma.c | 22 |
2 files changed, 56 insertions, 6 deletions
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; |