diff --git a/src/devices/bus/x68k/x68k_scsiext.cpp b/src/devices/bus/x68k/x68k_scsiext.cpp index a5f8a984567..dbf1e9a04cd 100644 --- a/src/devices/bus/x68k/x68k_scsiext.cpp +++ b/src/devices/bus/x68k/x68k_scsiext.cpp @@ -56,7 +56,7 @@ void x68k_scsiext_device::device_add_mconfig(machine_config &config) { mb89352_device &spc = downcast(*device); - spc.set_clock(8'000'000); // ? + spc.set_clock(10'000'000 / 2); // 10MHz clock from bus spc.out_irq_callback().set(*this, FUNC(x68k_scsiext_device::irq_w)); spc.out_dreq_callback().set(*this, FUNC(x68k_scsiext_device::drq_w)); }); @@ -68,16 +68,24 @@ x68k_scsiext_device::x68k_scsiext_device(const machine_config &mconfig, const ch , m_slot(nullptr) , m_spc(*this, "scsi:7:spc") , m_rom(*this, "scsiexrom") + , m_drq(false) { } void x68k_scsiext_device::device_start() { + save_item(NAME(m_drq)); + m_slot = dynamic_cast(owner()); m_slot->space().install_rom(0xea0020,0xea1fff, m_rom.target()); m_slot->space().unmap_write(0xea0020,0xea1fff); m_slot->space().install_device(0xea0000, 0xea001f, *m_spc, &mb89352_device::map, 0x00ff00ff); + + // replace data register handlers with DMA-aware glue + m_slot->space().install_readwrite_handler(0xea0015, 0xea0015, + emu::rw_delegate(*this, FUNC(x68k_scsiext_device::data_r)), + emu::rw_delegate(*this, FUNC(x68k_scsiext_device::data_w))); } void x68k_scsiext_device::device_reset() @@ -86,7 +94,8 @@ void x68k_scsiext_device::device_reset() void x68k_scsiext_device::irq_w(int state) { - m_slot->irq2_w(state); // correct? Or perhaps selectable? + // TODO: jumper-configurable IRQ2/IRQ4 + m_slot->irq2_w(state); } uint8_t x68k_scsiext_device::iack2() @@ -96,5 +105,36 @@ uint8_t x68k_scsiext_device::iack2() void x68k_scsiext_device::drq_w(int state) { - // TODO + m_drq = bool(state); +} + +u8 x68k_scsiext_device::data_r() +{ + // check for DMA cycle + if (m_slot->exown() && !machine().side_effects_disabled()) + { + // negate #DTACK if not requesting a DMA transfer + if (!m_drq) + m_slot->dtack_w(1); + + return m_spc->dma_r(); + } + else + return m_spc->dreg_r(); + +} + +void x68k_scsiext_device::data_w(u8 data) +{ + // check for DMA cycle + if (m_slot->exown()) + { + // negate #DTACK if not requesting a DMA transfer + if (!m_drq) + m_slot->dtack_w(1); + else + m_spc->dma_w(data); + } + else + m_spc->dreg_w(data); } diff --git a/src/devices/bus/x68k/x68k_scsiext.h b/src/devices/bus/x68k/x68k_scsiext.h index dcd345c008f..8bd66a52a70 100644 --- a/src/devices/bus/x68k/x68k_scsiext.h +++ b/src/devices/bus/x68k/x68k_scsiext.h @@ -22,23 +22,28 @@ public: x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: - // device-level overrides + // device_t implementation virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; - // device_x68k_expansion_card_interface overrides + // device_x68k_expansion_card_interface implementation virtual uint8_t iack2() override; private: void irq_w(int state); void drq_w(int state); + u8 data_r(); + void data_w(u8 data); + x68k_expansion_slot_device *m_slot; required_device m_spc; required_region_ptr m_rom; + + bool m_drq; }; // device type definition diff --git a/src/devices/bus/x68k/x68kexp.cpp b/src/devices/bus/x68k/x68kexp.cpp index 58c0f639170..cd83867017e 100644 --- a/src/devices/bus/x68k/x68kexp.cpp +++ b/src/devices/bus/x68k/x68kexp.cpp @@ -53,6 +53,7 @@ x68k_expansion_slot_device::x68k_expansion_slot_device(const machine_config &mco m_out_irq4_cb(*this), m_out_nmi_cb(*this), m_out_reset_cb(*this), + m_out_dtack_cb(*this), m_card(nullptr) { } @@ -67,6 +68,8 @@ x68k_expansion_slot_device::~x68k_expansion_slot_device() void x68k_expansion_slot_device::device_start() { + save_item(NAME(m_exown)); + m_card = get_card_device(); } @@ -75,3 +78,4 @@ void x68k_expansion_slot_device::irq2_w(int state) { m_out_irq2_cb(state); } void x68k_expansion_slot_device::irq4_w(int state) { m_out_irq4_cb(state); } void x68k_expansion_slot_device::nmi_w(int state) { m_out_nmi_cb(state); } void x68k_expansion_slot_device::reset_w(int state) { m_out_reset_cb(state); } +void x68k_expansion_slot_device::dtack_w(int state) { m_out_dtack_cb(state); } diff --git a/src/devices/bus/x68k/x68kexp.h b/src/devices/bus/x68k/x68kexp.h index 33ad1bd46b9..a4638de1157 100644 --- a/src/devices/bus/x68k/x68kexp.h +++ b/src/devices/bus/x68k/x68kexp.h @@ -115,6 +115,7 @@ public: auto out_irq4_callback() { return m_out_irq4_cb.bind(); } auto out_nmi_callback() { return m_out_nmi_cb.bind(); } auto out_reset_callback() { return m_out_reset_cb.bind(); } + auto out_dtack_callback() { return m_out_dtack_cb.bind(); } address_space &space() { return *m_space; } @@ -122,22 +123,29 @@ public: void irq4_w(int state); void nmi_w(int state); void reset_w(int state); + void dtack_w(int state); + bool exown() const { return m_exown; } uint8_t iack2() { return (m_card != nullptr) ? m_card->iack2() : 0x18; } uint8_t iack4() { return (m_card != nullptr) ? m_card->iack4() : 0x18; } + void exown_w(int state) { m_exown = !state; } protected: - // device-level overrides + // device_t implementation virtual void device_start() override ATTR_COLD; required_address_space m_space; +private: devcb_write_line m_out_irq2_cb; devcb_write_line m_out_irq4_cb; devcb_write_line m_out_nmi_cb; devcb_write_line m_out_reset_cb; + devcb_write_line m_out_dtack_cb; device_x68k_expansion_card_interface *m_card; + + bool m_exown; }; diff --git a/src/mame/sharp/x68k.cpp b/src/mame/sharp/x68k.cpp index efdb0432da5..e702030c437 100644 --- a/src/mame/sharp/x68k.cpp +++ b/src/mame/sharp/x68k.cpp @@ -742,24 +742,24 @@ void x68k_state::irq4_line(int state) uint8_t x68k_state::iack2() { - // Relative priority of IACK2-1 and IACK2-2 is unknown + // IACK2-1 has higher priority than IACK2-2 if (m_exp_irq2[0]) return m_expansion[0]->iack2(); else if (m_exp_irq2[1]) return m_expansion[1]->iack2(); else - return 0x18; // spurious interrupt + return m68000_base_device::autovector(0); // spurious interrupt } uint8_t x68k_state::iack4() { - // Relative priority of IACK4-1 and IACK4-2 is unknown + // IACK4-1 has higher priority than IACK4-2 if (m_exp_irq4[0]) return m_expansion[0]->iack4(); else if (m_exp_irq4[1]) return m_expansion[1]->iack4(); else - return 0x18; // spurious interrupt + return m68000_base_device::autovector(0); // spurious interrupt } void x68k_state::cpu_space_map(address_map &map) @@ -1111,12 +1111,16 @@ void x68k_state::x68000_base(machine_config &config) m_expansion[0]->out_irq2_callback().set(FUNC(x68k_state::irq2_line<0>)); m_expansion[0]->out_irq4_callback().set(FUNC(x68k_state::irq4_line<0>)); m_expansion[0]->out_nmi_callback().set(nmi, FUNC(input_merger_any_high_device::in_w<0>)); + m_expansion[0]->out_dtack_callback().set(m_hd63450, FUNC(hd63450_device::dtack_w)); + m_hd63450->own().append(m_expansion[0], FUNC(x68k_expansion_slot_device::exown_w)); X68K_EXPANSION_SLOT(config, m_expansion[1], x68000_exp_cards, nullptr); m_expansion[1]->set_space(m_maincpu, AS_PROGRAM); m_expansion[1]->out_irq2_callback().set(FUNC(x68k_state::irq2_line<1>)); m_expansion[1]->out_irq4_callback().set(FUNC(x68k_state::irq4_line<1>)); m_expansion[1]->out_nmi_callback().set(nmi, FUNC(input_merger_any_high_device::in_w<1>)); + m_expansion[1]->out_dtack_callback().set(m_hd63450, FUNC(hd63450_device::dtack_w)); + m_hd63450->own().append(m_expansion[1], FUNC(x68k_expansion_slot_device::exown_w)); /* internal ram */ RAM(config, m_ram).set_default_size("4M").set_extra_options("1M,2M,3M,5M,6M,7M,8M,9M,10M,11M,12M"); @@ -1169,12 +1173,9 @@ void x68ksupr_state::x68ksupr_base(machine_config &config) spc.set_clock(40_MHz_XTAL / 8); spc.out_irq_callback().set(*this, FUNC(x68ksupr_state::ioc_irq)); - spc.out_dreq_callback().set(m_hd63450, FUNC(hd63450_device::drq1_w)); + // TODO: duplicate DMA glue from CZ-6BS1 }); - m_hd63450->dma_read<1>().set("scsi:7:spc", FUNC(mb89352_device::dma_r)); - m_hd63450->dma_write<1>().set("scsi:7:spc", FUNC(mb89352_device::dma_w)); - VICON(config, m_crtc, 38.86363_MHz_XTAL); m_crtc->set_clock_69m(69.55199_MHz_XTAL); m_crtc->set_screen("screen");