hd63450: add primitive /own and /dtack support

* also improve auto-request mode logic
This commit is contained in:
Patrick Mackinlay 2025-04-02 13:19:27 +07:00
parent 3c729314b8
commit ee6cb33f46
2 changed files with 24 additions and 6 deletions

View File

@ -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)
@ -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
@ -525,14 +534,18 @@ void hd63450_device::drq_w(int channel, int state)
bool ostate = m_drq_state[channel];
m_drq_state[channel] = state;
if ((m_reg[channel].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(channel);
m_timer[channel]->adjust(m_our_clock[channel], channel, m_our_clock[channel]);
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[channel]->adjust(attotime::never);
}
void hd63450_device::pcl_w(int channel, int state)

View File

@ -22,6 +22,7 @@ public:
auto irq_callback() { return m_irq_callback.bind(); }
auto dma_end() { return m_dma_end.bind(); }
auto own() { return m_own.bind(); }
template <int Ch> auto dma_read() { return m_dma_read[Ch].bind(); }
template <int Ch> auto dma_write() { return m_dma_write[Ch].bind(); }
@ -62,6 +63,7 @@ public:
ERR_NONE= 7
};
void bec_w(offs_t offset, uint8_t data) { m_bec = data; }
void dtack_w(int state) { m_dtack = !state; }
void single_transfer(int x);
void set_timer(int channel, const attotime &tm);
@ -96,6 +98,7 @@ private:
devcb_write_line m_irq_callback;
devcb_write8 m_dma_end;
devcb_write_line m_own;
devcb_read8::array<4> m_dma_read;
devcb_write8::array<4> m_dma_write;
@ -113,6 +116,8 @@ private:
int8_t m_irq_channel;
uint8_t m_bec;
bool m_dtack;
// tell if a channel is in use
bool dma_in_progress(int channel) const { return (m_reg[channel].csr & 0x08) != 0; }