From 3637f4bc4d587bfcd1ff3b01e957bdbf96f256ca Mon Sep 17 00:00:00 2001 From: shattered Date: Thu, 17 Feb 2022 02:46:01 +0000 Subject: [PATCH] ibm6580: floppy adapter LLE (WIP) (#9196) --- src/mame/drivers/ibm6580.cpp | 282 +++++++++++++++-------------------- 1 file changed, 123 insertions(+), 159 deletions(-) diff --git a/src/mame/drivers/ibm6580.cpp b/src/mame/drivers/ibm6580.cpp index f73ad8928a4..fa9aaa011ca 100644 --- a/src/mame/drivers/ibm6580.cpp +++ b/src/mame/drivers/ibm6580.cpp @@ -151,6 +151,7 @@ Notes on floppy drive: #include "bus/rs232/rs232.h" #include "cpu/i86/i86.h" +#include "cpu/mcs48/mcs48.h" #include "imagedev/floppy.h" #include "machine/i8251.h" #include "machine/i8255.h" @@ -210,10 +211,12 @@ public: , m_dma8257(*this, "dma8257") , m_screen(*this, "screen") , m_kbd(*this, "kbd") - , m_fdc(*this, UPD765_TAG) - , m_flop(*this, UPD765_TAG ":%u", 0U) , m_p_chargen(*this, "chargen") , m_leds(*this, "led%u", 5U) + , m_mcu(*this, "mcu") + , m_mcuppi(*this, "mcuppi") + , m_fdc(*this, UPD765_TAG) + , m_drive(*this, UPD765_TAG ":%u", 0U) { } void ibm6580(machine_config &config); @@ -248,8 +251,6 @@ private: void floppy_w(offs_t offset, uint8_t data); uint8_t floppy_r(offs_t offset); static void floppy_formats(format_registration &fr); - DECLARE_WRITE_LINE_MEMBER(floppy_intrq); - DECLARE_WRITE_LINE_MEMBER(floppy_hdl); DECLARE_WRITE_LINE_MEMBER(hrq_w); uint8_t memory_read_byte(offs_t offset); void memory_write_byte(offs_t offset, uint8_t data); @@ -259,20 +260,27 @@ private: void ibm6580_io(address_map &map); void ibm6580_mem(address_map &map); + void mcu_io(address_map &map); + void mcu_mem(address_map &map); + uint16_t m_gate; - uint8_t m_p40, m_p4a, m_p50, m_e000; + uint8_t m_dma0pg; + uint8_t m_p40, m_p4a, m_p50; uint8_t m_kb_data, m_ppi_c, m_led_state; + bool m_e000; bool m_kb_data_bit, m_kb_strobe, m_kb_clock; - util::fifo m_floppy_mcu_sr, m_floppy_mcu_cr; - int m_floppy_mcu_cr_fifo; - uint8_t m_floppy_sr; - floppy_image_device *m_floppies[2]; - floppy_image_device *m_floppy; - bool m_floppy_intrq, m_floppy_hdl, m_floppy_idle; - uint8_t m_dma0pg; - uint8_t floppy_mcu_command(); - bool floppy_mcu_cr_full(); + uint8_t m_mcu_p1, m_mcu_p2; + uint8_t m_mcuppi_a, m_mcuppi_b, m_mcuppi_c; + + void mcu_io_w(offs_t offset, uint8_t data); + uint8_t mcu_io_r(offs_t offset); + + void mcuppi_c_w(uint8_t data); + + bool m_floppy_intrq, m_floppy_idle; + uint8_t m_floppy_mcu_wrap; + struct { floppy_image_device *image; bool hdl; } m_floppy[2]; required_shared_ptr m_p_videoram; required_device m_ram; @@ -283,10 +291,12 @@ private: required_device m_dma8257; required_device m_screen; required_device m_kbd; - required_device m_fdc; - required_device_array m_flop; required_region_ptr m_p_chargen; output_finder<4> m_leds; + required_device m_mcu; + required_device m_mcuppi; + required_device m_fdc; + required_device_array m_drive; }; @@ -330,6 +340,9 @@ void ibm6580_state::p40_w(offs_t offset, uint8_t data) m_dma0pg = data; break; + case 7: + break; + case 8: m_p50 = data; break; @@ -619,13 +632,6 @@ WRITE_LINE_MEMBER(ibm6580_state::kb_strobe_w) m_ppi8255->pc4_w(m_kb_strobe); } -WRITE_LINE_MEMBER(ibm6580_state::floppy_intrq) -{ - m_floppy_intrq = state; - if (state) - m_floppy_idle = true; -} - WRITE_LINE_MEMBER(ibm6580_state::hrq_w) { m_maincpu->set_input_line(INPUT_LINE_HALT, state); @@ -644,133 +650,71 @@ void ibm6580_state::memory_write_byte(offs_t offset, uint8_t data) prog_space.write_byte(offset | (m_dma0pg << 16), data); } -bool ibm6580_state::floppy_mcu_cr_full() -{ - uint8_t command = m_floppy_mcu_cr.peek(); +// floppy adapter board - if ((command & 1) && m_floppy_mcu_cr_fifo == 1) - return true; - if (command == 0x0c && m_floppy_mcu_cr_fifo == 4) - return true; - if (m_floppy_mcu_cr_fifo == 3) - return true; - else - return false; +void ibm6580_state::mcu_io_w(offs_t offset, uint8_t data) +{ + LOGDBG("MCU IO %02x(%d) <- %02x\n", m_mcu_p1, m_mcu_p1 & 7, data); + + switch (m_mcu_p1 & 7) + { + case 0: case 1: case 2: case 3: + m_mcuppi->write(m_mcu_p1, data); + break; + } } -uint8_t ibm6580_state::floppy_mcu_command() +uint8_t ibm6580_state::mcu_io_r(offs_t offset) { - uint8_t data = 0, command = m_floppy_mcu_cr.dequeue(), i; + uint8_t data = 0; - LOG("Floppy mcu_command %02x\n", command); - - m_floppy_mcu_sr.clear(); - m_floppy_idle = true; - - switch (command) + switch (m_mcu_p1 & 7) { - case 0: - m_fdc->soft_reset(); - break; - - // 3 bytes - case 4: - break; - - // 1 byte -- get status? - case 5: - m_floppy_mcu_sr.enqueue(0x00); - if (m_flop[0]->get_device()->exists()) - m_floppy_mcu_sr.enqueue( m_flop[0]->get_device()->idx_r() ? 0x08 : 0); - else - m_floppy_mcu_sr.enqueue(0x08); - break; - - // 3 bytes, no return -- engage head - case 6: - m_floppy_mcu_cr.dequeue(); - i = m_floppy_mcu_cr.dequeue(); - m_floppy_hdl = i; - break; - - // 1 byte -- read head engage signal - case 7: - m_floppy_mcu_sr.enqueue(0x00); - m_floppy_mcu_sr.enqueue(m_floppy_hdl); - break; - - // 3 bytes - case 8: - break; - - // 4 bytes -- used by cp/m. drive select? - case 0xc: - break; - - // 1 byte -- get drive ready status? - case 0xd: - m_floppy_mcu_sr.enqueue(0x00); - i = 0; - if (m_flop[0]->get_device()->exists()) - i |= m_flop[0]->get_device()->ready_r() ? 0 : 0x40; - if (m_flop[1]->get_device()->exists()) - i |= m_flop[1]->get_device()->ready_r() ? 0 : 0x80; - m_floppy_mcu_sr.enqueue(i); - break; - - // 3 bytes, no return -- recalibrate? - case 0xe: - m_floppy_mcu_cr.dequeue(); - i = m_floppy_mcu_cr.dequeue(); -#if 1 - if (i & 1) - m_fdc->set_floppy(m_flop[0]->get_device()); - else if (i & 2) - m_fdc->set_floppy(m_flop[1]->get_device()); -#endif - break; - - // 1 byte - case 0x13: - break; - - // 1 byte - case 0x15: + case 0: case 1: case 2: case 3: + data = m_mcuppi->read(m_mcu_p1); break; } - m_floppy_mcu_cr.clear(); - m_floppy_mcu_cr_fifo = 0; + LOGDBG("MCU IO %02x(%d) == %02x at %s\n", m_mcu_p1, m_mcu_p1 & 7, data, machine().describe_context()); return data; } +void ibm6580_state::mcuppi_c_w(uint8_t data) +{ + LOGDBG("MCU PPI PC <- %02x\n", data); + m_mcuppi_c = data; + m_mcu->set_input_line(MCS48_INPUT_IRQ, BIT(data, 3)); // invert? +} + +// what happens on access to odd address ? void ibm6580_state::floppy_w(offs_t offset, uint8_t data) { - LOG("Floppy %02x <- %02x\n", 0x8150 + (offset << 1), data); + LOG("Floppy %s %02x <- %02x\n", machine().describe_context(), 0x8150 + (offset << 1), data); switch (offset) { case 0: // 8150 -- mcu reset? - m_floppy_mcu_sr.enqueue(0x00); - m_floppy_mcu_sr.enqueue(0x00); + m_mcu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); break; - case 1: // 8152 - m_fdc->soft_reset(); + case 1: // 8152 -- fdc reset? status not checked + // m_fdc->soft_reset(); + break; + + case 2: // 8154 + if (BIT(m_gate, 14)) + m_floppy_mcu_wrap = data; break; case 5: // 815A m_fdc->fifo_w(data); - if (m_floppy_idle) - m_floppy_idle = false; break; case 6: // 815C - m_floppy_mcu_cr.enqueue(data); - m_floppy_mcu_cr_fifo++; - if (floppy_mcu_cr_full()) - floppy_mcu_command(); + m_mcuppi_a = data; + m_mcuppi->pc4_w(1); + m_mcuppi->pc4_w(0); break; } } @@ -785,8 +729,12 @@ uint8_t ibm6580_state::floppy_r(offs_t offset) // bit 4 -- ?? ready // bit 5 -- mcu busy // bit 6 -- ?? idle - if (m_floppy_mcu_sr.empty() && (m_floppy_idle || m_floppy_intrq)) - data |= 0x40; + data = 8 | BIT(m_mcuppi_c, 7) << 6 | (m_mcuppi_c & 0x20); + break; + + case 3: // 8156 + if (BIT(m_gate, 14)) + data = m_floppy_mcu_wrap << 2; break; case 4: // 8158 @@ -798,27 +746,11 @@ uint8_t ibm6580_state::floppy_r(offs_t offset) break; case 6: // 815c - if (!m_floppy_mcu_sr.empty()) - data = m_floppy_mcu_sr.dequeue(); + data = m_mcuppi->acka_r(); break; } - if (offset) - LOG("Floppy %02x == %02x\n", 0x8150 + (offset << 1), data); - else { - floppy_image_device *f = m_flop[0]->get_device(); - - if (f) - LOG("Floppy %02x == %02x (empty %d hdl %d + idle %d irq %d drq %d + dskchg %d idx %d cyl %d)\n", - 0x8150 + (offset << 1), data, - m_floppy_mcu_sr.empty(), m_floppy_hdl, - m_floppy_idle, m_fdc->get_irq(), m_fdc->get_drq(), - f->dskchg_r(), f->idx_r(), f->get_cyl()); - else - LOG("Floppy %02x == %02x (idle %d irq %d drq %d)\n", - 0x8150 + (offset << 1), data, - m_floppy_idle, m_fdc->get_irq(), m_fdc->get_drq()); - } + LOG("Floppy %s %02x == %02x\n", machine().describe_context(), 0x8150 + (offset << 1), data); return data; } @@ -844,8 +776,8 @@ void ibm6580_state::ibm6580_io(address_map &map) map(0x0120, 0x0127).rw(m_pit8253, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff); map(0x0140, 0x0143).rw("upd8251a", FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); map(0x0160, 0x0163).rw("upd8251b", FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); - map(0x4000, 0x400f).unmaprw(); - map(0x5000, 0x500f).unmaprw(); + map(0x4000, 0x400f).unmaprw(); // bus error reporting? + map(0x5000, 0x500f).unmaprw(); // bus error reporting? map(0x6000, 0x601f).unmaprw(); map(0x8060, 0x807f).w(FUNC(ibm6580_state::gate_close_w)).umask16(0xff); map(0x8150, 0x815f).rw(FUNC(ibm6580_state::floppy_r), FUNC(ibm6580_state::floppy_w)).umask16(0x00ff); // HLE of floppy board @@ -854,6 +786,17 @@ void ibm6580_state::ibm6580_io(address_map &map) map(0xe000, 0xe02f).rw(FUNC(ibm6580_state::video_r), FUNC(ibm6580_state::video_w)).umask16(0x00ff); } +void ibm6580_state::mcu_mem(address_map &map) +{ + map.unmap_value_high(); + map(0x000, 0x7ff).rom().region("mcu", 0); +} + +void ibm6580_state::mcu_io(address_map &map) +{ + map(0x00, 0xff).rw(FUNC(ibm6580_state::mcu_io_r), FUNC(ibm6580_state::mcu_io_w)); +} + uint32_t ibm6580_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { @@ -970,6 +913,9 @@ void ibm6580_state::machine_start() m_fdc->set_rate(500000); // FIXME: workaround + m_floppy[0].image = m_fdc->subdevice("0")->get_device(); + m_floppy[1].image = m_fdc->subdevice("1")->get_device(); + m_leds.resolve(); memset(m_p_videoram, 0x0, 0x1000); @@ -977,23 +923,22 @@ void ibm6580_state::machine_start() void ibm6580_state::machine_reset() { - m_p40 = m_p4a = m_p50 = m_gate = m_e000 = m_ppi_c = m_floppy_sr = m_led_state = 0; + m_p40 = m_p4a = m_p50 = m_gate = m_ppi_c = m_led_state = 0; + m_mcu_p1 = m_mcu_p2 = 0; + m_mcuppi_a = m_mcuppi_b = m_mcuppi_c = 0; + m_e000 = false; m_kb_data_bit = false; m_kb_clock = false; m_kb_strobe = true; m_kb_data = 0; - m_floppy_idle = true; m_pit8253->set_clockin(0, 0.0); m_p40 |= m_kbd->memory_record_r(); - m_flop[0]->get_device()->mon_w(!m_flop[0]->get_device()->exists()); - m_flop[1]->get_device()->mon_w(!m_flop[1]->get_device()->exists()); - m_fdc->set_floppy(m_flop[0]->get_device()); - m_floppy_mcu_sr.clear(); - m_floppy_mcu_cr.clear(); - m_floppy_mcu_cr_fifo = 0; + m_floppy[0].hdl = m_floppy[1].hdl = false; + + m_fdc->set_floppy(m_drive[0]->get_device()); } static void dw_floppies(device_slot_interface &device) @@ -1049,13 +994,6 @@ void ibm6580_state::ibm6580(machine_config &config) m_dma8257->in_ior_cb<0>().set(m_fdc, FUNC(upd765a_device::dma_r)); m_dma8257->out_iow_cb<0>().set(m_fdc, FUNC(upd765a_device::dma_w)); - UPD765A(config, m_fdc, 24_MHz_XTAL / 3, false, false); - m_fdc->intrq_wr_callback().set(FUNC(ibm6580_state::floppy_intrq)); -// m_fdc->intrq_wr_callback().append(m_pic8259, FUNC(pic8259_device::ir4_w)); - m_fdc->drq_wr_callback().set(m_dma8257, FUNC(i8257_device::dreq0_w)); - FLOPPY_CONNECTOR(config, UPD765_TAG ":0", dw_floppies, "8sssd", floppy_image_device::default_mfm_floppy_formats); - FLOPPY_CONNECTOR(config, UPD765_TAG ":1", dw_floppies, "8sssd", floppy_image_device::default_mfm_floppy_formats); - i8251_device &upd8251a(I8251(config, "upd8251a", 0)); upd8251a.txd_handler().set("rs232a", FUNC(rs232_port_device::write_txd)); upd8251a.dtr_handler().set("rs232a", FUNC(rs232_port_device::write_dtr)); @@ -1080,6 +1018,29 @@ void ibm6580_state::ibm6580(machine_config &config) rs232b.dsr_handler().set("upd8251b", FUNC(i8251_device::write_dsr)); rs232b.cts_handler().set("upd8251b", FUNC(i8251_device::write_cts)); + // floppy adapter card (in the drive) + + I8048(config, m_mcu, 24_MHz_XTAL / 6); // XTAL divisor unknown + m_mcu->set_addrmap(AS_PROGRAM, &ibm6580_state::mcu_mem); + m_mcu->set_addrmap(AS_IO, &ibm6580_state::mcu_io); + m_mcu->p1_in_cb().set([this] () { + return (m_mcu_p1 & ~0x18) | \ + (!m_floppy[0].image->idx_r() << 3) | (!m_floppy[1].image->idx_r() << 4); + }); + m_mcu->p1_out_cb().set([this] (uint8_t data) { m_mcu_p1 = data; }); + + I8255(config, m_mcuppi); + m_mcuppi->in_pa_callback().set([this] () { LOGDBG("MCU PPI read A: %02X\n", m_mcuppi_a); return m_mcuppi_a; }); + m_mcuppi->out_pb_callback().set([this] (uint8_t data) { m_mcuppi_b = data; }); + m_mcuppi->out_pc_callback().set(FUNC(ibm6580_state::mcuppi_c_w)); + + // NEC D765D. READY and SELECT likely not connected. SEEK, STEP and DIR likely connected to MCU. + UPD765A(config, m_fdc, 24_MHz_XTAL / 3, false, false); + m_fdc->intrq_wr_callback().set([this] (bool state) { m_floppy_intrq = state; }); + m_fdc->drq_wr_callback().set(m_dma8257, FUNC(i8257_device::dreq0_w)); + FLOPPY_CONNECTOR(config, UPD765_TAG ":0", dw_floppies, "8sssd", floppy_image_device::default_mfm_floppy_formats); + FLOPPY_CONNECTOR(config, UPD765_TAG ":1", dw_floppies, "8sssd", floppy_image_device::default_mfm_floppy_formats); + SOFTWARE_LIST(config, "flop_list").set_original("ibm6580"); } @@ -1111,6 +1072,9 @@ ROM_START( ibm6580 ) ROM_REGION( 0x2000, "chargen", 0 ) ROM_LOAD( "8493383_chr.bin", 0x0000, 0x2000, CRC(779044df) SHA1(95ec46f9edf4d44c5dd3c955c73e00754d58e180)) + + ROM_REGION( 0x800, "mcu", 0 ) + ROM_LOAD( "4430030_flp_8041.bin", 0x0000, 0x0400, CRC(2bb96799) SHA1(e30b0f2d790197f290858eab74ad5e151ded78c3)) ROM_END /* Driver */