heathzenith/h89.cpp: Add wait states for mms 77316 fdc (#12502)

This commit is contained in:
Mark Garlanger 2024-06-23 11:26:41 -05:00 committed by GitHub
parent 21d5d9c8fc
commit d0b00a538b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 21 deletions

View File

@ -150,6 +150,8 @@ protected:
void h89_base_io(address_map &map); void h89_base_io(address_map &map);
void set_wait_state(int data);
u8 raise_NMI_r(); u8 raise_NMI_r();
void raise_NMI_w(u8 data); void raise_NMI_w(u8 data);
void console_intr(int data); void console_intr(int data);
@ -247,14 +249,14 @@ class h89_mms_state : public h89_base_state
public: public:
h89_mms_state(const machine_config &mconfig, device_type type, const char *tag): h89_mms_state(const machine_config &mconfig, device_type type, const char *tag):
h89_base_state(mconfig, type, tag), h89_base_state(mconfig, type, tag),
m_mms(*this, "mms_fdc") m_mms316(*this, "mms77316")
{ {
} }
void h89_mms(machine_config &config); void h89_mms(machine_config &config);
protected: protected:
required_device<mms77316_fdc_device> m_mms; required_device<mms77316_fdc_device> m_mms316;
void h89_mms_io(address_map &map); void h89_mms_io(address_map &map);
}; };
@ -466,7 +468,7 @@ void h89_mms_state::h89_mms_io(address_map &map)
h89_base_state::h89_base_io(map); h89_base_state::h89_base_io(map);
// Add MMS 77316 Double Density Controller // Add MMS 77316 Double Density Controller
map(0x38,0x3f).rw(m_mms, FUNC(mms77316_fdc_device::read), FUNC(mms77316_fdc_device::write)); map(0x38,0x3f).rw(m_mms316, FUNC(mms77316_fdc_device::read), FUNC(mms77316_fdc_device::write));
} }
@ -783,6 +785,16 @@ void h89_base_state::machine_reset()
update_mem_view(); update_mem_view();
} }
void h89_base_state::set_wait_state(int data)
{
m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, data);
if (data)
{
machine().scheduler().synchronize();
m_maincpu->defer_access();
}
}
u8 h89_base_state::raise_NMI_r() u8 h89_base_state::raise_NMI_r()
{ {
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2));
@ -1010,9 +1022,10 @@ void h89_mms_state::h89_mms(machine_config &config)
m_intr_socket->set_default_option("mms"); m_intr_socket->set_default_option("mms");
m_intr_socket->set_fixed(true); m_intr_socket->set_fixed(true);
MMS77316_FDC(config, m_mms); MMS77316_FDC(config, m_mms316);
m_mms->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); m_mms316->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq));
m_mms->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); m_mms316->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq));
m_mms316->wait_cb().set(FUNC(h89_mms_state::set_wait_state));
} }

View File

