summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/z80/z80daisy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/z80/z80daisy.c')
-rw-r--r--src/devices/cpu/z80/z80daisy.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/devices/cpu/z80/z80daisy.c b/src/devices/cpu/z80/z80daisy.c
new file mode 100644
index 00000000000..c1b0a5454c3
--- /dev/null
+++ b/src/devices/cpu/z80/z80daisy.c
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders:Juergen Buchmueller
+/***************************************************************************
+
+ z80daisy.c
+
+ Z80/180 daisy chaining support functions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE Z80 DAISY INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_z80daisy_interface - constructor
+//-------------------------------------------------
+
+device_z80daisy_interface::device_z80daisy_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "z80daisy")
+{
+}
+
+
+//-------------------------------------------------
+// ~device_z80daisy_interface - destructor
+//-------------------------------------------------
+
+device_z80daisy_interface::~device_z80daisy_interface()
+{
+}
+
+
+
+//**************************************************************************
+// Z80 DAISY CHAIN
+//**************************************************************************
+
+//-------------------------------------------------
+// z80_daisy_chain - constructor
+//-------------------------------------------------
+
+z80_daisy_chain::z80_daisy_chain()
+ : m_daisy_list(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// init - allocate the daisy chain based on the
+// provided configuration
+//-------------------------------------------------
+
+void z80_daisy_chain::init(device_t *cpudevice, const z80_daisy_config *daisy)
+{
+ // create a linked list of devices
+ daisy_entry **tailptr = &m_daisy_list;
+ for ( ; daisy->devname != NULL; daisy++)
+ {
+ // find the device
+ device_t *target;
+ if ((target = cpudevice->subdevice(daisy->devname)) == NULL)
+ {
+ if ((target = cpudevice->siblingdevice(daisy->devname)) == NULL)
+ fatalerror("Unable to locate device '%s'\n", daisy->devname);
+ }
+
+ // make sure it has an interface
+ device_z80daisy_interface *intf;
+ if (!target->interface(intf))
+ fatalerror("Device '%s' does not implement the z80daisy interface!\n", daisy->devname);
+
+ // append to the end, or overwrite existing entry
+ daisy_entry *next = (*tailptr) ? (*tailptr)->m_next : NULL;
+ if (*tailptr != NULL)
+ auto_free(cpudevice->machine(), *tailptr);
+ *tailptr = auto_alloc(cpudevice->machine(), daisy_entry(target));
+ (*tailptr)->m_next = next;
+ tailptr = &(*tailptr)->m_next;
+ }
+}
+
+
+//-------------------------------------------------
+// reset - send a reset signal to all chained
+// devices
+//-------------------------------------------------
+
+void z80_daisy_chain::reset()
+{
+ // loop over all devices and call their reset function
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ daisy->m_device->reset();
+}
+
+
+//-------------------------------------------------
+// update_irq_state - update the IRQ state and
+// return assert/clear based on the state
+//-------------------------------------------------
+
+int z80_daisy_chain::update_irq_state()
+{
+ // loop over all devices; dev[0] is highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the INT line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ if (state & Z80_DAISY_INT)
+ return ASSERT_LINE;
+
+ // if this device is asserting the IEO line, it blocks everyone else
+ if (state & Z80_DAISY_IEO)
+ return CLEAR_LINE;
+ }
+ return CLEAR_LINE;
+}
+
+
+//-------------------------------------------------
+// call_ack_device - acknowledge an interrupt
+// from a chained device and return the vector
+//-------------------------------------------------
+
+int z80_daisy_chain::call_ack_device()
+{
+ int vector = 0;
+
+ // loop over all devices; dev[0] is the highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the INT line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ vector = daisy->m_interface->z80daisy_irq_ack();
+ if (state & Z80_DAISY_INT)
+ return vector;
+ }
+ //logerror("z80daisy_call_ack_device: failed to find an device to ack!\n");
+ return vector;
+}
+
+
+//-------------------------------------------------
+// call_reti_device - signal a RETI operator to
+// the chain
+//-------------------------------------------------
+
+void z80_daisy_chain::call_reti_device()
+{
+ // loop over all devices; dev[0] is the highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the IEO line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ if (state & Z80_DAISY_IEO)
+ {
+ daisy->m_interface->z80daisy_irq_reti();
+ return;
+ }
+ }
+ //logerror("z80daisy_call_reti_device: failed to find an device to reti!\n");
+}
+
+
+//-------------------------------------------------
+// daisy_entry - constructor
+//-------------------------------------------------
+
+z80_daisy_chain::daisy_entry::daisy_entry(device_t *device)
+ : m_next(NULL),
+ m_device(device),
+ m_interface(NULL)
+{
+ device->interface(m_interface);
+}