From 398471f89177c5675217892d7ddc78386090158b Mon Sep 17 00:00:00 2001 From: AJR Date: Thu, 13 Jun 2019 12:59:52 -0400 Subject: hpc3: DMA/interrupt improvements (nw) - Implement XIE (interrupt when done) flag in SCSI and PBUS DMA descriptors - Sort out some confusion between SCSI DMA control register and BC word in descriptor - Do something when FIFO flush bit is set in SCSI DMA control register - Move WD33C93 IRQs to IOC2 device (whose implementation is now completely decoupled from HPC3) --- src/mame/drivers/indy_indigo2.cpp | 7 +- src/mame/machine/hpc3.cpp | 140 +++++++++++++++++++++++++------------- src/mame/machine/hpc3.h | 19 +++--- src/mame/machine/ioc2.cpp | 18 ++++- src/mame/machine/ioc2.h | 2 + 5 files changed, 122 insertions(+), 64 deletions(-) diff --git a/src/mame/drivers/indy_indigo2.cpp b/src/mame/drivers/indy_indigo2.cpp index 931476ddf5b..85abfd849c4 100644 --- a/src/mame/drivers/indy_indigo2.cpp +++ b/src/mame/drivers/indy_indigo2.cpp @@ -61,6 +61,7 @@ #include "machine/ds1386.h" #include "machine/eepromser.h" #include "machine/hpc3.h" +#include "machine/ioc2.h" #include "machine/nscsi_bus.h" #include "machine/nscsi_cd.h" #include "machine/nscsi_hd.h" @@ -293,7 +294,7 @@ INPUT_PORTS_END void ip24_state::wd33c93(device_t *device) { device->set_clock(10000000); - downcast(device)->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi0_irq)); + downcast(device)->irq_cb().set(m_ioc2, FUNC(ioc2_device::scsi0_int_w)); downcast(device)->drq_cb().set(m_hpc3, FUNC(hpc3_device::scsi0_drq)); } @@ -329,7 +330,7 @@ void ip24_state::ip24_base(machine_config &config) GIO64_SLOT(config, m_gio64_exp0, m_gio64, gio64_slot_device::GIO64_SLOT_EXP0, gio64_cards, nullptr); GIO64_SLOT(config, m_gio64_exp1, m_gio64, gio64_slot_device::GIO64_SLOT_EXP1, gio64_cards, nullptr); - SGI_HPC3(config, m_hpc3, m_ioc2, m_hal2); + SGI_HPC3(config, m_hpc3, m_hal2); m_hpc3->set_gio64_space(m_maincpu, AS_PROGRAM); m_hpc3->set_addrmap(hpc3_device::AS_PIO0, &ip24_state::pio0_map); m_hpc3->set_addrmap(hpc3_device::AS_PIO1, &ip24_state::pio1_map); @@ -396,7 +397,7 @@ void ip24_state::indy_4610(machine_config &config) void ip22_state::wd33c93_2(device_t *device) { device->set_clock(10000000); - downcast(device)->irq_cb().set(m_hpc3, FUNC(hpc3_device::scsi1_irq)); + downcast(device)->irq_cb().set(m_ioc2, FUNC(ioc2_device::scsi1_int_w)); downcast(device)->drq_cb().set(m_hpc3, FUNC(hpc3_device::scsi1_drq)); } diff --git a/src/mame/machine/hpc3.cpp b/src/mame/machine/hpc3.cpp index b1f8c154ed1..dbcfe3d529c 100644 --- a/src/mame/machine/hpc3.cpp +++ b/src/mame/machine/hpc3.cpp @@ -39,7 +39,6 @@ hpc3_device::hpc3_device(const machine_config &mconfig, const char *tag, device_ {"PIO channel 8", ENDIANNESS_LITTLE, 16, 8, -1}, {"PIO channel 9", ENDIANNESS_LITTLE, 16, 8, -1}} , m_gio64_space(*this, finder_base::DUMMY_TAG, -1) - , m_ioc2(*this, finder_base::DUMMY_TAG) , m_hal2(*this, finder_base::DUMMY_TAG) , m_hd_rd_cb{{*this}, {*this}} , m_hd_wr_cb{{*this}, {*this}} @@ -109,9 +108,9 @@ void hpc3_device::device_start() save_item(NAME(m_scsi_dma[i].m_nbdp), i); save_item(NAME(m_scsi_dma[i].m_ctrl), i); save_item(NAME(m_scsi_dma[i].m_bc), i); + save_item(NAME(m_scsi_dma[i].m_count), i); save_item(NAME(m_scsi_dma[i].m_dmacfg), i); save_item(NAME(m_scsi_dma[i].m_piocfg), i); - save_item(NAME(m_scsi_dma[i].m_irq), i); save_item(NAME(m_scsi_dma[i].m_drq), i); save_item(NAME(m_scsi_dma[i].m_big_endian), i); save_item(NAME(m_scsi_dma[i].m_to_device), i); @@ -187,6 +186,9 @@ void hpc3_device::device_reset() m_pbus_dma[i].m_active = false; m_pbus_dma[i].m_timer->adjust(attotime::never); } + + m_intstat = 0; + m_dma_complete_int_cb(0); } void hpc3_device::map(address_map &map) @@ -248,13 +250,19 @@ void hpc3_device::do_pbus_dma(uint32_t channel) if (dma.m_bytes_left == 0) { + if (BIT(dma.m_desc_flags, 29)) + { + LOGMASKED(LOG_PBUS_DMA, "Raising channel %d IRQ\n", channel); + m_intstat |= 1 << channel; + m_dma_complete_int_cb(1); + } if (!BIT(dma.m_desc_flags, 31)) { dma.m_desc_ptr = dma.m_next_ptr; LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_DescPtr = %08x\n", channel, dma.m_desc_ptr); fflush(stdout); dma.m_cur_ptr = m_gio64_space->read_dword(dma.m_desc_ptr); dma.m_desc_flags = m_gio64_space->read_dword(dma.m_desc_ptr + 4); - dma.m_bytes_left = dma.m_desc_flags & 0x7fffffff; + dma.m_bytes_left = dma.m_desc_flags & 0x3fff; dma.m_next_ptr = m_gio64_space->read_dword(dma.m_desc_ptr + 8); LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_CurPtr = %08x\n", channel, dma.m_cur_ptr); fflush(stdout); LOGMASKED(LOG_PBUS_DMA, "Channel %d Next PBUS_DMA_BytesLeft = %08x\n", channel, dma.m_bytes_left); fflush(stdout); @@ -320,15 +328,28 @@ READ32_MEMBER(hpc3_device::hd_enet_r) case 0x3000/4: { const uint32_t channel = (offset & 0x2000/4) ? 1 : 0; - LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Buffer Count Read: %08x & %08x\n", machine().describe_context(), channel, m_scsi_dma[channel].m_bc, mem_mask); - return m_scsi_dma[channel].m_bc; + const uint32_t ret = (m_scsi_dma[channel].m_count & 0x3fff) | (m_scsi_dma[channel].m_bc & 0xffffc000); + LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Buffer Count Read: %08x & %08x\n", machine().describe_context(), channel, ret, mem_mask); + return ret; } case 0x1004/4: case 0x3004/4: { const uint32_t channel = (offset & 0x2000/4) ? 1 : 0; - LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Control Read: %08x & %08x\n", machine().describe_context(), channel, m_scsi_dma[channel].m_ctrl, mem_mask); - return m_scsi_dma[channel].m_ctrl; + uint32_t ret = m_scsi_dma[channel].m_ctrl; + if (BIT(m_intstat, channel + 8)) + { + ret |= HPC3_DMACTRL_IRQ; + if (!machine().side_effects_disabled()) + { + LOGMASKED(LOG_SCSI_IRQ, "Lowering SCSI %d IRQ\n", channel); + m_intstat &= ~(0x100 << channel); + if (m_intstat == 0) + m_dma_complete_int_cb(0); + } + } + LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Control Read: %08x & %08x\n", machine().describe_context(), channel, ret, mem_mask); + return ret; } case 0x1008/4: case 0x3008/4: @@ -421,22 +442,41 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) m_scsi_dma[channel].m_nbdp = data; break; } + case 0x1000/4: + case 0x3000/4: + { + const uint32_t channel = (offset & 0x2000/4) ? 1 : 0; + LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Buffer Count Write: %08x\n", machine().describe_context(), channel, data); + m_scsi_dma[channel].m_bc = data; + } case 0x1004/4: case 0x3004/4: { const uint32_t channel = (offset & 0x2000/4) ? 1 : 0; LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d DMA Control Write: %08x\n", machine().describe_context(), channel, data); const bool was_active = m_scsi_dma[channel].m_active; - m_scsi_dma[channel].m_ctrl = data; + if (data & HPC3_DMACTRL_WRMASK) + { + m_scsi_dma[channel].m_ctrl = data & ~HPC3_DMACTRL_IRQ & ~HPC3_DMACTRL_ENABLE & ~HPC3_DMACTRL_WRMASK; + if (was_active) + m_scsi_dma[channel].m_ctrl |= HPC3_DMACTRL_ENABLE; + } + else + { + m_scsi_dma[channel].m_ctrl = data & ~HPC3_DMACTRL_IRQ & ~HPC3_DMACTRL_WRMASK; + m_scsi_dma[channel].m_active = (m_scsi_dma[channel].m_ctrl & HPC3_DMACTRL_ENABLE); + } m_scsi_dma[channel].m_to_device = (m_scsi_dma[channel].m_ctrl & HPC3_DMACTRL_DIR); m_scsi_dma[channel].m_big_endian = (m_scsi_dma[channel].m_ctrl & HPC3_DMACTRL_ENDIAN); - m_scsi_dma[channel].m_active = (m_scsi_dma[channel].m_ctrl & HPC3_DMACTRL_ENABLE); - m_scsi_dma[channel].m_irq = (m_scsi_dma[channel].m_ctrl & HPC3_DMACTRL_IRQ); if (!was_active && m_scsi_dma[channel].m_active) { fetch_chain(channel); } m_hd_reset_cb[channel](BIT(data, 6)); + if (BIT(data, 3)) + { + scsi_fifo_flush(channel); + } if (m_scsi_dma[channel].m_drq && m_scsi_dma[channel].m_active) { do_scsi_dma(channel); @@ -666,6 +706,17 @@ READ32_MEMBER(hpc3_device::pbusdma_r) break; case 0x1000/4: ret = (dma.m_timer->remaining() != attotime::never) ? 2 : 0; + if (BIT(m_intstat, channel)) + { + ret |= 1; + if (!machine().side_effects_disabled()) + { + LOGMASKED(LOG_PBUS_DMA, "Lowering channel %d IRQ\n", channel); + m_intstat &= ~(1 << channel); + if (m_intstat == 0) + m_dma_complete_int_cb(0); + } + } LOGMASKED(LOG_PBUS_DMA, "%s: PBUS DMA Channel %d Control Read: %08x & %08x\n", machine().describe_context(), channel, ret, mem_mask); break; default: @@ -689,7 +740,7 @@ WRITE32_MEMBER(hpc3_device::pbusdma_w) dma.m_cur_ptr = space.read_dword(dma.m_desc_ptr); dma.m_desc_flags = space.read_dword(dma.m_desc_ptr + 4); dma.m_next_ptr = space.read_dword(dma.m_desc_ptr + 8); - dma.m_bytes_left = dma.m_desc_flags & 0x7fffffff; + dma.m_bytes_left = dma.m_desc_flags & 0x3fff; LOGMASKED(LOG_PBUS_DMA, "%s: PBUS_DMA_CurPtr = %08x\n", machine().describe_context(), dma.m_cur_ptr); LOGMASKED(LOG_PBUS_DMA, "%s: PBUS_DMA_BytesLeft = %08x\n", machine().describe_context(), dma.m_bytes_left); LOGMASKED(LOG_PBUS_DMA, "%s: PBUS_DMA_NextPtr = %08x\n", machine().describe_context(), dma.m_next_ptr); @@ -827,23 +878,29 @@ void hpc3_device::fetch_chain(int channel) scsi_dma_t &dma = m_scsi_dma[channel]; const uint32_t desc_addr = dma.m_nbdp; dma.m_cbp = m_gio64_space->read_dword(desc_addr); - dma.m_ctrl = m_gio64_space->read_dword(desc_addr+4); + dma.m_bc = m_gio64_space->read_dword(desc_addr+4); dma.m_nbdp = m_gio64_space->read_dword(desc_addr+8); - dma.m_bc = dma.m_ctrl & 0x3fff; + dma.m_count = dma.m_bc & 0x3fff; LOGMASKED(LOG_CHAIN, "Fetching chain from %08x:\n", desc_addr); LOGMASKED(LOG_CHAIN, " Addr: %08x\n", dma.m_cbp); - LOGMASKED(LOG_CHAIN, " Ctrl: %08x\n", dma.m_ctrl); + LOGMASKED(LOG_CHAIN, " Ctrl: %08x\n", dma.m_bc); LOGMASKED(LOG_CHAIN, " Next: %08x\n", dma.m_nbdp); } void hpc3_device::decrement_chain(int channel) { scsi_dma_t &dma = m_scsi_dma[channel]; - dma.m_bc--; - if (dma.m_bc == 0) + dma.m_count--; + if (dma.m_count == 0) { - if (BIT(dma.m_ctrl, 31)) + if (BIT(dma.m_bc, 29)) + { + LOGMASKED(LOG_SCSI_IRQ, "Raising SCSI %d IRQ\n", channel); + m_intstat |= 0x100 << channel; + m_dma_complete_int_cb(1); + } + if (BIT(dma.m_bc, 31)) { dma.m_active = false; dma.m_ctrl &= ~HPC3_DMACTRL_ENABLE; @@ -853,6 +910,23 @@ void hpc3_device::decrement_chain(int channel) } } +void hpc3_device::scsi_fifo_flush(int channel) +{ + scsi_dma_t &dma = m_scsi_dma[channel]; + + LOGMASKED(LOG_SCSI_DMA, "Flushing SCSI %d FIFO\n", channel); + + if (BIT(dma.m_bc, 29)) + { + LOGMASKED(LOG_SCSI_IRQ, "Raising SCSI %d IRQ\n", channel); + m_intstat |= 0x100 << channel; + m_dma_complete_int_cb(1); + } + + dma.m_active = false; + dma.m_ctrl &= ~(HPC3_DMACTRL_ENABLE | HPC3_DMACTRL_FLUSH); +} + void hpc3_device::scsi_drq(bool state, int channel) { scsi_dma_t &dma = m_scsi_dma[channel]; @@ -894,38 +968,6 @@ WRITE_LINE_MEMBER(hpc3_device::scsi1_drq) scsi_drq(state, 1); } -WRITE_LINE_MEMBER(hpc3_device::scsi0_irq) -{ - if (state) - { - LOGMASKED(LOG_SCSI_IRQ, "Raising SCSI 0 IRQ\n"); - m_ioc2->raise_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI0); - m_intstat |= 0x100; - } - else - { - LOGMASKED(LOG_SCSI_IRQ, "Lowering SCSI 0 IRQ\n"); - m_ioc2->lower_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI0); - m_intstat &= ~0x100; - } -} - -WRITE_LINE_MEMBER(hpc3_device::scsi1_irq) -{ - if (state) - { - LOGMASKED(LOG_SCSI_IRQ, "Raising SCSI 1 IRQ\n"); - m_ioc2->raise_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI1); - m_intstat |= 0x200; - } - else - { - LOGMASKED(LOG_SCSI_IRQ, "Lowering SCSI 1 IRQ\n"); - m_ioc2->lower_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI1); - m_intstat &= ~0x200; - } -} - READ32_MEMBER(hpc3_device::intstat_r) { return m_intstat; diff --git a/src/mame/machine/hpc3.h b/src/mame/machine/hpc3.h index 24f837a7f77..7fadd8f631a 100644 --- a/src/mame/machine/hpc3.h +++ b/src/mame/machine/hpc3.h @@ -12,7 +12,6 @@ #pragma once #include "machine/hal2.h" -#include "machine/ioc2.h" class hpc3_device : public device_t, public device_memory_interface { @@ -33,16 +32,14 @@ public: hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - template - hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&ioc2_tag, U &&hal2_tag) + template + hpc3_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&hal2_tag) : hpc3_device(mconfig, tag, owner, (uint32_t)0) { - set_ioc2_tag(std::forward(ioc2_tag)); - set_hal2_tag(std::forward(hal2_tag)); + set_hal2_tag(std::forward(hal2_tag)); } template void set_gio64_space(T &&tag, int spacenum) { m_gio64_space.set_tag(std::forward(tag), spacenum); } - template void set_ioc2_tag(T &&tag) { m_ioc2.set_tag(std::forward(tag)); } template void set_hal2_tag(T &&tag) { m_hal2.set_tag(std::forward(tag)); } template auto hd_rd_cb() { return m_hd_rd_cb[N].bind(); } @@ -61,9 +58,7 @@ public: void map(address_map &map); - DECLARE_WRITE_LINE_MEMBER(scsi0_irq); DECLARE_WRITE_LINE_MEMBER(scsi0_drq); - DECLARE_WRITE_LINE_MEMBER(scsi1_irq); DECLARE_WRITE_LINE_MEMBER(scsi1_drq); protected: @@ -114,6 +109,7 @@ protected: void dump_chain(uint32_t base); void fetch_chain(int channel); void decrement_chain(int channel); + void scsi_fifo_flush(int channel); void scsi_drq(bool state, int channel); //void scsi_dma(int channel); @@ -160,7 +156,9 @@ protected: HPC3_DMACTRL_IRQ = 0x01, HPC3_DMACTRL_ENDIAN = 0x02, HPC3_DMACTRL_DIR = 0x04, + HPC3_DMACTRL_FLUSH = 0x08, HPC3_DMACTRL_ENABLE = 0x10, + HPC3_DMACTRL_WRMASK = 0x20, }; enum @@ -173,7 +171,6 @@ protected: required_address_space m_gio64_space; address_space *m_pio_space[10]; - required_device m_ioc2; required_device m_hal2; devcb_read8 m_hd_rd_cb[2]; @@ -198,11 +195,11 @@ protected: { uint32_t m_cbp; uint32_t m_nbdp; - uint32_t m_ctrl; + uint8_t m_ctrl; uint32_t m_bc; + uint16_t m_count; uint32_t m_dmacfg; uint32_t m_piocfg; - bool m_irq; bool m_drq; bool m_big_endian; bool m_to_device; diff --git a/src/mame/machine/ioc2.cpp b/src/mame/machine/ioc2.cpp index fde355d9418..4ed1d0a3d07 100644 --- a/src/mame/machine/ioc2.cpp +++ b/src/mame/machine/ioc2.cpp @@ -721,7 +721,7 @@ WRITE_LINE_MEMBER(ioc2_device::gio_int2_w) WRITE_LINE_MEMBER(ioc2_device::hpc_dma_done_w) { - if (state == ASSERT_LINE) + if (state) raise_local_irq(1, ioc2_device::INT3_LOCAL1_HPC_DMA); else lower_local_irq(1, ioc2_device::INT3_LOCAL1_HPC_DMA); @@ -734,3 +734,19 @@ WRITE_LINE_MEMBER(ioc2_device::mc_dma_done_w) else lower_local_irq(0, ioc2_device::INT3_LOCAL0_MC_DMA); } + +WRITE_LINE_MEMBER(ioc2_device::scsi0_int_w) +{ + if (state) + raise_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI0); + else + lower_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI0); +} + +WRITE_LINE_MEMBER(ioc2_device::scsi1_int_w) +{ + if (state) + raise_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI1); + else + lower_local_irq(0, ioc2_device::INT3_LOCAL0_SCSI1); +} diff --git a/src/mame/machine/ioc2.h b/src/mame/machine/ioc2.h index 1af24846849..d4b711958f0 100644 --- a/src/mame/machine/ioc2.h +++ b/src/mame/machine/ioc2.h @@ -33,6 +33,8 @@ public: DECLARE_WRITE_LINE_MEMBER(gio_int2_w); DECLARE_WRITE_LINE_MEMBER(hpc_dma_done_w); DECLARE_WRITE_LINE_MEMBER(mc_dma_done_w); + DECLARE_WRITE_LINE_MEMBER(scsi0_int_w); + DECLARE_WRITE_LINE_MEMBER(scsi1_int_w); void raise_local_irq(int channel, uint8_t mask); void lower_local_irq(int channel, uint8_t mask); -- cgit v1.2.3