summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/rc2014/ide.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/rc2014/ide.cpp')
-rw-r--r--src/devices/bus/rc2014/ide.cpp295
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")