From dd73e03c08b6e6058d55b73a6557f4c3d1355248 Mon Sep 17 00:00:00 2001 From: r09 Date: Wed, 7 Oct 2020 18:20:32 +0200 Subject: [PATCH] fmtowns: add devices for the SCSI card slot and the FMT-121 card (#7306) * fmtowns: add a SCSI card slot for the original models - Add a slot device for the Model 1/2 dedicated SCSI slot - Add a device for the FMT-121 SCSI Card - Modify the I/O maps and machine configurations so the slot and the integrated controller don't overlap --- scripts/src/bus.lua | 14 +++ scripts/target/mame/mess.lua | 1 + src/devices/bus/fmt_scsi/fmt121.cpp | 150 ++++++++++++++++++++++++ src/devices/bus/fmt_scsi/fmt121.h | 50 ++++++++ src/devices/bus/fmt_scsi/fmt_scsi.cpp | 158 ++++++++++++++++++++++++++ src/devices/bus/fmt_scsi/fmt_scsi.h | 98 ++++++++++++++++ src/mame/drivers/fmtowns.cpp | 48 ++++---- src/mame/includes/fmtowns.h | 7 +- 8 files changed, 504 insertions(+), 22 deletions(-) create mode 100644 src/devices/bus/fmt_scsi/fmt121.cpp create mode 100644 src/devices/bus/fmt_scsi/fmt121.h create mode 100644 src/devices/bus/fmt_scsi/fmt_scsi.cpp create mode 100644 src/devices/bus/fmt_scsi/fmt_scsi.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 54550c06341..f54599e7837 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1115,6 +1115,20 @@ if (BUSES["EP64"]~=null) then end +--------------------------------------------------- +-- +--@src/devices/bus/fmt_scsi/fmt_scsi.h,BUSES["FMT_SCSI"] = true +--------------------------------------------------- + +if (BUSES["FMT_SCSI"]~=null) then + files { + MAME_DIR .. "src/devices/bus/fmt_scsi/fmt_scsi.cpp", + MAME_DIR .. "src/devices/bus/fmt_scsi/fmt_scsi.h", + MAME_DIR .. "src/devices/bus/fmt_scsi/fmt121.cpp", + MAME_DIR .. "src/devices/bus/fmt_scsi/fmt121.h", + } +end + --------------------------------------------------- -- --@src/devices/bus/gamate/slot.h,BUSES["GAMATE"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 533d5cf0712..82f6bfc26ea 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -841,6 +841,7 @@ BUSES["ELECTRON"] = true BUSES["ELECTRON_CART"] = true BUSES["EP64"] = true BUSES["EPSON_SIO"] = true +BUSES["FMT_SCSI"] = true BUSES["GAMATE"] = true BUSES["GAMEBOY"] = true BUSES["GAMEGEAR"] = true diff --git a/src/devices/bus/fmt_scsi/fmt121.cpp b/src/devices/bus/fmt_scsi/fmt121.cpp new file mode 100644 index 00000000000..34f784115a0 --- /dev/null +++ b/src/devices/bus/fmt_scsi/fmt121.cpp @@ -0,0 +1,150 @@ +// license:BSD-3-Clause +// copyright-holders:r09 +/**************************************************************************** + + Fujitsu FMT-121 SCSI Card + + An expansion card for the dedicated SCSI card slot on the FM Towns + Model 1 and 2 computers. It contains a Fujitsu MB673522U SCSI controller + and an external 50-pin Centronics connector. + + ||||||||||||||||||||| ++-------------------------| |-------------------------+ +| CN1 +-------------------+ | +| | +| 74LS04N | +| 74LS14N 74LS240N SN74LS06N | +| MB413 | +| MB463 | +| 74AS00N | +| +-----------+ | +| MB463 | | | +| | MB673522U | MB412 | +| +-----------+ | +| MB463 74LS240N | +| CN3 | +| .......................................... | +| . . | +| .......................................... | +| CN2 | +| +----------------------------------------+ | +| | | | ++--------------| |---------------+ + |||||||||||||||||||||||||||||||||||||||||| + + CN1: 30-pin MFC-30LFD DIP connector + CN2: 50-pin Centronics connector + CN3: solder pads for internal 50-pin connector (not present) + +****************************************************************************/ + +#include "emu.h" +#include "fmt121.h" + +#include "bus/scsi/scsi.h" +#include "bus/scsi/scsihd.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(FMT121, fmt121_device, "fmt121", "FMT-121 SCSI Card") + +//************************************************************************** +// DEVICE DEFINITION +//************************************************************************** + +//------------------------------------------------- +// fmt121_device - construction +//------------------------------------------------- + +fmt121_device::fmt121_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, FMT121, tag, owner, clock) + , fmt_scsi_card_interface(mconfig, *this) + , m_scsi_ctlr(*this, "fmscsi") +{ +} + + +//------------------------------------------------- +// device_add_mconfig - add device-specific +// machine configuration +//------------------------------------------------- + +void fmt121_device::device_add_mconfig(machine_config &config) +{ + scsi_port_device &scsi(SCSI_PORT(config, "scsi", 0)); + scsi.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0)); + scsi.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1)); + scsi.set_slot_device(3, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_2)); + scsi.set_slot_device(4, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_3)); + scsi.set_slot_device(5, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4)); + + FMSCSI(config, m_scsi_ctlr, 0); + m_scsi_ctlr->set_scsi_port("scsi"); + m_scsi_ctlr->irq_handler().set(FUNC(fmt121_device::irq_w)); + m_scsi_ctlr->drq_handler().set(FUNC(fmt121_device::drq_w)); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void fmt121_device::device_start() +{ +} + +//************************************************************************** +// FMT121 INTERFACE +//************************************************************************** + +//------------------------------------------------- +// fmt_scsi_read - I/O read access +//------------------------------------------------- + +u8 fmt121_device::fmt_scsi_read(offs_t offset) +{ + return m_scsi_ctlr->fmscsi_r(offset); +} + + +//------------------------------------------------- +// fmt_scsi_write - I/O write access +//------------------------------------------------- + +void fmt121_device::fmt_scsi_write(offs_t offset, u8 data) +{ + m_scsi_ctlr->fmscsi_w(offset, data); +} + +//------------------------------------------------- +// fmt_scsi_data_read - data read access +//------------------------------------------------- + +u8 fmt121_device::fmt_scsi_data_read() +{ + return m_scsi_ctlr->fmscsi_data_r(); +} + +//------------------------------------------------- +// fmt_scsi_data_write - data write access +//------------------------------------------------- + +void fmt121_device::fmt_scsi_data_write(u8 data) +{ + m_scsi_ctlr->fmscsi_data_w(data); +} + + +void fmt121_device::irq_w(int state) +{ + m_slot->irq_w(state); +} + + +void fmt121_device::drq_w(int state) +{ + m_slot->drq_w(state); +} diff --git a/src/devices/bus/fmt_scsi/fmt121.h b/src/devices/bus/fmt_scsi/fmt121.h new file mode 100644 index 00000000000..9b80b2c70f1 --- /dev/null +++ b/src/devices/bus/fmt_scsi/fmt121.h @@ -0,0 +1,50 @@ +// license:BSD-3-Clause +// copyright-holders:r09 + +#ifndef MAME_BUS_FMT_SCSI_FMT121_H +#define MAME_BUS_FMT_SCSI_FMT121_H + +#pragma once + +#include "fmt_scsi.h" + +#include "machine/fm_scsi.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> fmt121_device + +class fmt121_device : public device_t, public fmt_scsi_card_interface +{ +public: + // device type constructor + fmt121_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + + // fmt_scsi_card_interface overrides + virtual u8 fmt_scsi_read(offs_t offset) override; + virtual void fmt_scsi_write(offs_t offset, u8 data) override; + + virtual u8 fmt_scsi_data_read(void) override; + virtual void fmt_scsi_data_write(u8 data) override; + +private: + + required_device m_scsi_ctlr; + + void irq_w(int state); + void drq_w(int state); + +}; + +// device type declaration +DECLARE_DEVICE_TYPE(FMT121, fmt121_device) + +#endif // MAME_BUS_FMT_SCSI_FMT121_H diff --git a/src/devices/bus/fmt_scsi/fmt_scsi.cpp b/src/devices/bus/fmt_scsi/fmt_scsi.cpp new file mode 100644 index 00000000000..b5d62fb3577 --- /dev/null +++ b/src/devices/bus/fmt_scsi/fmt_scsi.cpp @@ -0,0 +1,158 @@ +// license:BSD-3-Clause +// copyright-holders:r09 +/**************************************************************************** + + Fujitsu FM Towns SCSI card slot + + This is a dedicated 30-pin slot for the FMT-121 SCSI Card. It is only + present on the Model 1 and 2; all later models integrate the SCSI + controller directly on the motherboard. + +****************************************************************************/ + +#include "emu.h" +#include "fmt_scsi.h" + +#include "fmt121.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(FMT_SCSI_SLOT, fmt_scsi_slot_device, "fmt_scsi_slot", "FM Towns SCSI card slot") + +//************************************************************************** +// FMT_SCSI SLOT DEVICE +//************************************************************************** + +//------------------------------------------------- +// fmt_scsi_slot_device - construction +//------------------------------------------------- + +fmt_scsi_slot_device::fmt_scsi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, FMT_SCSI_SLOT, tag, owner, clock) + , device_single_card_slot_interface(mconfig, *this) + , m_card(nullptr) + , m_irq_handler(*this) + , m_drq_handler(*this) +{ +} + + +//------------------------------------------------- +// device_resolve_objects - resolve objects that +// may be needed for other devices to set +// initial conditions at start time +//------------------------------------------------- + +void fmt_scsi_slot_device::device_resolve_objects() +{ + m_card = get_card_device(); + if (m_card != nullptr) + m_card->m_slot = this; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void fmt_scsi_slot_device::device_start() +{ + m_irq_handler.resolve_safe(); + m_drq_handler.resolve_safe(); +} + + +//------------------------------------------------- +// read - I/O read access +//------------------------------------------------- + +u8 fmt_scsi_slot_device::read(address_space &space, offs_t offset) +{ + if (m_card) + return m_card->fmt_scsi_read(offset); + else + return space.unmap(); +} + + +//------------------------------------------------- +// write - I/O write access +//------------------------------------------------- + +void fmt_scsi_slot_device::write(offs_t offset, u8 data) +{ + if (m_card) + m_card->fmt_scsi_write(offset, data); +} + +//------------------------------------------------- +// data_read - data read access +//------------------------------------------------- + +u8 fmt_scsi_slot_device::data_read() +{ + if (m_card) + return m_card->fmt_scsi_data_read(); + else + return 0; +} + +//------------------------------------------------- +// data_write - data write access +//------------------------------------------------- + +void fmt_scsi_slot_device::data_write(u8 data) +{ + if (m_card) + m_card->fmt_scsi_data_write(data); +} + +void fmt_scsi_slot_device::irq_w(int state) +{ + m_irq_handler(state); +} + +void fmt_scsi_slot_device::drq_w(int state) +{ + m_drq_handler(state); +} + +//************************************************************************** +// FMT_SCSI CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// fmt_scsi_card_interface - construction +//------------------------------------------------- + +fmt_scsi_card_interface::fmt_scsi_card_interface(const machine_config &mconfig, device_t &device) + : device_interface(device, "fmtscsicard") + , m_slot(nullptr) +{ +} + + +//------------------------------------------------- +// interface_pre_start - called before the +// device's own start function +//------------------------------------------------- + +void fmt_scsi_card_interface::interface_pre_start() +{ + if (!m_slot) + throw device_missing_dependencies(); +} + + +//------------------------------------------------- +// fmt_scsi_default_devices - add standard options +// for main slots +//------------------------------------------------- + +void fmt_scsi_default_devices(device_slot_interface &device) +{ + device.option_add("fmt121", FMT121); +} diff --git a/src/devices/bus/fmt_scsi/fmt_scsi.h b/src/devices/bus/fmt_scsi/fmt_scsi.h new file mode 100644 index 00000000000..549b1047f4c --- /dev/null +++ b/src/devices/bus/fmt_scsi/fmt_scsi.h @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:r09 +/********************************************************************** + + Fujitsu FM Towns SCSI card slot + +**********************************************************************/ + +#ifndef MAME_BUS_FMT_SCSI_FMT_SCSI_H +#define MAME_BUS_FMT_SCSI_FMT_SCSI_H + +#pragma once + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward declarations +class fmt_scsi_card_interface; + +// ======================> fmt_scsi_slot_device + +class fmt_scsi_slot_device : public device_t, public device_single_card_slot_interface +{ + friend class fmt_scsi_card_interface; + +public: + // construction/destruction + template + fmt_scsi_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) + : fmt_scsi_slot_device(mconfig, tag, owner, 0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(false); + } + + fmt_scsi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + auto irq_handler() { return m_irq_handler.bind(); } + auto drq_handler() { return m_drq_handler.bind(); } + + u8 read(address_space &space, offs_t offset); + void write(offs_t offset, u8 data); + + uint8_t data_read(void); + void data_write(uint8_t data); + + void irq_w(int state); + void drq_w(int state); + +protected: + // device-specific overrides + virtual void device_resolve_objects() override; + virtual void device_start() override; + +private: + fmt_scsi_card_interface *m_card; + + devcb_write_line m_irq_handler; + devcb_write_line m_drq_handler; + +}; + + +// ======================> fmt_scsi_card_interface + +class fmt_scsi_card_interface : public device_interface +{ + friend class fmt_scsi_slot_device; + +protected: + // construction/destruction + fmt_scsi_card_interface(const machine_config &mconfig, device_t &device); + + // required overrides + virtual u8 fmt_scsi_read(offs_t offset) = 0; + virtual void fmt_scsi_write(offs_t offset, u8 data) = 0; + + virtual u8 fmt_scsi_data_read(void) = 0; + virtual void fmt_scsi_data_write(u8 data) = 0; + + fmt_scsi_slot_device *m_slot; + +private: + virtual void interface_pre_start() override; + +}; + + +// device type definition +DECLARE_DEVICE_TYPE(FMT_SCSI_SLOT, fmt_scsi_slot_device) + +void fmt_scsi_default_devices(device_slot_interface &device); + +#endif // MAME_BUS_FMT_SCSI_FMT_SCSI_H diff --git a/src/mame/drivers/fmtowns.cpp b/src/mame/drivers/fmtowns.cpp index 9bac53acb6b..07044988df3 100644 --- a/src/mame/drivers/fmtowns.cpp +++ b/src/mame/drivers/fmtowns.cpp @@ -2012,16 +2012,6 @@ WRITE_LINE_MEMBER(towns_state::rtc_busy_w) } // SCSI controller - I/O ports 0xc30 and 0xc32 -uint16_t towns_state::towns_scsi_dma_r() -{ - return m_scsi->fmscsi_data_r(); -} - -void towns_state::towns_scsi_dma_w(uint16_t data) -{ - m_scsi->fmscsi_data_w(data & 0xff); -} - WRITE_LINE_MEMBER(towns_state::towns_scsi_irq) { m_pic_slave->ir0_w(state); @@ -2374,6 +2364,13 @@ void towns_state::towns_io(address_map &map) map(0xff80, 0xffff).rw(FUNC(towns_state::towns_video_cff80_r), FUNC(towns_state::towns_video_cff80_w)); } +void towns_state::towns_1g_io(address_map &map) +{ + // For the first generation FM Towns with a SCSI card slot + towns_io(map); + map(0x0c30, 0x0c37).rw(m_scsi_slot, FUNC(fmt_scsi_slot_device::read), FUNC(fmt_scsi_slot_device::write)).umask32(0x00ff00ff); +} + void towns_state::towns2_io(address_map &map) { // For FM Towns II models with integrated SCSI controller @@ -2831,7 +2828,7 @@ void towns_state::towns_base(machine_config &config) /* basic machine hardware */ I386(config, m_maincpu, 16000000); m_maincpu->set_addrmap(AS_PROGRAM, &towns_state::towns_mem); - m_maincpu->set_addrmap(AS_IO, &towns_state::towns_io); + m_maincpu->set_addrmap(AS_IO, &towns_state::towns_1g_io); m_maincpu->set_vblank_int("screen", FUNC(towns_state::towns_vsync_irq)); m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb)); //MCFG_MACHINE_RESET_OVERRIDE(towns_state,towns) @@ -2960,6 +2957,15 @@ void towns_state::towns(machine_config &config) { towns_base(config); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); + + FMT_SCSI_SLOT(config, m_scsi_slot, fmt_scsi_default_devices, nullptr); + m_scsi_slot->irq_handler().set(FUNC(towns_state::towns_scsi_irq)); + m_scsi_slot->drq_handler().set(FUNC(towns_state::towns_scsi_drq)); + + m_dma[0]->dma_read_callback<1>().set(m_scsi_slot, FUNC(fmt_scsi_slot_device::data_read)); + m_dma[0]->dma_write_callback<1>().set(m_scsi_slot, FUNC(fmt_scsi_slot_device::data_write)); + m_dma[1]->dma_read_callback<1>().set(m_scsi_slot, FUNC(fmt_scsi_slot_device::data_read)); + m_dma[1]->dma_write_callback<1>().set(m_scsi_slot, FUNC(fmt_scsi_slot_device::data_write)); } void towns16_state::townsux(machine_config &config) @@ -2984,10 +2990,10 @@ void towns16_state::townsux(machine_config &config) m_scsi->irq_handler().set(FUNC(towns16_state::towns_scsi_irq)); m_scsi->drq_handler().set(FUNC(towns16_state::towns_scsi_drq)); - m_dma[0]->dma_read_callback<1>().set(FUNC(towns16_state::towns_scsi_dma_r)); - m_dma[0]->dma_write_callback<1>().set(FUNC(towns16_state::towns_scsi_dma_w)); - m_dma[1]->dma_read_callback<1>().set(FUNC(towns16_state::towns_scsi_dma_r)); - m_dma[1]->dma_write_callback<1>().set(FUNC(towns16_state::towns_scsi_dma_w)); + m_dma[0]->dma_read_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_r)); + m_dma[0]->dma_write_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_w)); + m_dma[1]->dma_read_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_r)); + m_dma[1]->dma_write_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_w)); // 2 MB onboard, one SIMM slot with 2-8 MB m_ram->set_default_size("2M").set_extra_options("4M,6M,10M"); @@ -2997,7 +3003,7 @@ void towns16_state::townsux(machine_config &config) void towns_state::townssj(machine_config &config) { - towns(config); + towns_base(config); I486(config.replace(), m_maincpu, 66000000); m_maincpu->set_addrmap(AS_PROGRAM, &towns_state::towns_mem); @@ -3017,13 +3023,15 @@ void towns_state::townssj(machine_config &config) m_scsi->irq_handler().set(FUNC(towns_state::towns_scsi_irq)); m_scsi->drq_handler().set(FUNC(towns_state::towns_scsi_drq)); - m_dma[0]->dma_read_callback<1>().set(FUNC(towns_state::towns_scsi_dma_r)); - m_dma[0]->dma_write_callback<1>().set(FUNC(towns_state::towns_scsi_dma_w)); - m_dma[1]->dma_read_callback<1>().set(FUNC(towns_state::towns_scsi_dma_r)); - m_dma[1]->dma_write_callback<1>().set(FUNC(towns_state::towns_scsi_dma_w)); + m_dma[0]->dma_read_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_r)); + m_dma[0]->dma_write_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_w)); + m_dma[1]->dma_read_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_r)); + m_dma[1]->dma_write_callback<1>().set(m_scsi, FUNC(fmscsi_device::fmscsi_data_w)); // 4 MB (SJ2/SJ2A) or 8 MB (SJ26/SJ53) onboard, 2 SIMM slots with 4-32 MB each m_ram->set_default_size("8M").set_extra_options("4M,12M,16M,20M,24M,28M,32M,36M,40M,44M,48M,52M,56M,68M,72M"); + + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); } void towns_state::townshr(machine_config &config) diff --git a/src/mame/includes/fmtowns.h b/src/mame/includes/fmtowns.h index 7197a102ea9..525e4ce429f 100644 --- a/src/mame/includes/fmtowns.h +++ b/src/mame/includes/fmtowns.h @@ -26,6 +26,8 @@ #include "bus/generic/carts.h" #include "bus/generic/slot.h" #include "bus/rs232/rs232.h" +#include "bus/fmt_scsi/fmt_scsi.h" +#include "bus/fmt_scsi/fmt121.h" #include "formats/fmtowns_dsk.h" @@ -111,6 +113,7 @@ class towns_state : public driver_device , m_dma_1(*this, "dma_1") , m_cdrom(*this, "cdrom") , m_cdda(*this, "cdda") + , m_scsi_slot(*this, "scsislot") , m_bank_cb000_r(*this, "bank_cb000_r") , m_bank_cb000_w(*this, "bank_cb000_w") , m_bank_f8000_r(*this, "bank_f8000_r") @@ -150,6 +153,7 @@ protected: void pcm_mem(address_map &map); void towns16_io(address_map &map); void towns_io(address_map &map); + void towns_1g_io(address_map &map); void towns2_io(address_map &map); void townsux_io(address_map &map); void towns_mem(address_map &map); @@ -167,8 +171,6 @@ protected: DECLARE_WRITE_LINE_MEMBER(towns_scsi_irq); DECLARE_WRITE_LINE_MEMBER(towns_scsi_drq); - uint16_t towns_scsi_dma_r(); - void towns_scsi_dma_w(uint16_t data); private: /* devices */ @@ -187,6 +189,7 @@ private: required_device m_dma_1; required_device m_cdrom; required_device m_cdda; + optional_device m_scsi_slot; required_memory_bank m_bank_cb000_r; required_memory_bank m_bank_cb000_w;