diff options
-rw-r--r-- | src/mame/machine/dmac_0266.cpp | 54 | ||||
-rw-r--r-- | src/mame/machine/dmac_0266.h | 20 |
2 files changed, 34 insertions, 40 deletions
diff --git a/src/mame/machine/dmac_0266.cpp b/src/mame/machine/dmac_0266.cpp index 97a7c1bb7e5..0e65a33af87 100644 --- a/src/mame/machine/dmac_0266.cpp +++ b/src/mame/machine/dmac_0266.cpp @@ -12,9 +12,7 @@ * - https://github.com/NetBSD/src/blob/trunk/sys/arch/news68k/dev/si.c * * TODO: - * - tczero vs interrupt status - * - verify if eop output exists - * - verify map count/width + * - find the real solution to the short transfer issue */ #include "emu.h" @@ -31,7 +29,6 @@ DEFINE_DEVICE_TYPE(DMAC_0266, dmac_0266_device, "dmac_0266", "Sony 0266 DMA Cont dmac_0266_device::dmac_0266_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, DMAC_0266, tag, owner, clock) , m_bus(*this, finder_base::DUMMY_TAG, -1, 32) - , m_int(*this) , m_dma_r(*this) , m_dma_w(*this) { @@ -49,8 +46,6 @@ void dmac_0266_device::map(address_map &map) void dmac_0266_device::device_start() { - m_int.resolve_safe(); - m_dma_r.resolve_safe(0); m_dma_w.resolve_safe(); @@ -61,13 +56,11 @@ void dmac_0266_device::device_start() save_item(NAME(m_offset)); save_item(NAME(m_map)); - save_item(NAME(m_int_state)); - save_item(NAME(m_drq_state)); + save_item(NAME(m_req_state)); m_dma_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dmac_0266_device::dma_check), this)); - m_int_state = false; - m_drq_state = false; + m_req_state = false; } void dmac_0266_device::device_reset() @@ -90,33 +83,22 @@ void dmac_0266_device::soft_reset() m_dma_check->enable(false); } -void dmac_0266_device::irq_w(int state) +void dmac_0266_device::eop_w(int state) { if (state) m_status |= INTERRUPT; else m_status &= ~INTERRUPT; - - set_int(state); } -void dmac_0266_device::drq_w(int state) +void dmac_0266_device::req_w(int state) { - m_drq_state = bool(state); + m_req_state = bool(state); - if (m_drq_state) + if (m_req_state) m_dma_check->adjust(attotime::zero); } -void dmac_0266_device::set_int(bool int_state) -{ - if (int_state != m_int_state) - { - m_int_state = int_state; - m_int(int_state); - } -} - void dmac_0266_device::control_w(u32 data) { LOG("control_w 0x%08x (%s)\n", data, machine().describe_context()); @@ -144,8 +126,8 @@ void dmac_0266_device::control_w(u32 data) void dmac_0266_device::dma_check(void *ptr, s32 param) { - // check drq active - if (!m_drq_state) + // check req active + if (!m_req_state) return; // check enabled @@ -154,7 +136,22 @@ void dmac_0266_device::dma_check(void *ptr, s32 param) // check transfer count if (!m_tcount) + { + /* + * HACK: NEWS-OS tries to write a block to disk but sets the transfer + * count to less than the block length, causing a hang while the + * adapter waits for more data that the DMAC is not ready to supply. + * It's not clear how the real hardware works - for now this hack + * continues to read and discard data from the device, or write + * arbitrary zero bytes to it until it deasserts the request line. + */ + if (m_control & DIRECTION) + m_dma_r(); + else + m_dma_w(0); + return; + } u32 const address = (m_map[m_tag & 0x7f] << 12) | (m_offset & 0xfff); @@ -195,7 +192,8 @@ void dmac_0266_device::dma_check(void *ptr, s32 param) if (!m_tcount) { LOG("transfer complete\n"); - m_control &= ~ENABLE; + // HACK: per hack above, don't disable when reaching terminal count + //m_control &= ~ENABLE; m_status |= TCZERO; } else diff --git a/src/mame/machine/dmac_0266.h b/src/mame/machine/dmac_0266.h index bfadb405ca2..83150106d5d 100644 --- a/src/mame/machine/dmac_0266.h +++ b/src/mame/machine/dmac_0266.h @@ -14,14 +14,13 @@ public: // configuration template <typename T> void set_bus(T &&tag, int spacenum) { m_bus.set_tag(std::forward<T>(tag), spacenum); } - auto out_int_cb() { return m_int.bind(); } auto dma_r_cb() { return m_dma_r.bind(); } auto dma_w_cb() { return m_dma_w.bind(); } void map(address_map &map); - void irq_w(int state); - void drq_w(int state); + void eop_w(int state); + void req_w(int state); protected: // device_t overrides @@ -34,20 +33,18 @@ protected: u32 tcount_r() { return m_tcount; } void control_w(u32 data); - void tcount_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tcount); } - void tag_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_tag); } - void offset_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_offset); } - void entry_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_map[m_tag & 0x7f]); } + void tcount_w(u32 data) { m_tcount = data; } + void tag_w(u32 data) { m_tag = data; } + void offset_w(u32 data) { m_offset = data; } + void entry_w(u32 data) { m_map[m_tag & 0x7f] = data & 0x7fff; } // dma logic void soft_reset(); - void set_int(bool int_state); void dma_check(void *ptr, s32 param); private: required_address_space m_bus; - devcb_write_line m_int; devcb_read8 m_dma_r; devcb_write8 m_dma_w; @@ -72,11 +69,10 @@ private: u32 m_tcount; u32 m_tag; u32 m_offset; - u32 m_map[128]; + u32 m_map[129]; // internal state - bool m_int_state; - bool m_drq_state; + bool m_req_state; }; DECLARE_DEVICE_TYPE(DMAC_0266, dmac_0266_device) |