summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2008-09-27 15:41:16 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2008-09-27 15:41:16 +0000
commite873cabccd956a8738db1ee6d04dc32c1614c9e3 (patch)
tree0c72c5408fd08c24fca5f4bd5fbe09226eaa9862 /sys/powerpc
parent3177393070971da5219f5f2ef9b2e19b00821465 (diff)
downloadFreeBSD-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.h40
-rw-r--r--sys/powerpc/powermac/dbdma.c22
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;
OpenPOWER on IntegriCloud