From 0759cce9e7a7447d3dac117c377369d84b04984d Mon Sep 17 00:00:00 2001 From: AJR Date: Fri, 21 Feb 2025 09:59:27 -0500 Subject: [PATCH] bus/qbus: Add dump and skeleton device for TDL-12 SCSI Host Adapter [Bitsavers] * z8536: Respect data direction registers when reading back from Ports A & B --- scripts/src/bus.lua | 2 + src/devices/bus/qbus/qbus.cpp | 2 + src/devices/bus/qbus/tdl12.cpp | 137 +++++++++++++++++++++++++++++++++ src/devices/bus/qbus/tdl12.h | 42 ++++++++++ src/devices/machine/z8536.cpp | 33 +++++--- 5 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 src/devices/bus/qbus/tdl12.cpp create mode 100644 src/devices/bus/qbus/tdl12.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 7f18c0431b3..c28d003849a 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -4790,6 +4790,8 @@ if (BUSES["QBUS"]~=null) then MAME_DIR .. "src/devices/bus/qbus/qg640.h", MAME_DIR .. "src/devices/bus/qbus/qtx.cpp", MAME_DIR .. "src/devices/bus/qbus/qtx.h", + MAME_DIR .. "src/devices/bus/qbus/tdl12.cpp", + MAME_DIR .. "src/devices/bus/qbus/tdl12.h", MAME_DIR .. "src/devices/bus/qbus/uknc_kmd.cpp", MAME_DIR .. "src/devices/bus/qbus/uknc_kmd.h", } diff --git a/src/devices/bus/qbus/qbus.cpp b/src/devices/bus/qbus/qbus.cpp index a5293df0c46..d3b639c801f 100644 --- a/src/devices/bus/qbus/qbus.cpp +++ b/src/devices/bus/qbus/qbus.cpp @@ -18,6 +18,7 @@ #include "pc11.h" #include "qg640.h" #include "qtx.h" +#include "tdl12.h" #include "uknc_kmd.h" @@ -31,6 +32,7 @@ void qbus_cards(device_slot_interface &device) device.option_add("mz", UKNC_KMD); device.option_add("qg640", MATROX_QG640); device.option_add("by", BK_KMD); + device.option_add("tdl12", TDL12); } diff --git a/src/devices/bus/qbus/tdl12.cpp b/src/devices/bus/qbus/tdl12.cpp new file mode 100644 index 00000000000..b9ea3a6df71 --- /dev/null +++ b/src/devices/bus/qbus/tdl12.cpp @@ -0,0 +1,137 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*********************************************************************************************************************************** + + TDL-12 SCSI Host Adapter (© 1985 T.D. Systems) + +************************************************************************************************************************************/ + +#include "emu.h" +#include "tdl12.h" + +#include "bus/nscsi/devices.h" +#include "cpu/z80/z80.h" +#include "machine/eepromser.h" +#include "machine/ncr5380.h" +#include "machine/z8536.h" + + +// device type definition +DEFINE_DEVICE_TYPE(TDL12, tdl12_device, "tdl12", "TDL-12 SCSI Host Adapter") + + +tdl12_device::tdl12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, TDL12, tag, owner, clock) + , device_qbus_card_interface(mconfig, *this) + , m_tdcpu(*this, "tdcpu") +{ +} + +void tdl12_device::device_start() +{ +} + +u8 tdl12_device::latch_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + logerror("%s: Reading from latch %c\n", machine().describe_context(), offset ? 'H' : 'L'); + return 0; +} + +void tdl12_device::latch_w(offs_t offset, u8 data) +{ + logerror("%s: Writing %02X to latch %c\n", machine().describe_context(), data, offset ? 'H' : 'L'); +} + +u8 tdl12_device::in40_r() +{ + // Used as low 8 bits of jump offset + // Valid values include 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xd0, 0xff + return 0xff; +} + +void tdl12_device::out40_w(u8 data) +{ + logerror("%s: Output %02X to port 40\n", machine().describe_context(), data); +} + +void tdl12_device::out70_w(u8 data) +{ + // Data written is irrelevant + logerror("%s: Output to port 70\n", machine().describe_context()); +} + +void tdl12_device::out74_w(u8 data) +{ + // Data written is irrelevant + logerror("%s: Output to port 74\n", machine().describe_context()); +} + +void tdl12_device::mem_map(address_map &map) +{ + map(0x0000, 0x3fff).rom().region("firmware", 0); + map(0x4000, 0x47ff).ram(); + map(0x8000, 0x8001).rw(FUNC(tdl12_device::latch_r), FUNC(tdl12_device::latch_w)); +} + +void tdl12_device::io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x03).rw("cio", FUNC(z8536_device::read), FUNC(z8536_device::write)); + map(0x40, 0x40).rw(FUNC(tdl12_device::in40_r), FUNC(tdl12_device::out40_w)); + map(0x70, 0x70).w(FUNC(tdl12_device::out70_w)); + map(0x74, 0x74).w(FUNC(tdl12_device::out74_w)); + map(0x80, 0x87).m("scsi:7:ncr5380", FUNC(ncr5380_device::map)); +} + +void tdl12_device::device_add_mconfig(machine_config &config) +{ + Z80(config, m_tdcpu, 12_MHz_XTAL / 2); // covered by "TD SYSTEMS INC." sticker (most likely Z80B) + m_tdcpu->set_addrmap(AS_PROGRAM, &tdl12_device::mem_map); + m_tdcpu->set_addrmap(AS_IO, &tdl12_device::io_map); + + z8536_device &cio(Z8536(config, "cio", 12_MHz_XTAL / 2)); // ST Z8536AB1 + cio.irq_wr_cb().set_inputline(m_tdcpu, 0); + cio.pb_wr_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::clk_write)).bit(0); + cio.pb_wr_cb().append("eeprom", FUNC(eeprom_serial_93cxx_device::di_write)).bit(1); + cio.pc_rd_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::do_read)).lshift(3); + cio.pc_wr_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::cs_write)).bit(2); + + NSCSI_BUS(config, "scsi"); + NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR5380).machine_config([this](device_t *device) { + (void)this; + }); + + EEPROM_93C46_16BIT(config, "eeprom"); // NMC9346N +} + + +ROM_START(tdl12) + ROM_REGION(0x4000, "firmware", 0) + ROM_LOAD("tdl-12_v180.bin", 0x0000, 0x4000, CRC(fd0f4468) SHA1(1cf0bf8702747ff3047691d2b661bb08d40754f0)) // Am(27128?)-25DC + + ROM_REGION(0x40, "proms", 0) // probably either Q-bus address decode or a short bootstrap program + ROM_LOAD("m_tdl-11.bin", 0x00, 0x20, NO_DUMP) // N82S123AN + ROM_LOAD("m_tdl-12.bin", 0x20, 0x20, NO_DUMP) // N82S123AN + + ROM_REGION(0x7a1, "plds", 0) + ROM_LOAD("mst_tdl-13.bin", 0x000, 0x117, NO_DUMP) // TIBPAL16L8-25CN (socketed, next to A/B jumpers) + ROM_LOAD("mst_tdl-21.bin", 0x117, 0x117, NO_DUMP) // TIBPAL16L8-25CN + ROM_LOAD("mst_tdl-26.bin", 0x22e, 0x117, NO_DUMP) // TIBPAL16L8-25CN + ROM_LOAD("mst_tdl-31.bin", 0x345, 0x117, NO_DUMP) // TIBPAL16L8-25CN + ROM_LOAD("mst_tdl-40.bin", 0x45c, 0x117, NO_DUMP) // TIBPAL16L8-25CN + ROM_LOAD("mst_tdl-41.bin", 0x573, 0x117, NO_DUMP) // TIBPAL16L8-25CN + ROM_LOAD("mst_tdl-42.bin", 0x68a, 0x117, NO_DUMP) // TIBPAL16L8-25CN +ROM_END + +const tiny_rom_entry *tdl12_device::device_rom_region() const +{ + return ROM_NAME(tdl12); +} diff --git a/src/devices/bus/qbus/tdl12.h b/src/devices/bus/qbus/tdl12.h new file mode 100644 index 00000000000..46716f98ff7 --- /dev/null +++ b/src/devices/bus/qbus/tdl12.h @@ -0,0 +1,42 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_BUS_QBUS_TDL12_H +#define MAME_BUS_QBUS_TDL12_H + +#pragma once + +#include "qbus.h" +#include "machine/ncr5380.h" + + +class tdl12_device : public device_t, public device_qbus_card_interface +{ +public: + // device type constructor + tdl12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() 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; + +private: + u8 latch_r(offs_t offset); + void latch_w(offs_t offset, u8 data); + u8 in40_r(); + void out40_w(u8 data); + void out70_w(u8 data); + void out74_w(u8 data); + + void mem_map(address_map &map) ATTR_COLD; + void io_map(address_map &map) ATTR_COLD; + + required_device m_tdcpu; +}; + +// device type declaration +DECLARE_DEVICE_TYPE(TDL12, tdl12_device) + +#endif // MAME_BUS_QBUS_TDL12_H diff --git a/src/devices/machine/z8536.cpp b/src/devices/machine/z8536.cpp index cb1fa74adb6..af1dd90c28a 100644 --- a/src/devices/machine/z8536.cpp +++ b/src/devices/machine/z8536.cpp @@ -201,15 +201,22 @@ u8 cio_base_device::read_register(offs_t offset) switch (offset) { case PORT_A_DATA: - data = m_read_pa(0); + // TODO: take data path polarity into account + data = m_output[PORT_A]; + if (m_register[PORT_A_DATA_DIRECTION] != 0) + data = (data & ~m_register[PORT_A_DATA_DIRECTION]) | (m_read_pa() & m_register[PORT_A_DATA_DIRECTION]); break; case PORT_B_DATA: - data = m_read_pb(0); + // TODO: take data path polarity into account + data = m_output[PORT_B]; + if (m_register[PORT_B_DATA_DIRECTION] != 0) + data = (data & ~m_register[PORT_B_DATA_DIRECTION]) | (m_read_pb() & m_register[PORT_B_DATA_DIRECTION]); break; case PORT_C_DATA: - data = 0xf0 | (m_read_pc(0) & 0x0f); + // TODO: take data path polarity into account + data = 0xf0 | (m_read_pc() & 0x0f); break; case COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE: @@ -340,17 +347,17 @@ void cio_base_device::write_register(offs_t offset, u8 data) case PORT_C_DATA_PATH_POLARITY: LOG("%s CIO Port C Data Path Polarity: %02x\n", machine().describe_context(), data); - m_register[offset] = data; + m_register[offset] = data & 0x0f; break; case PORT_C_DATA_DIRECTION: LOG("%s CIO Port C Data Direction: %02x\n", machine().describe_context(), data); - m_register[offset] = data; + m_register[offset] = data & 0x0f; break; case PORT_C_SPECIAL_IO_CONTROL: LOG("%s CIO Port C Special I/O Control: %02x\n", machine().describe_context(), data); - m_register[offset] = data; + m_register[offset] = data & 0x0f; break; case PORT_A_COMMAND_AND_STATUS: @@ -422,11 +429,15 @@ void cio_base_device::write_register(offs_t offset, u8 data) break; case PORT_A_DATA: - m_write_pa((offs_t)0, data); + // TODO: take data path polarity into account + m_output[PORT_A] = data; + m_write_pa(data); break; case PORT_B_DATA: - m_write_pb((offs_t)0, data); + // TODO: take data path polarity into account + m_output[PORT_B] = data; + m_write_pb(data); break; case PORT_C_DATA: @@ -435,7 +446,8 @@ void cio_base_device::write_register(offs_t offset, u8 data) m_output[PORT_C] = (m_output[PORT_C] & mask) | ((data & 0x0f) & (mask ^ 0xff)); - m_write_pc((offs_t)0, m_output[PORT_C]); + // TODO: take data path polarity into account + m_write_pc(m_output[PORT_C]); } break; @@ -862,6 +874,9 @@ void cio_base_device::device_reset() m_register[PORT_A_COMMAND_AND_STATUS] = PCS_ORE; m_register[PORT_B_COMMAND_AND_STATUS] = PCS_ORE; m_register[CURRENT_VECTOR] = 0xff; + m_register[PORT_A_DATA_DIRECTION] = 0xff; + m_register[PORT_B_DATA_DIRECTION] = 0xff; + m_register[PORT_C_DATA_DIRECTION] = 0x0f; check_interrupt(); }