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
This commit is contained in:
r09 2020-10-07 18:20:32 +02:00 committed by GitHub
parent c552c38ac6
commit dd73e03c08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 504 additions and 22 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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<fmscsi_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

View File

@ -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<fmt_scsi_card_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);
}

View File

@ -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<fmt_scsi_card_interface>
{
friend class fmt_scsi_card_interface;
public:
// construction/destruction
template <typename T>
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

View File

@ -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)

View File

@ -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<upd71071_device> m_dma_1;
required_device<cdrom_image_device> m_cdrom;
required_device<cdda_device> m_cdda;
optional_device<fmt_scsi_slot_device> m_scsi_slot;
required_memory_bank m_bank_cb000_r;
required_memory_bank m_bank_cb000_w;