diff options
author | 2022-05-17 12:56:38 +1000 | |
---|---|---|
committer | 2022-05-17 12:56:38 +1000 | |
commit | b91e4cd32ed17c42e5b7c1d40e5f3022349581db (patch) | |
tree | a4e3b7eb55b64b1d0768da1f3797e27a8570ee22 /src/devices/bus/rc2014/ide.cpp | |
parent | 17f0347abdc3e4c147133e6c0ff018352f5f96cc (diff) | |
parent | 7282130cc31b7b518f5be5bc17e07cdab760d7eb (diff) |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/devices/bus/rc2014/ide.cpp')
-rw-r--r-- | src/devices/bus/rc2014/ide.cpp | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/src/devices/bus/rc2014/ide.cpp b/src/devices/bus/rc2014/ide.cpp new file mode 100644 index 00000000000..e81a168cba6 --- /dev/null +++ b/src/devices/bus/rc2014/ide.cpp @@ -0,0 +1,295 @@ +// license:BSD-3-Clause +// copyright-holders:Miodrag Milanovic +/*************************************************************************** + + RC2014 IDE + +****************************************************************************/ + +#include "emu.h" +#include "ide.h" +#include "machine/i8255.h" +#include "bus/ata/ataintf.h" + +namespace { + +//************************************************************************** +// rc2014_ide_base +//************************************************************************** + +class rc2014_ide_base : public device_t, public device_rc2014_card_interface +{ +protected: + // construction/destruction + rc2014_ide_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + + uint8_t ppi_pa_r() { return m_data.b.l; } + uint8_t ppi_pb_r() { return m_data.b.h; } + void ppi_pa_w(uint8_t data) { m_data.b.l = data; } + void ppi_pb_w(uint8_t data) { m_data.b.h = data; } + virtual void ppi_pc_w(uint8_t data) = 0; + + // base-class members + required_device<ata_interface_device> m_ata; + required_device<i8255_device> m_ppi; + + PAIR16 m_data; + uint8_t m_prev; +}; + +rc2014_ide_base::rc2014_ide_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock) + , device_rc2014_card_interface(mconfig, *this) + , m_ata(*this, "ata") + , m_ppi(*this, "82c55") + , m_prev(0) +{ +} + +void rc2014_ide_base::device_start() +{ +} + +void rc2014_ide_base::device_add_mconfig(machine_config &config) +{ + I8255(config, m_ppi, 0); + m_ppi->in_pa_callback().set(FUNC(rc2014_ide_base::ppi_pa_r)); + m_ppi->in_pb_callback().set(FUNC(rc2014_ide_base::ppi_pb_r)); + m_ppi->out_pa_callback().set(FUNC(rc2014_ide_base::ppi_pa_w)); + m_ppi->out_pb_callback().set(FUNC(rc2014_ide_base::ppi_pb_w)); + m_ppi->out_pc_callback().set(FUNC(rc2014_ide_base::ppi_pc_w)); + + ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", "hdd", false); +} + +//************************************************************************** +// RC2014 82C55 IDE Interface +// Module author: Ed Brindley +//************************************************************************** + +class rc2014_82c55_ide_device : public rc2014_ide_base +{ +public: + // construction/destruction + rc2014_82c55_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + + void ppi_pc_w(uint8_t data) override; +private: + required_ioport m_sw; + required_ioport_array<4> m_jp; + + uint8_t m_da0; + uint8_t m_da1; + uint8_t m_dcs1; + uint8_t m_dior; +}; + +rc2014_82c55_ide_device::rc2014_82c55_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : rc2014_ide_base(mconfig, RC2014_82C55_IDE, tag, owner, clock) + , m_sw(*this, "SW1") + , m_jp(*this, "JP%u", 1U) +{ +} + +void rc2014_82c55_ide_device::device_reset() +{ + m_da0 = (m_jp[0]->read() == 1) ? 4 : 0; + m_dcs1 = (m_jp[1]->read() == 1) ? 0 : 4; + m_da1 = (m_jp[2]->read() == 1) ? 6 : 1; + m_dior = (m_jp[3]->read() == 1) ? 1 : 6; + + uint8_t base = m_sw->read(); // SW1 + // A15-A8 not connected + m_bus->installer(AS_IO)->install_readwrite_handler(base, base+0x03, 0, 0xff00, 0, read8sm_delegate(m_ppi, FUNC(i8255_device::read)), write8sm_delegate(m_ppi, FUNC(i8255_device::write))); +} + +void rc2014_82c55_ide_device::ppi_pc_w(uint8_t data) +{ + // On IDE connector DIOW and DIOR are inverted + // write is on falling and read on rising edge + uint8_t offset = BIT(data,2) << 2 | BIT(data,m_da1) << 1 | BIT(data,m_da0); + + if (BIT(data,3)) // DCS0 + { + if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW + { + m_ata->cs0_w(offset, m_data.w); + } + if (BIT(data,m_dior)==1 && BIT(m_prev,m_dior)==0) // DIOR + { + m_data.w = m_ata->cs0_r(offset); + } + } + if (BIT(data,m_dcs1)) // DCS1 + { + if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW + { + m_ata->cs1_w(offset, m_data.w); + } + if (BIT(data,m_dior)==1 && BIT(m_prev,m_dior)==0) // DIOR + { + m_data.w = m_ata->cs1_r(offset); + } + } + if (BIT(data,7)) // DRESET + { + // RESET IDE Disk + m_ata->reset(); + } + m_prev = data; + +} + +static INPUT_PORTS_START( rc2014_82c55_ide_jumpers ) + PORT_START("SW1") + PORT_DIPNAME(0x04, 0x00, "0x04") PORT_DIPLOCATION("Base Address:1") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x04, DEF_STR( On ) ) + PORT_DIPNAME(0x08, 0x00, "0x08") PORT_DIPLOCATION("Base Address:2") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x08, DEF_STR( On ) ) + PORT_DIPNAME(0x10, 0x00, "0x10") PORT_DIPLOCATION("Base Address:3") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x10, DEF_STR( On ) ) + PORT_DIPNAME(0x20, 0x20, "0x20") PORT_DIPLOCATION("Base Address:4") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x20, DEF_STR( On ) ) + PORT_DIPNAME(0x40, 0x00, "0x40") PORT_DIPLOCATION("Base Address:5") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x40, DEF_STR( On ) ) + PORT_DIPNAME(0x80, 0x00, "0x80") PORT_DIPLOCATION("Base Address:6") + PORT_DIPSETTING(0x00, DEF_STR( Off ) ) + PORT_DIPSETTING(0x80, DEF_STR( On ) ) + PORT_START("JP1") + PORT_CONFNAME( 0x1, 0x0, "DA0" ) + PORT_CONFSETTING( 0x0, "PC0" ) + PORT_CONFSETTING( 0x1, "PC4" ) + PORT_START("JP2") + PORT_CONFNAME( 0x1, 0x0, "DCS1" ) + PORT_CONFSETTING( 0x0, "PC4" ) + PORT_CONFSETTING( 0x1, "PC0" ) + PORT_START("JP3") + PORT_CONFNAME( 0x1, 0x0, "DA1" ) + PORT_CONFSETTING( 0x0, "PC1" ) + PORT_CONFSETTING( 0x1, "PC6" ) + PORT_START("JP4") + PORT_CONFNAME( 0x1, 0x0, "DIOR" ) + PORT_CONFSETTING( 0x0, "PC6" ) + PORT_CONFSETTING( 0x1, "PC1" ) + PORT_START("JP5") + PORT_CONFNAME( 0x1, 0x0, "Power" ) + PORT_CONFSETTING( 0x0, "Bus" ) + PORT_CONFSETTING( 0x1, "External" ) +INPUT_PORTS_END + +ioport_constructor rc2014_82c55_ide_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( rc2014_82c55_ide_jumpers ); +} + +//************************************************************************** +// RC2014 IDE Hard Drive Module +// Module author: Spencer Owen +// Based on design from Ed Brindley, but simplified +//************************************************************************** + +class rc2014_ide_hdd_device : public rc2014_ide_base +{ +public: + // construction/destruction + rc2014_ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + + void ppi_pc_w(uint8_t data) override; +private: + required_ioport m_jp; +}; + +rc2014_ide_hdd_device::rc2014_ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : rc2014_ide_base(mconfig, RC2014_IDE_HDD, tag, owner, clock) + , m_jp(*this, "J1") +{ +} + +void rc2014_ide_hdd_device::device_reset() +{ + uint8_t base = m_jp->read() << 3; + // A15-A8 are not connected, A7,A6 and A2 must be 0 + m_bus->installer(AS_IO)->install_readwrite_handler(base, base+0x03, 0, 0xff00, 0, read8sm_delegate(m_ppi, FUNC(i8255_device::read)), write8sm_delegate(m_ppi, FUNC(i8255_device::write))); +} + +void rc2014_ide_hdd_device::ppi_pc_w(uint8_t data) +{ + uint8_t offset = data & 7; + + if (BIT(data,3)) // DCS0 + { + if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW + { + m_ata->cs0_w(offset, m_data.w); + } + if (BIT(data,6)==1 && BIT(m_prev,6)==0) // DIOR + { + m_data.w = m_ata->cs0_r(offset); + } + } + if (BIT(data,4)) // DCS1 + { + if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW + { + m_ata->cs1_w(offset, m_data.w); + } + if (BIT(data,6)==1 && BIT(m_prev,6)==0) // DIOR + { + m_data.w = m_ata->cs1_r(offset); + } + } + if (BIT(data,7)) // DRESET + { + // RESET IDE Disk + m_ata->reset(); + } + m_prev = data; + +} + +static INPUT_PORTS_START( rc2014_ide_hdd_jumpers ) + PORT_START("J1") + PORT_CONFNAME( 0x7, 0x4, "Base Address" ) + PORT_CONFSETTING( 0x1, "0x08" ) + PORT_CONFSETTING( 0x2, "0x10" ) + PORT_CONFSETTING( 0x3, "0x18" ) + PORT_CONFSETTING( 0x4, "0x20" ) + PORT_CONFSETTING( 0x5, "0x28" ) + PORT_CONFSETTING( 0x6, "0x30" ) + PORT_CONFSETTING( 0x7, "0x38" ) + PORT_START("JP1") + PORT_CONFNAME( 0x1, 0x0, "Power" ) + PORT_CONFSETTING( 0x0, "Bus" ) + PORT_CONFSETTING( 0x1, "External" ) +INPUT_PORTS_END + +ioport_constructor rc2014_ide_hdd_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( rc2014_ide_hdd_jumpers ); +} + +} +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** +DEFINE_DEVICE_TYPE_PRIVATE(RC2014_82C55_IDE, device_rc2014_card_interface, rc2014_82c55_ide_device, "rc2014_82c55_ide", "RC2014 82C55 IDE Interface") +DEFINE_DEVICE_TYPE_PRIVATE(RC2014_IDE_HDD, device_rc2014_card_interface, rc2014_ide_hdd_device, "rc2014_ide_hdd", "RC2014 IDE Hard Drive Module") |