@ -41,6 +41,7 @@ mms77316_fdc_device::mms77316_fdc_device(const machine_config &mconfig, const ch
device_t(mconfig, MMS77316_FDC, tag, owner, 0), device_t(mconfig, MMS77316_FDC, tag, owner, 0),
m_irq_cb(*this), m_irq_cb(*this),
m_drq_cb(*this), m_drq_cb(*this),
m_wait_cb(*this),
m_fdc(*this, "mms_fdc"), m_fdc(*this, "mms_fdc"),
m_floppies(*this, "mms_fdc:%u", 0U) m_floppies(*this, "mms_fdc:%u", 0U)
{ {
@ -84,7 +85,7 @@ void mms77316_fdc_device::ctrl_w(u8 val)
floppy_image_device *floppy = elem->get_device(); floppy_image_device *floppy = elem->get_device();
if (floppy) if (floppy)
{ {
// turn on all installed 5" floppies // set motor for installed 5" drives
floppy->mon_w(!five_in_drv); floppy->mon_w(!five_in_drv);
} }
} }
@ -93,10 +94,12 @@ void mms77316_fdc_device::ctrl_w(u8 val)
void mms77316_fdc_device::data_w(u8 val) void mms77316_fdc_device::data_w(u8 val)
{ {
if (burstMode()) if (burst_mode_r() && !m_drq && !m_irq)
{ {
// TODO add wait states in burst mode, currently blocked on Z80 properly supporting wait states LOGBURST("%s: burst_mode_r\n", FUNCNAME);
LOGBURST("%s: burst_mode: %d\n", FUNCNAME, val); m_wait_cb(ASSERT_LINE);
return;
} }
m_fdc->data_w(val); m_fdc->data_w(val);
@ -133,10 +136,12 @@ void mms77316_fdc_device::write(offs_t reg, u8 val)
u8 mms77316_fdc_device::data_r() u8 mms77316_fdc_device::data_r()
{ {
if (burstMode()) if (burst_mode_r() && !m_drq && !m_irq)
{ {
// TODO add wait states in burst mode, currently blocked on Z80 properly supporting wait states LOGBURST("%s: burst_mode setting wait state\n", FUNCNAME);
LOGBURST("%s: burst_mode\n", FUNCNAME); m_wait_cb(ASSERT_LINE);
return(0x00);
} }
return m_fdc->data_r(); return m_fdc->data_r();
@ -193,6 +198,7 @@ void mms77316_fdc_device::device_reset()
m_irq_cb(0); m_irq_cb(0);
m_drq_cb(0); m_drq_cb(0);
m_wait_cb(0);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
auto elem = m_floppies[i]; auto elem = m_floppies[i];
@ -265,6 +271,7 @@ void mms77316_fdc_device::set_irq(int state)
if (state) if (state)
{ {
m_wait_cb(CLEAR_LINE);
m_drq_count = 0; m_drq_count = 0;
} }
@ -275,16 +282,22 @@ void mms77316_fdc_device::set_irq(int state)
void mms77316_fdc_device::set_drq(int state) void mms77316_fdc_device::set_drq(int state)
{ {
bool drq_allowed = false;
LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state); LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state);
m_drq = state; m_drq = state;
if (burst_mode_r())
{
LOGBURST("%s: in burst mode drq: %d, m_drq_count: %d\n", FUNCNAME, m_drq, m_drq_count);
if (m_drq) if (m_drq)
{ {
// even if drq bit is not set, trigger if the first one after an IRQ. m_wait_cb(CLEAR_LINE);
drq_allowed = m_drq_allowed || (m_drq_count++ == 0);
} }
m_drq_cb(drq_allowed ? m_drq : CLEAR_LINE); m_drq_cb(m_drq_count == 0 ? m_drq : CLEAR_LINE);
}
else
{
m_drq_cb(m_drq_allowed ? m_drq : CLEAR_LINE);
}
} }

View File

@ -26,6 +26,7 @@ public:
auto irq_cb() { return m_irq_cb.bind(); } auto irq_cb() { return m_irq_cb.bind(); }
auto drq_cb() { return m_drq_cb.bind(); } auto drq_cb() { return m_drq_cb.bind(); }
auto wait_cb() { return m_wait_cb.bind(); }
protected: protected:
@ -43,12 +44,13 @@ protected:
// Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates. // Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates.
// The typical irq/drq was too slow, this utilizes wait states to read the // The typical irq/drq was too slow, this utilizes wait states to read the
// WD1797 data port once the drq line is high. // WD1797 data port once the drq line is high.
inline bool burstMode() { return !m_drq_allowed; } inline bool burst_mode_r() { return !m_drq_allowed; }
private: private:
devcb_write_line m_irq_cb; devcb_write_line m_irq_cb;
devcb_write_line m_drq_cb; devcb_write_line m_drq_cb;
devcb_write_line m_wait_cb;
required_device<fd1797_device> m_fdc; required_device<fd1797_device> m_fdc;
required_device_array<floppy_connector, 8> m_floppies; required_device_array<floppy_connector, 8> m_floppies;