diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 6b00222572c1d..a5d235b748a98 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -4923,6 +4923,8 @@ if (BUSES["QBUS"]~=null) then MAME_DIR .. "src/devices/bus/qbus/dsd4432.h", MAME_DIR .. "src/devices/bus/qbus/dvk_kgd.cpp", MAME_DIR .. "src/devices/bus/qbus/dvk_kgd.h", + MAME_DIR .. "src/devices/bus/qbus/dvk_kmd.cpp", + MAME_DIR .. "src/devices/bus/qbus/dvk_kmd.h", MAME_DIR .. "src/devices/bus/qbus/dvk_mx.cpp", MAME_DIR .. "src/devices/bus/qbus/dvk_mx.h", MAME_DIR .. "src/devices/bus/qbus/pc11.cpp", diff --git a/src/devices/bus/qbus/dvk_kmd.cpp b/src/devices/bus/qbus/dvk_kmd.cpp new file mode 100644 index 0000000000000..04aceaf530e0f --- /dev/null +++ b/src/devices/bus/qbus/dvk_kmd.cpp @@ -0,0 +1,320 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/*************************************************************************** + + DVK KMD floppy controller (decimal 3.057.136, device driver MY.SYS) + + https://emuverse.ru/downloads/computers/DVK/docs/KMD/KMD_MY_RU1_.djvu + + 22-bit bus capable, uses DMA. CSR 172140, vector 170. + + Firmware 091 supports only ISO track format (without index mark) and + double-sided disks. + + Firmware 092 also supports PC track format (with index mark) and + single-sided disks, fixes bugs and adds 4 new commands. + + Bootstrap for systems without ROM 279: + + 172140/000040 37 + 172142/xxxxxx 0 "^" + 172140/000000 40 "G" + + Commands: + + 0 read + 1 write + 2 read dd + 3 write dd + 4 read track + 5 read id + 6 format iso + 7 seek + 8 set + 9 read error state + A* + B* format & write + C* format ibm + D* block move + E* run user code + F boot + +***************************************************************************/ + +#include "emu.h" +#include "dvk_kmd.h" + +#define LOG_DBG (1U << 1) + +//#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info + +#include "logmacro.h" + +#define LOGDBG(format, ...) LOGMASKED(LOG_DBG, "%11.6f at %s: " format, machine().time().as_double(), machine().describe_context(), __VA_ARGS__) + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(DVK_KMD, dvk_kmd_device, "dvk_kmd", "DVK KMD floppy controller") + +ROM_START(dvk_kmd) + ROM_REGION(0x2000, "maincpu", 0) + ROM_DEFAULT_BIOS("092") + ROM_SYSTEM_BIOS(0, "091", "mask 091") + ROMX_LOAD("091.dat", 0x0000, 0x2000, CRC(3bd0effc) SHA1(4a3e4567dc46cb306d37fbe71839bc46e232bac8), ROM_BIOS(0)) + ROM_SYSTEM_BIOS(1, "092", "mask 092") + ROMX_LOAD("092.dat", 0x0000, 0x2000, CRC(eb4e1de1) SHA1(6bc020054934a5562e763a18f915b8d612ccc70c), ROM_BIOS(1)) +ROM_END + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// dvk_kmd_device - constructor +//------------------------------------------------- + +dvk_kmd_device::dvk_kmd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, DVK_KMD, tag, owner, clock) + , device_qbus_card_interface(mconfig, *this) + , device_z80daisy_interface(mconfig, *this) + , m_maincpu(*this, "maincpu") + , m_fdc(*this, "fdc") + , m_installed(false) +{ +} + +void dvk_kmd_device::floppy_formats(format_registration &fr) +{ + fr.add_mfm_containers(); + fr.add(FLOPPY_BK0010_FORMAT); +} + +static void kmd_floppies(device_slot_interface &device) +{ + device.option_add("525qd", FLOPPY_525_QD); +} + +void dvk_kmd_device::kmd_mem(address_map &map) +{ + // FIXME: add trap + map(0000000, 0017777).rom().region("maincpu", 0); + map(0020000, 0023777).ram(); + map(0040000, 0077777).rw(FUNC(dvk_kmd_device::dma_read), FUNC(dvk_kmd_device::dma_write)); + map(0177100, 0177103).rw(FUNC(dvk_kmd_device::local_read), FUNC(dvk_kmd_device::local_write)); + map(0177130, 0177133).rw(m_fdc, FUNC(k1801vp128_device::read), FUNC(k1801vp128_device::write)); + map(0177716, 0177717).lr16(NAME([] (offs_t offset) { return 010000 | 1; })).nopw(); + map(0177760, 0177761).noprw(); // RAM chip base address register +} + +const tiny_rom_entry *dvk_kmd_device::device_rom_region() const +{ + return ROM_NAME(dvk_kmd); +} + +void dvk_kmd_device::device_add_mconfig(machine_config &config) +{ + K1801VM1(config, m_maincpu, XTAL(8'000'000) / 2); + m_maincpu->set_addrmap(AS_PROGRAM, &dvk_kmd_device::kmd_mem); + + K1801VP128(config, m_fdc, XTAL(4'000'000)); + m_fdc->ds_in_callback().set( + [] (uint16_t data) + { + switch (data & 15) + { + case 1: return 0; + case 2: return 1; + case 4: return 2; + case 8: return 3; + default: return -1; + } + }); + FLOPPY_CONNECTOR(config, "fdc:0", kmd_floppies, "525qd", dvk_kmd_device::floppy_formats); + FLOPPY_CONNECTOR(config, "fdc:1", kmd_floppies, "525qd", dvk_kmd_device::floppy_formats); + FLOPPY_CONNECTOR(config, "fdc:2", kmd_floppies, "525qd", dvk_kmd_device::floppy_formats); + FLOPPY_CONNECTOR(config, "fdc:3", kmd_floppies, "525qd", dvk_kmd_device::floppy_formats); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dvk_kmd_device::device_start() +{ + // save state + save_item(NAME(m_installed)); + save_item(NAME(m_cr)); + save_item(NAME(m_dr)); + + m_installed = false; +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dvk_kmd_device::device_reset() +{ + if (!m_installed) + { + m_bus->install_device(0172140, 0172143, + read16sm_delegate(*this, FUNC(dvk_kmd_device::read)), + write16sm_delegate(*this, FUNC(dvk_kmd_device::write))); + m_installed = true; + } + m_cr = m_dr = m_go = 0; + m_rxrdy = CLEAR_LINE; +} + +void dvk_kmd_device::init_w() +{ + m_maincpu->pulse_input_line(t11_device::CP2_LINE, m_maincpu->minimum_quantum_time()); +} + + +//------------------------------------------------- +// read - register read +//------------------------------------------------- + +uint16_t dvk_kmd_device::read(offs_t offset) +{ + uint16_t data = 0; + + switch (offset) + { + case 0: + data = m_cr & KMDCSR_RD; + break; + + case 1: + data = m_dr; + break; + } + + return data; +} + + +//------------------------------------------------- +// write - register write +//------------------------------------------------- + +void dvk_kmd_device::write(offs_t offset, uint16_t data) +{ + LOGDBG("host W %06o <- %06o [cr %06o go %06o]\n", 0172140 + (offset << 1), data, m_cr, m_go); + + switch (offset) + { + case 0: + if ((data & CSR_IE) == 0) + { + clear_virq(m_bus->birq4_w, 1, 1, m_rxrdy); + } + m_cr = ((m_cr & ~KMDCSR_WR) | (data & KMDCSR_WR)); + if (data & KMDCSR_GO) + { + m_go = m_cr; + m_cr &= ~KMDCSR_DONE; + } + break; + + case 1: + m_dr = data; + m_cr &= ~KMDCSR_TR; + clear_virq(m_bus->birq4_w, m_cr, CSR_IE, m_rxrdy); + break; + } +} + + +int dvk_kmd_device::z80daisy_irq_state() +{ + if (m_rxrdy == ASSERT_LINE) + return Z80_DAISY_INT; + else + return 0; +} + +int dvk_kmd_device::z80daisy_irq_ack() +{ + int vec = -1; + + if (m_rxrdy == ASSERT_LINE) + { + m_rxrdy = CLEAR_LINE; + vec = 0170; + } + + return vec; +} + + +//************************************************************************** +// local bus +//************************************************************************** + +uint16_t dvk_kmd_device::local_read(offs_t offset) +{ + uint16_t data = 0; + + switch (offset) + { + case 0: + data = m_cr; + break; + + case 1: + data = m_dr; + break; + } + + return data; +} + +void dvk_kmd_device::local_write(offs_t offset, uint16_t data) +{ + LOGDBG("locl W %06o <- %06o [cr %06o go %06o]\n", 0177100 + (offset << 1), data, m_cr, m_go); + + switch (offset) + { + case 0: + if ((data & KMDCSR_DONE) && !(m_cr & KMDCSR_DONE)) + { + if (m_go & CSR_IE) LOGDBG("raising irq %s\n", ""); + raise_virq(m_bus->birq4_w, m_cr, CSR_IE, m_rxrdy); + } + else if (!(data & KMDCSR_DONE) && (m_cr & KMDCSR_DONE)) + { + if (m_go & CSR_IE) LOGDBG("clearing irq %s\n", ""); + clear_virq(m_bus->birq4_w, m_cr, CSR_IE, m_rxrdy); + } + m_cr = ((m_cr & ~KMDCSR_L_WR) | (data & KMDCSR_L_WR)); + break; + + case 1: + m_dr = data; + break; + } +} + +// FIXME add DMA protocol (CPU halt etc.); HALT mode howto? +uint16_t dvk_kmd_device::dma_read(offs_t offset) +{ + LOGDBG("dma R %06o=%06o\n", offset, (offset << 1) | ((m_dr & 3) << 14)); + + return m_bus->read((offset << 1) | ((m_dr & 3) << 14)); +} + +void dvk_kmd_device::dma_write(offs_t offset, uint16_t data) +{ + LOGDBG("dma W %06o=%06o <- %06o\n", offset, (offset << 1) | ((m_dr & 3) << 14), data); + + m_bus->write((offset << 1) | ((m_dr & 3) << 14), data); +} diff --git a/src/devices/bus/qbus/dvk_kmd.h b/src/devices/bus/qbus/dvk_kmd.h new file mode 100644 index 0000000000000..97d33b1001453 --- /dev/null +++ b/src/devices/bus/qbus/dvk_kmd.h @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/*************************************************************************** + + DVK KMD floppy controller (device driver MY.SYS) + +***************************************************************************/ + +#ifndef MAME_BUS_QBUS_DVK_KMD_H +#define MAME_BUS_QBUS_DVK_KMD_H + +#pragma once + +#include "qbus.h" + +#include "cpu/t11/t11.h" +#include "machine/1801vp128.h" +#include "machine/pdp11.h" +#include "machine/z80daisy.h" + +#include "formats/bk0010_dsk.h" + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +// ======================> dvk_kmd_device + +class dvk_kmd_device : public device_t, + public device_qbus_card_interface, + public device_z80daisy_interface +{ +public: + // construction/destruction + dvk_kmd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint16_t read(offs_t offset); + void write(offs_t offset, uint16_t data); + + virtual void init_w() override; + +protected: + // 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_z80daisy_interface overrides + virtual int z80daisy_irq_state() override; + virtual int z80daisy_irq_ack() override; + virtual void z80daisy_irq_reti() override {}; + + void kmd_mem(address_map &map) ATTR_COLD; + + required_device m_maincpu; + required_device m_fdc; + +private: + static constexpr uint16_t KMDCSR_GO = 0001; + static constexpr uint16_t KMDCSR_DONE = 0040; + static constexpr uint16_t KMDCSR_TR = 0200; + static constexpr uint16_t KMDCSR_RD = CSR_ERR | KMDCSR_TR | CSR_IE | KMDCSR_DONE; + static constexpr uint16_t KMDCSR_WR = CSR_IE | 077437; + static constexpr uint16_t KMDCSR_L_WR = CSR_ERR | KMDCSR_TR | KMDCSR_DONE; + + bool m_installed; + line_state m_rxrdy; + + uint16_t m_cr; + uint16_t m_go; + uint16_t m_dr; + + static void floppy_formats(format_registration &fr); + + uint16_t local_read(offs_t offset); + void local_write(offs_t offset, uint16_t data); + + uint16_t dma_read(offs_t offset); + void dma_write(offs_t offset, uint16_t data); +}; + + +// device type definition +DECLARE_DEVICE_TYPE(DVK_KMD, dvk_kmd_device) + +#endif // MAME_BUS_QBUS_DVK_KMD_H diff --git a/src/devices/bus/qbus/qbus.cpp b/src/devices/bus/qbus/qbus.cpp index d3b639c801f42..599a1e7b1eada 100644 --- a/src/devices/bus/qbus/qbus.cpp +++ b/src/devices/bus/qbus/qbus.cpp @@ -14,6 +14,7 @@ #include "bk_kmd.h" #include "dsd4432.h" #include "dvk_kgd.h" +#include "dvk_kmd.h" #include "dvk_mx.h" #include "pc11.h" #include "qg640.h" @@ -29,6 +30,7 @@ void qbus_cards(device_slot_interface &device) device.option_add("dsd4432", DSD4432); device.option_add("kgd", DVK_KGD); device.option_add("mx", DVK_MX); + device.option_add("my", DVK_KMD); device.option_add("mz", UKNC_KMD); device.option_add("qg640", MATROX_QG640); device.option_add("by", BK_KMD); @@ -159,6 +161,16 @@ void qbus_device::install_device(offs_t start, offs_t end, read16sm_delegate rha m_space->install_readwrite_handler(start, end, rhandler, whandler, mask); } +uint16_t qbus_device::read(offs_t offset, uint16_t mem_mask) +{ + return m_space->read_word(offset, mem_mask); +} + +void qbus_device::write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + m_space->write_word(offset, data, mem_mask); +} + //------------------------------------------------- // z80daisy_interface diff --git a/src/devices/bus/qbus/qbus.h b/src/devices/bus/qbus/qbus.h index c33af439080c3..68c16ae5d7061 100644 --- a/src/devices/bus/qbus/qbus.h +++ b/src/devices/bus/qbus/qbus.h @@ -92,6 +92,9 @@ class qbus_device : public device_t, void bdmr_w(int state) { m_out_bdmr_cb(state); } + uint16_t read(offs_t offset, uint16_t mem_mask = ~0); + void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + const address_space_config m_program_config; protected: