diff options
Diffstat (limited to 'src/devices/cpu/z80/z80daisy.c')
-rw-r--r-- | src/devices/cpu/z80/z80daisy.c | 179 |
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); +} |