summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sharc/sharcdma.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sharc/sharcdma.hxx')
-rw-r--r--src/devices/cpu/sharc/sharcdma.hxx136
1 files changed, 116 insertions, 20 deletions
diff --git a/src/devices/cpu/sharc/sharcdma.hxx b/src/devices/cpu/sharc/sharcdma.hxx
index fdbf7a0f635..c068ba5fbb3 100644
--- a/src/devices/cpu/sharc/sharcdma.hxx
+++ b/src/devices/cpu/sharc/sharcdma.hxx
@@ -10,7 +10,7 @@
void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_ptr, int chained_direction)
{
- uint32_t op_ptr = 0x20000 + dma_chain_ptr;
+ uint32_t op_ptr = 0x20000 + (dma_chain_ptr & 0x1ffff);
uint32_t int_index = dm_read32(op_ptr - 0);
uint32_t int_modifier = dm_read32(op_ptr - 1);
@@ -49,10 +49,14 @@ void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_p
m_core->dma_op[channel].chain_ptr = chain_ptr;
m_core->dma_op[channel].chained_direction = chained_direction;
+ m_core->dma_op[channel].chained = true;
m_core->dma_op[channel].active = true;
- int cycles = m_core->dma_op[channel].src_count / 4;
- m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
+ if (m_enable_drc)
+ {
+ int cycles = m_core->dma_op[channel].src_count / 4;
+ m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
+ }
// enable busy flag
m_core->dma_status |= (1 << channel);
@@ -74,15 +78,107 @@ void adsp21062_device::schedule_dma_op(int channel, uint32_t src, uint32_t dst,
m_core->dma_op[channel].pmode = pmode;
m_core->dma_op[channel].chain_ptr = 0;
+ m_core->dma_op[channel].chained = false;
m_core->dma_op[channel].active = true;
- int cycles = src_count / 4;
- m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
+ if (m_enable_drc)
+ {
+ int cycles = src_count / 4;
+ m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
+ }
// enable busy flag
m_core->dma_status |= (1 << channel);
}
+void adsp21062_device::dma_run_cycle(int channel)
+{
+ if (m_core->dma_status & (1 << channel))
+ {
+ uint32_t src = m_core->dma_op[channel].src;
+ uint32_t dst = m_core->dma_op[channel].dst;
+ int src_modifier = m_core->dma_op[channel].src_modifier;
+ int dst_modifier = m_core->dma_op[channel].dst_modifier;
+ int src_count = m_core->dma_op[channel].src_count;
+ //int dst_count = m_core->dma_op[channel].dst_count;
+ int pmode = m_core->dma_op[channel].pmode;
+
+ switch (pmode)
+ {
+ case DMA_PMODE_NO_PACKING:
+ {
+ uint32_t data = dm_read32(src);
+ dm_write32(dst, data);
+ src += src_modifier;
+ dst += dst_modifier;
+ src_count--;
+ break;
+ }
+ case DMA_PMODE_16_32:
+ {
+ uint32_t data = ((dm_read32(src + 0) & 0xffff) << 16) | (dm_read32(src + 1) & 0xffff);
+
+ dm_write32(dst, data);
+ src += src_modifier * 2;
+ dst += dst_modifier;
+ src_count -= 2;
+ break;
+ }
+ case DMA_PMODE_8_48:
+ {
+ uint64_t data = ((uint64_t)(dm_read32(src + 0) & 0xff) << 0) |
+ ((uint64_t)(dm_read32(src + 1) & 0xff) << 8) |
+ ((uint64_t)(dm_read32(src + 2) & 0xff) << 16) |
+ ((uint64_t)(dm_read32(src + 3) & 0xff) << 24) |
+ ((uint64_t)(dm_read32(src + 4) & 0xff) << 32) |
+ ((uint64_t)(dm_read32(src + 5) & 0xff) << 40);
+
+ pm_write48(dst, data);
+ src += src_modifier * 6;
+ dst += dst_modifier;
+ src_count -= 6;
+ break;
+ }
+ default:
+ {
+ fatalerror("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
+ }
+ }
+
+ m_core->dma_op[channel].src_count = src_count;
+ m_core->dma_op[channel].src = src;
+ m_core->dma_op[channel].dst = dst;
+
+ if (src_count <= 0)
+ {
+ // clear busy flag
+ m_core->dma_status &= ~(1 << channel);
+
+ m_core->dma_op[channel].active = false;
+
+ // raise interrupt if
+ // * non-chained DMA
+ // * chained-DMA with PCI set in the next chain pointer
+ if (!m_core->dma_op[channel].chained || (m_core->dma_op[channel].chained && (m_core->dma_op[channel].chain_ptr & 0x20000)))
+ {
+ m_core->irptl |= (1 << (channel + 10));
+
+ // DMA interrupt
+ if (m_core->imask & (1 << (channel + 10)))
+ {
+ m_core->irq_pending |= 1 << (channel + 10);
+ }
+ }
+
+ // schedule chained op if chaining
+ if ((m_core->dma_op[channel].chain_ptr & 0x1ffff) != 0)
+ {
+ schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
+ }
+ }
+ }
+}
+
void adsp21062_device::dma_op(int channel)
{
int i;
@@ -94,7 +190,7 @@ void adsp21062_device::dma_op(int channel)
//int dst_count = m_core->dma_op[channel].dst_count;
int pmode = m_core->dma_op[channel].pmode;
- //printf("dma_op: %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, pmode);
+ //printf("dma_op: ch %d: %08X, %08X, %08X, %08X, %08X, %d at %08X\n", channel, src, dst, src_modifier, dst_modifier, src_count, pmode, m_core->pc);
switch (pmode)
{
@@ -197,25 +293,25 @@ void adsp21062_device::sharc_dma_exec(int channel)
{
if (tran) // Transmit to external
{
- dst = m_core->dma[channel].ext_index;
- dst_modifier = m_core->dma[channel].ext_modifier;
- dst_count = m_core->dma[channel].ext_count;
- src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
- src_modifier = m_core->dma[channel].int_modifier;
- src_count = m_core->dma[channel].int_count;
+ dst = m_core->dma[channel].ext_index;
+ dst_modifier = m_core->dma[channel].ext_modifier;
+ dst_count = m_core->dma[channel].ext_count;
+ src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
+ src_modifier = m_core->dma[channel].int_modifier;
+ src_count = m_core->dma[channel].int_count;
}
else // Receive from external
{
- src = m_core->dma[channel].ext_index;
- src_modifier = m_core->dma[channel].ext_modifier;
- src_count = m_core->dma[channel].ext_count;
- dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
- dst_modifier = m_core->dma[channel].int_modifier;
- dst_count = m_core->dma[channel].int_count;
+ src = m_core->dma[channel].ext_index;
+ src_modifier = m_core->dma[channel].ext_modifier;
+ src_count = m_core->dma[channel].ext_count;
+ dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
+ dst_modifier = m_core->dma[channel].int_modifier;
+ dst_count = m_core->dma[channel].int_count;
}
if (dtype)
- //if (src_count != dst_count)
+ //if (src_count != dst_count)
{
pmode = DMA_PMODE_8_48;
}
@@ -239,7 +335,7 @@ TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_dma_callback)
}
dma_op(channel);
- if (m_core->dma_op[channel].chain_ptr != 0)
+ if ((m_core->dma_op[channel].chain_ptr & 0x1ffff) != 0)
{
schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
}