summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/hd63450.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/hd63450.cpp')
-rw-r--r--src/devices/machine/hd63450.cpp39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/devices/machine/hd63450.cpp b/src/devices/machine/hd63450.cpp
index 86d8a9e101c..21b032f55f6 100644
--- a/src/devices/machine/hd63450.cpp
+++ b/src/devices/machine/hd63450.cpp
@@ -62,6 +62,7 @@ void hd63450_device::device_start()
save_item(STRUCT_MEMBER(m_reg, mar));
save_item(STRUCT_MEMBER(m_reg, dar));
save_item(STRUCT_MEMBER(m_reg, btc));
+ save_item(STRUCT_MEMBER(m_reg, bar));
save_item(STRUCT_MEMBER(m_reg, niv));
save_item(STRUCT_MEMBER(m_reg, eiv));
save_item(STRUCT_MEMBER(m_reg, mfc));
@@ -278,7 +279,7 @@ void hd63450_device::dma_transfer_start(int channel)
m_reg[channel].csr &= ~0xe0;
m_reg[channel].csr |= 0x08; // Channel active
m_reg[channel].csr &= ~0x30; // Reset Error and Normal termination bits
- if ((m_reg[channel].ocr & 0x0c) != 0x00) // Array chain or Link array chain
+ if ((m_reg[channel].ocr & 0x0c) == 0x08) // Array chain
{
m_reg[channel].mar = space.read_word(m_reg[channel].bar) << 16;
m_reg[channel].mar |= space.read_word(m_reg[channel].bar+2);
@@ -286,9 +287,19 @@ void hd63450_device::dma_transfer_start(int channel)
if (m_reg[channel].btc > 0)
m_reg[channel].btc--;
}
+ else if ((m_reg[channel].ocr & 0x0c) == 0x0c) // Link array chain
+ {
+ u32 bar = m_reg[channel].bar;
+ m_reg[channel].mar = space.read_word(bar) << 16;
+ m_reg[channel].mar |= space.read_word(bar+2);
+ m_reg[channel].mtc = space.read_word(bar+4);
+ m_reg[channel].bar = space.read_word(bar+6) << 16;
+ m_reg[channel].bar |= space.read_word(bar+8);
+ }
// Burst transfers will halt the CPU until the transfer is complete
- if ((m_reg[channel].dcr & 0xc0) == 0x00) // Burst transfer
+ // max rate transfer hold the bus
+ if (((m_reg[channel].dcr & 0xc0) == 0x00) || ((m_reg[channel].ocr & 3) == 1)) // Burst transfer
{
m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
m_timer[channel]->adjust(attotime::zero, channel, m_burst_clock[channel]);
@@ -452,7 +463,7 @@ void hd63450_device::single_transfer(int x)
{
// End of transfer
LOG("DMA#%i: End of transfer\n",x);
- if ((m_reg[x].ocr & 0x0c) != 0 && m_reg[x].btc > 0)
+ if ((m_reg[x].ocr & 0x0c) == 0x08 && m_reg[x].btc > 0)
{
m_reg[x].btc--;
m_reg[x].bar+=6;
@@ -461,13 +472,31 @@ void hd63450_device::single_transfer(int x)
m_reg[x].mtc = space.read_word(m_reg[x].bar+4);
return;
}
+ else if ((m_reg[x].ocr & 0x0c) == 0x0c && m_reg[x].bar)
+ {
+ u32 bar = m_reg[x].bar;
+ m_reg[x].mar = space.read_word(bar) << 16;
+ m_reg[x].mar |= space.read_word(bar+2);
+ m_reg[x].mtc = space.read_word(bar+4);
+ m_reg[x].bar = space.read_word(bar+6) << 16;
+ m_reg[x].bar |= space.read_word(bar+8);
+ return;
+ }
+ else if (m_reg[x].ccr & 0x40)
+ {
+ m_reg[x].mar = m_reg[x].bar;
+ m_reg[x].mtc = m_reg[x].btc;
+ m_reg[x].csr |= 0x40;
+ set_irq(x);
+ return;
+ }
m_timer[x]->adjust(attotime::never);
m_reg[x].csr |= 0xe0; // channel operation complete, block transfer complete
m_reg[x].csr &= ~0x08; // channel no longer active
m_reg[x].ccr &= ~0xc0;
- // Burst transfer
- if ((m_reg[x].dcr & 0xc0) == 0x00)
+ // Burst transfer or max rate transfer
+ if (((m_reg[x].dcr & 0xc0) == 0x00) || ((m_reg[x].ocr & 3) == 1))
{
m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}