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.cpp93
1 files changed, 48 insertions, 45 deletions
diff --git a/src/devices/machine/hd63450.cpp b/src/devices/machine/hd63450.cpp
index d726a0c64a7..36cced7ef53 100644
--- a/src/devices/machine/hd63450.cpp
+++ b/src/devices/machine/hd63450.cpp
@@ -18,6 +18,7 @@ hd63450_device::hd63450_device(const machine_config &mconfig, const char *tag, d
: device_t(mconfig, HD63450, tag, owner, clock)
, m_irq_callback(*this)
, m_dma_end(*this)
+ , m_own(*this)
, m_dma_read(*this, 0)
, m_dma_write(*this)
, m_cpu(*this, finder_base::DUMMY_TAG)
@@ -195,7 +196,7 @@ void hd63450_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
dma_transfer_abort(channel);
if (data & 0x0020) // halt operation
dma_transfer_halt(channel);
- if (data & 0x0040) // continure operation
+ if (data & 0x0040) // continue operation
dma_transfer_continue(channel);
if ((data & 0x0008) == 0)
clear_irq(channel);
@@ -360,6 +361,9 @@ void hd63450_device::single_transfer(int x)
return;
m_bec = 0;
+ m_dtack = true;
+
+ m_own(0);
if (m_reg[x].ocr & 0x80) // direction: 1 = device -> memory
{
@@ -440,6 +444,11 @@ void hd63450_device::single_transfer(int x)
// LOG("DMA#%i: byte transfer %08lx -> %08lx\n",x,m_reg[x].mar,m_reg[x].dar);
}
+ m_own(1);
+
+ if (!m_dtack)
+ return;
+
if (m_bec == ERR_BUS)
{
set_error(x, 9); //assume error in mar, TODO: other errors
@@ -520,61 +529,55 @@ void hd63450_device::set_error(int channel, uint8_t code)
set_irq(channel);
}
-void hd63450_device::drq0_w(int state)
+void hd63450_device::drq_w(int channel, int state)
{
- bool ostate = m_drq_state[0];
- m_drq_state[0] = state;
+ bool ostate = m_drq_state[channel];
+ m_drq_state[channel] = state;
- if ((m_reg[0].ocr & 2) && (state && !ostate))
+ // check for external request modes
+ if (m_reg[channel].ocr & 2)
{
- // in cycle steal mode drq is supposed to be edge triggered
- single_transfer(0);
- m_timer[0]->adjust(m_our_clock[0], 0, m_our_clock[0]);
+ if (state && !ostate)
+ {
+ // in cycle steal mode DRQ is supposed to be edge triggered
+ single_transfer(channel);
+ m_timer[channel]->adjust(m_our_clock[channel], channel, m_our_clock[channel]);
+ }
+ else if (!state)
+ m_timer[channel]->adjust(attotime::never);
}
- else if (!state)
- m_timer[0]->adjust(attotime::never);
}
-void hd63450_device::drq1_w(int state)
+void hd63450_device::pcl_w(int channel, int state)
{
- bool ostate = m_drq_state[1];
- m_drq_state[1] = state;
+ bool ostate = (m_reg[channel].csr & 1);
- if ((m_reg[1].ocr & 2) && (state && !ostate))
- {
- single_transfer(1);
- m_timer[1]->adjust(m_our_clock[1], 1, m_our_clock[1]);
- }
- else if (!state)
- m_timer[1]->adjust(attotime::never);
-}
+ // status can be determined by PCS in CSR regardless of PCL in DCR
+ if (state)
+ m_reg[channel].csr |= 0x01; // PCS
+ else
+ m_reg[channel].csr &= ~0x01;
-void hd63450_device::drq2_w(int state)
-{
- bool ostate = m_drq_state[2];
- m_drq_state[2] = state;
-
- if ((m_reg[2].ocr & 2) && (state && !ostate))
+ switch (m_reg[channel].dcr & 7)
{
- single_transfer(2);
- m_timer[2]->adjust(m_our_clock[2], 2, m_our_clock[2]);
- }
- else if (!state)
- m_timer[2]->adjust(attotime::never);
-}
-
-void hd63450_device::drq3_w(int state)
-{
- bool ostate = m_drq_state[3];
- m_drq_state[3] = state;
-
- if ((m_reg[3].ocr & 2) && (state && !ostate))
- {
- single_transfer(3);
- m_timer[3]->adjust(m_our_clock[3], 3, m_our_clock[3]);
+ case 0: // status
+ if (!state && ostate)
+ m_reg[channel].csr |= 0x02; // PCT
+ break;
+ case 1: // status with interrupt
+ if (!state && ostate)
+ {
+ m_reg[channel].csr |= 0x02; // PCT
+ set_irq(channel);
+ }
+ break;
+ case 2: // 1/8 start pulse
+ LOG("DMA#%i: PCL write : %d 1/8 starting pulse not implemented\n", channel, state);
+ break;
+ case 3: // abort
+ LOG("DMA#%i: PCL write : %d abort not implemented\n", channel, state);
+ break;
}
- else if (!state)
- m_timer[3]->adjust(attotime::never);
}
void hd63450_device::set_irq(int channel)