summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/apricot/expansion
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-03-26 11:13:37 +1100
committer Vas Crabb <vas@vastheman.com>2019-03-26 11:13:37 +1100
commit97b67170277437131adf6ed4d60139c172529e4f (patch)
tree7a5cbf608f191075f1612b1af15832c206a3fe2d /src/devices/bus/apricot/expansion
parentb380514764cf857469bae61c11143a19f79a74c5 (diff)
(nw) Clean up the mess on master
This effectively reverts b380514764cf857469bae61c11143a19f79a74c5 and c24473ddff715ecec2e258a6eb38960cf8c8e98e, restoring the state at 598cd5227223c3b04ca31f0dbc1981256d9ea3ff. Before pushing, please check that what you're about to push is sane. Check your local commit log and ensure there isn't anything out-of-place before pushing to mainline. When things like this happen, it wastes everyone's time. I really don't need this in a week when real work™ is busting my balls and I'm behind where I want to be with preparing for MAME release.
Diffstat (limited to 'src/devices/bus/apricot/expansion')
-rw-r--r--src/devices/bus/apricot/expansion/cards.cpp2
-rw-r--r--src/devices/bus/apricot/expansion/expansion.cpp25
-rw-r--r--src/devices/bus/apricot/expansion/expansion.h33
-rw-r--r--src/devices/bus/apricot/expansion/winchester.cpp254
-rw-r--r--src/devices/bus/apricot/expansion/winchester.h66
5 files changed, 344 insertions, 36 deletions
diff --git a/src/devices/bus/apricot/expansion/cards.cpp b/src/devices/bus/apricot/expansion/cards.cpp
index d2c35366e42..ef0243bf412 100644
--- a/src/devices/bus/apricot/expansion/cards.cpp
+++ b/src/devices/bus/apricot/expansion/cards.cpp
@@ -9,10 +9,12 @@
#include "emu.h"
#include "cards.h"
#include "ram.h"
+#include "winchester.h"
void apricot_expansion_cards(device_slot_interface &device)
{
device.option_add("128k", APRICOT_128K_RAM);
device.option_add("256k", APRICOT_256K_RAM);
device.option_add("512k", APRICOT_512K_RAM);
+ device.option_add("winchester", APRICOT_WINCHESTER);
}
diff --git a/src/devices/bus/apricot/expansion/expansion.cpp b/src/devices/bus/apricot/expansion/expansion.cpp
index 98141860782..5a89c9a8868 100644
--- a/src/devices/bus/apricot/expansion/expansion.cpp
+++ b/src/devices/bus/apricot/expansion/expansion.cpp
@@ -59,18 +59,16 @@ DEFINE_DEVICE_TYPE(APRICOT_EXPANSION_BUS, apricot_expansion_bus_device, "apricot
apricot_expansion_bus_device::apricot_expansion_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, APRICOT_EXPANSION_BUS, tag, owner, clock),
- m_program(nullptr),
- m_io(nullptr),
- m_program_iop(nullptr),
- m_io_iop(nullptr),
+ m_program(*this, finder_base::DUMMY_TAG, -1),
+ m_io(*this, finder_base::DUMMY_TAG, -1),
+ m_program_iop(*this, finder_base::DUMMY_TAG, -1),
+ m_io_iop(*this, finder_base::DUMMY_TAG, -1),
m_dma1_handler(*this),
m_dma2_handler(*this),
m_ext1_handler(*this),
m_ext2_handler(*this),
m_int2_handler(*this),
- m_int3_handler(*this),
- m_cpu(*this, finder_base::DUMMY_TAG),
- m_iop(*this, finder_base::DUMMY_TAG)
+ m_int3_handler(*this)
{
}
@@ -99,19 +97,6 @@ void apricot_expansion_bus_device::device_start()
}
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void apricot_expansion_bus_device::device_reset()
-{
- m_program = &m_cpu->space(AS_PROGRAM);
- m_io = &m_cpu->space(AS_IO);
-
- m_program_iop = &m_iop->space(AS_PROGRAM);
- m_io_iop = &m_iop->space(AS_IO);
-}
-
-//-------------------------------------------------
// add_card - add new card to our bus
//-------------------------------------------------
diff --git a/src/devices/bus/apricot/expansion/expansion.h b/src/devices/bus/apricot/expansion/expansion.h
index 85b0e47dc5e..93c529f24e3 100644
--- a/src/devices/bus/apricot/expansion/expansion.h
+++ b/src/devices/bus/apricot/expansion/expansion.h
@@ -89,16 +89,14 @@ class apricot_expansion_bus_device : public device_t
{
public:
// construction/destruction
- template <typename T, typename U>
- apricot_expansion_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag, U &&iop_tag)
- : apricot_expansion_bus_device(mconfig, tag, owner, (uint32_t)0)
- {
- m_cpu.set_tag(std::forward<T>(cpu_tag));
- m_iop.set_tag(std::forward<U>(iop_tag));
- }
apricot_expansion_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~apricot_expansion_bus_device();
+ template <typename T> void set_program_space(T &&tag, int spacenum) { m_program.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_program_iop_space(T &&tag, int spacenum) { m_program_iop.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_io_iop_space(T &&tag, int spacenum) { m_io_iop.set_tag(std::forward<T>(tag), spacenum); }
+
auto dma1() { return m_dma1_handler.bind(); }
auto dma2() { return m_dma2_handler.bind(); }
auto ext1() { return m_ext1_handler.bind(); }
@@ -118,19 +116,26 @@ public:
void install_ram(offs_t addrstart, offs_t addrend, void *baseptr);
+ template<typename T> void install_io_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
+ {
+ m_io->install_device(addrstart, addrend, device, map, unitmask);
+
+ if (m_io_iop)
+ m_io_iop->install_device(addrstart, addrend, device, map, unitmask);
+ }
+
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
private:
simple_list<device_apricot_expansion_card_interface> m_dev;
// address spaces we have access to
- address_space *m_program;
- address_space *m_io;
- address_space *m_program_iop;
- address_space *m_io_iop;
+ required_address_space m_program;
+ required_address_space m_io;
+ optional_address_space m_program_iop;
+ optional_address_space m_io_iop;
devcb_write_line m_dma1_handler;
devcb_write_line m_dma2_handler;
@@ -138,10 +143,6 @@ private:
devcb_write_line m_ext2_handler;
devcb_write_line m_int2_handler;
devcb_write_line m_int3_handler;
-
- // configuration
- required_device<cpu_device> m_cpu;
- required_device<cpu_device> m_iop;
};
// device type definition
diff --git a/src/devices/bus/apricot/expansion/winchester.cpp b/src/devices/bus/apricot/expansion/winchester.cpp
new file mode 100644
index 00000000000..f16752b3ede
--- /dev/null
+++ b/src/devices/bus/apricot/expansion/winchester.cpp
@@ -0,0 +1,254 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best
+/***************************************************************************
+
+ ACT Apricot Winchester Controller
+
+ Version Rev 9
+
+***************************************************************************/
+
+#include "emu.h"
+#include "winchester.h"
+#include "imagedev/harddriv.h"
+
+//#define LOG_GENERAL (1U << 0)
+#define LOG_REGS (1U << 1)
+#define LOG_DATA (1U << 2)
+
+//#define VERBOSE (LOG_REGS)
+//#define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__)
+#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(APRICOT_WINCHESTER, apricot_winchester_device, "apricot_winchester", "Apricot Winchester Controller Board")
+
+//-------------------------------------------------
+// regs - controller register i/o map
+//-------------------------------------------------
+
+void apricot_winchester_device::regs(address_map &map)
+{
+ map(0x0e0, 0x0ef).rw(m_hdc, FUNC(wd1010_device::read), FUNC(wd1010_device::write)).umask16(0x00ff);
+ map(0x1e0, 0x1e0).rw(FUNC(apricot_winchester_device::int_r), FUNC(apricot_winchester_device::head_w<0>)).umask16(0x00ff);
+ map(0x1e2, 0x1e2).w(FUNC(apricot_winchester_device::head_w<1>)).umask16(0x00ff);
+ map(0x1e4, 0x1e4).w(FUNC(apricot_winchester_device::head_w<2>)).umask16(0x00ff);
+ map(0x1e6, 0x1e6).w(FUNC(apricot_winchester_device::drive_w<0>)).umask16(0x00ff);
+ map(0x1e8, 0x1e8).w(FUNC(apricot_winchester_device::xferd_w)).umask16(0x00ff); // transferred
+ map(0x1ea, 0x1ea).w(FUNC(apricot_winchester_device::hbcr_w)).umask16(0x00ff); // host buffer clear register
+ map(0x1ec, 0x1ec).w(FUNC(apricot_winchester_device::clksel_w)).umask16(0x00ff); // buffer chip read/write clock select (host or wdc)
+ map(0x1ee, 0x1ee).w(FUNC(apricot_winchester_device::drive_w<1>)).umask16(0x00ff);
+ map(0x1f0, 0x1f0).rw(FUNC(apricot_winchester_device::data_r), FUNC(apricot_winchester_device::data_w)).umask16(0x00ff);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void apricot_winchester_device::device_add_mconfig(machine_config &config)
+{
+ WD1010(config, m_hdc, 5000000);
+ m_hdc->out_intrq_callback().set(FUNC(apricot_winchester_device::hdc_intrq_w));
+ m_hdc->in_data_callback().set(FUNC(apricot_winchester_device::hdc_data_r));
+ m_hdc->out_data_callback().set(FUNC(apricot_winchester_device::hdc_data_w));
+
+ HARDDISK(config, "hdc:0", 0);
+ HARDDISK(config, "hdc:1", 0);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// apricot_winchester_device - constructor
+//-------------------------------------------------
+
+apricot_winchester_device::apricot_winchester_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, APRICOT_WINCHESTER, tag, owner, clock),
+ device_apricot_expansion_card_interface(mconfig, *this),
+ m_hdc(*this, "hdc"),
+ m_ram_ptr(0),
+ m_int(0),
+ m_drive(0),
+ m_head(0),
+ m_hbcr(0),
+ m_clksel(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void apricot_winchester_device::device_start()
+{
+ // allocate 8-bit buffer ram (8k)
+ m_ram = std::make_unique<uint8_t[]>(0x2000);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x2000);
+ save_item(NAME(m_ram_ptr));
+ save_item(NAME(m_int));
+ save_item(NAME(m_drive));
+ save_item(NAME(m_head));
+ save_item(NAME(m_hbcr));
+ save_item(NAME(m_clksel));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void apricot_winchester_device::device_reset()
+{
+ m_bus->install_io_device(0x000, 0xfff, *this, &apricot_winchester_device::regs);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+WRITE_LINE_MEMBER( apricot_winchester_device::hdc_intrq_w )
+{
+ LOGREGS("hdc_intrq_w: %d\n", state);
+
+ m_int = state;
+ m_bus->int2_w(state);
+}
+
+READ8_MEMBER( apricot_winchester_device::hdc_data_r )
+{
+ uint8_t data = 0xff;
+
+ if (m_clksel == 1)
+ {
+ LOGDATA("hdc_data_r[%04x]\n", m_ram_ptr);
+
+ data = m_ram[m_ram_ptr];
+ if (m_ram_ptr < 0x1fff)
+ m_ram_ptr++;
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER( apricot_winchester_device::hdc_data_w )
+{
+ if (m_clksel == 1)
+ {
+ LOGDATA("hdc_data_w[%04x] = %02x\n", m_ram_ptr, data);
+
+ m_ram[m_ram_ptr] = data;
+ if (m_ram_ptr < 0x1fff)
+ m_ram_ptr++;
+ }
+}
+
+READ8_MEMBER( apricot_winchester_device::int_r )
+{
+ return m_int;
+}
+
+template<int N>
+WRITE8_MEMBER( apricot_winchester_device::head_w )
+{
+ m_head = (m_head & ~(1 << N)) | (BIT(data, 0) << N);
+ LOGREGS("Select head: %d\n", m_head);
+}
+
+template<int N>
+WRITE8_MEMBER( apricot_winchester_device::drive_w )
+{
+ m_drive = (m_drive & ~(1 << N)) | (BIT(data, 0) << N);
+ LOGREGS("Select drive: %d\n", m_drive);
+
+ // forward drive status to the hdc
+ harddisk_image_device *drive = nullptr;
+
+ switch (m_drive)
+ {
+ case 0:
+ drive = nullptr;
+ break;
+ case 1:
+ drive = m_hdc->subdevice<harddisk_image_device>("0");
+ break;
+ case 2:
+ drive = m_hdc->subdevice<harddisk_image_device>("1");
+ break;
+ case 3:
+ // both (invalid?)
+ drive = nullptr;
+ break;
+ }
+
+ m_hdc->drdy_w(drive != nullptr && drive->exists());
+}
+
+WRITE8_MEMBER( apricot_winchester_device::xferd_w )
+{
+ LOGREGS("xferd_w: %02x\n", data);
+
+ m_hdc->brdy_w(BIT(data, 0));
+}
+
+WRITE8_MEMBER( apricot_winchester_device::hbcr_w )
+{
+ LOGREGS("hbcr_w: %02x\n", data);
+
+ // reset ram pointer on high->low transition
+ if (m_hbcr == 1 && data == 0)
+ m_ram_ptr = 0;
+
+ m_hbcr = BIT(data, 0);
+}
+
+WRITE8_MEMBER( apricot_winchester_device::clksel_w )
+{
+ LOGREGS("clksel_w: %02x\n", data);
+
+ m_clksel = BIT(data, 0);
+}
+
+READ8_MEMBER( apricot_winchester_device::data_r )
+{
+ uint8_t data = 0xff;
+
+ if (m_clksel == 0)
+ {
+ LOGDATA("data_r[%04x]\n", m_ram_ptr);
+
+ data = m_ram[m_ram_ptr];
+
+ // wrap or stop at end?
+ if (m_ram_ptr < 0x1fff)
+ m_ram_ptr++;
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER( apricot_winchester_device::data_w )
+{
+ if (m_clksel == 0)
+ {
+ LOGDATA("data_w[%04x] = %02x\n", m_ram_ptr, data);
+
+ m_ram[m_ram_ptr] = data;
+
+ // wrap or stop at end?
+ if (m_ram_ptr < 0x1fff)
+ m_ram_ptr++;
+ }
+}
diff --git a/src/devices/bus/apricot/expansion/winchester.h b/src/devices/bus/apricot/expansion/winchester.h
new file mode 100644
index 00000000000..c4c82ab0585
--- /dev/null
+++ b/src/devices/bus/apricot/expansion/winchester.h
@@ -0,0 +1,66 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best
+/***************************************************************************
+
+ ACT Apricot Winchester Controller
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_WINCHESTER_H
+#define MAME_BUS_APRICOT_WINCHESTER_H
+
+#pragma once
+
+#include "expansion.h"
+#include "machine/wd1010.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> apricot_winchester_device
+
+class apricot_winchester_device : public device_t, public device_apricot_expansion_card_interface
+{
+public:
+ // construction/destruction
+ apricot_winchester_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(hdc_intrq_w);
+ DECLARE_READ8_MEMBER(hdc_data_r);
+ DECLARE_WRITE8_MEMBER(hdc_data_w);
+ DECLARE_READ8_MEMBER(int_r);
+ template<int N> DECLARE_WRITE8_MEMBER(head_w);
+ template<int N> DECLARE_WRITE8_MEMBER(drive_w);
+ DECLARE_WRITE8_MEMBER(xferd_w);
+ DECLARE_WRITE8_MEMBER(hbcr_w);
+ DECLARE_WRITE8_MEMBER(clksel_w);
+ DECLARE_WRITE8_MEMBER(drvsel2_w);
+ DECLARE_READ8_MEMBER(data_r);
+ DECLARE_WRITE8_MEMBER(data_w);
+
+ void regs(address_map &map);
+
+ required_device<wd1010_device> m_hdc;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ unsigned m_ram_ptr;
+ int m_int;
+ int m_drive;
+ int m_head;
+ int m_hbcr;
+ int m_clksel;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(APRICOT_WINCHESTER, apricot_winchester_device)
+
+#endif // MAME_BUS_APRICOT_WINCHESTER_H