x68k: add CZ-7BS1 dma glue logic

This commit is contained in:
Patrick Mackinlay 2025-04-02 13:26:27 +07:00
parent ee6cb33f46
commit a71c0333b7
5 changed files with 72 additions and 14 deletions

View File

@ -56,7 +56,7 @@ void x68k_scsiext_device::device_add_mconfig(machine_config &config)
{
mb89352_device &spc = downcast<mb89352_device &>(*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<x68k_expansion_slot_device *>(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);
}

View File

@ -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<mb89352_device> m_spc;
required_region_ptr<u8> m_rom;
bool m_drq;
};
// device type definition

View File

@ -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); }

View File

@ -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;
};

View File

@ -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<IOC_HDD_INT>));
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");