diff options
Diffstat (limited to 'src/mess/machine/econet.c')
-rw-r--r-- | src/mess/machine/econet.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/mess/machine/econet.c b/src/mess/machine/econet.c new file mode 100644 index 00000000000..f366ad36c2c --- /dev/null +++ b/src/mess/machine/econet.c @@ -0,0 +1,355 @@ +/********************************************************************** + + Acorn Computers Econet local area network emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "econet.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 0 + + +static const char *const SIGNAL_NAME[] = { "CLK", "DATA" }; + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type ECONET = &device_creator<econet_device>; +const device_type ECONET_SLOT = &device_creator<econet_slot_device>; + + + +//************************************************************************** +// DEVICE INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_econet_interface - constructor +//------------------------------------------------- + +device_econet_interface::device_econet_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig, device) +{ +} + + +//------------------------------------------------- +// ~device_econet_interface - destructor +//------------------------------------------------- + +device_econet_interface::~device_econet_interface() +{ +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// econet_slot_device - constructor +//------------------------------------------------- + +econet_slot_device::econet_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, ECONET_SLOT, "Econet station", tag, owner, clock), + device_slot_interface(mconfig, *this) +{ +} + + +//------------------------------------------------- +// static_set_slot - +//------------------------------------------------- + +void econet_slot_device::static_set_slot(device_t &device, int address) +{ + econet_slot_device &econet_card = dynamic_cast<econet_slot_device &>(device); + econet_card.m_address = address; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void econet_slot_device::device_start() +{ + m_econet = machine().device<econet_device>(ECONET_TAG); + device_econet_interface *dev = dynamic_cast<device_econet_interface *>(get_card_device()); + if (dev) m_econet->add_device(get_card_device(), m_address); +} + + + +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void econet_device::device_config_complete() +{ + // inherit a copy of the static data + const econet_interface *intf = reinterpret_cast<const econet_interface *>(static_config()); + if (intf != NULL) + *static_cast<econet_interface *>(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_clk_cb, 0, sizeof(m_out_clk_cb)); + memset(&m_out_data_cb, 0, sizeof(m_out_data_cb)); + } +} + + + +//************************************************************************** +// INLINE HELPERS +//************************************************************************** + +//------------------------------------------------- +// set_signal - +//------------------------------------------------- + +inline void econet_device::set_signal(device_t *device, int signal, int state) +{ + bool changed = false; + + if (device == this) + { + if (m_line[signal] != state) + { + if (LOG) logerror("Econet: '%s' %s %u\n", tag(), SIGNAL_NAME[signal], state); + m_line[signal] = state; + changed = true; + } + } + else + { + daisy_entry *entry = m_device_list.first(); + + while (entry) + { + if (!strcmp(entry->m_device->tag(), device->tag())) + { + if (entry->m_line[signal] != state) + { + if (LOG) logerror("Econet: '%s' %s %u\n", device->tag(), SIGNAL_NAME[signal], state); + entry->m_line[signal] = state; + changed = true; + } + } + + entry = entry->next(); + } + } + + if (changed) + { + switch (signal) + { + case CLK: m_out_clk_func(state); break; + case DATA: m_out_data_func(state); break; + } + + daisy_entry *entry = m_device_list.first(); + + while (entry) + { + switch (signal) + { + case CLK: + entry->m_interface->econet_clk(state); + break; + + case DATA: + entry->m_interface->econet_data(state); + break; + } + + entry = entry->next(); + } + + if (LOG) logerror("Econet: CLK %u DATA %u\n", get_signal(CLK), get_signal(DATA)); + } +} + + +//------------------------------------------------- +// get_signal - +//------------------------------------------------- + +inline int econet_device::get_signal(int signal) +{ + int state = m_line[signal]; + + if (state) + { + daisy_entry *entry = m_device_list.first(); + + while (entry) + { + if (!entry->m_line[signal]) + { + state = 0; + break; + } + + entry = entry->next(); + } + } + + return state; +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// econet_device - constructor +//------------------------------------------------- + +econet_device::econet_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, ECONET, "Econet", tag, owner, clock) +{ + for (int i = 0; i < SIGNAL_COUNT; i++) + { + m_line[i] = 1; + } +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void econet_device::device_start() +{ + // resolve callbacks + m_out_clk_func.resolve(m_out_clk_cb, *this); + m_out_data_func.resolve(m_out_data_cb, *this); +} + + +//------------------------------------------------- +// device_stop - device-specific stop +//------------------------------------------------- + +void econet_device::device_stop() +{ + m_device_list.reset(); +} + + +//------------------------------------------------- +// add_device - +//------------------------------------------------- + +void econet_device::add_device(device_t *target, int address) +{ + daisy_entry *entry = auto_alloc(machine(), daisy_entry(target)); + + entry->m_interface->m_econet = this; + entry->m_interface->m_address = address; + + m_device_list.append(*entry); +} + + +//------------------------------------------------- +// daisy_entry - constructor +//------------------------------------------------- + +econet_device::daisy_entry::daisy_entry(device_t *device) + : m_next(NULL), + m_device(device), + m_interface(NULL) +{ + for (int i = 0; i < SIGNAL_COUNT; i++) + { + m_line[i] = 1; + } + + device->interface(m_interface); +} + + +//------------------------------------------------- +// clk_r - +//------------------------------------------------- + +READ_LINE_MEMBER( econet_device::clk_r ) +{ + return get_signal(CLK); +} + + +//------------------------------------------------- +// data_r - +//------------------------------------------------- + +READ_LINE_MEMBER( econet_device::data_r ) +{ + return get_signal(DATA); +} + + +//------------------------------------------------- +// clk_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( econet_device::clk_w ) +{ + set_signal(this, CLK, state); +} + + +//------------------------------------------------- +// data_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( econet_device::data_w ) +{ + set_signal(this, DATA, state); +} + + +//------------------------------------------------- +// clk_w - +//------------------------------------------------- + +void econet_device::clk_w(device_t *device, int state) +{ + set_signal(device, CLK, state); +} + + +//------------------------------------------------- +// data_w - +//------------------------------------------------- + +void econet_device::data_w(device_t *device, int state) +{ + set_signal(device, DATA, state); +} |