diff options
Diffstat (limited to 'src/devices/machine/hd63450.cpp')
-rw-r--r-- | src/devices/machine/hd63450.cpp | 93 |
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) |