summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/vme/vme.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/vme/vme.cpp')
-rw-r--r--src/devices/bus/vme/vme.cpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/src/devices/bus/vme/vme.cpp b/src/devices/bus/vme/vme.cpp
new file mode 100644
index 00000000000..342596f10bf
--- /dev/null
+++ b/src/devices/bus/vme/vme.cpp
@@ -0,0 +1,399 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/*
+ * vme.c
+ *
+ * The Versabus-E was standardized as the VME bus by VITA 1981 for Europe
+ * in the single or double Euroboard form factor. Several standard revs has
+ * been approved since then up until recently and the VME64 revision.
+ *
+ * This bus driver starts with Versabus and VME rev C.
+ * http://bitsavers.informatik.uni-stuttgart.de/pdf/motorola/versabus/M68KVBS_VERSAbus_Specification_Manual_Jul81.pdf
+ *
+ * Acronymes from the specification
+ * ---------------------------------
+ * BACKPLANE - A printed circuit board which provides the interconnection path
+ between other printed circuit cards.
+ SLOT - A single position at which a card may be inserted into the backplane.
+ One slot may consist of more than one edge connector.
+ BOARD/CARD - Interchangeable terms representing one printed circuit board capable
+ of being inserted into the backplane and containing a collection of
+ electronic components.
+ MODULE - A collection of electronic components with a single functional
+ purpose. More than one module may exist on the same card, but one
+ module should never be spread over multiple cards.
+ MASTER - A functional module capable of initiating data bus transfers.
+ REQUESTER - A functional module capable of requesting control of the data
+ transfer bus.
+ INTERRUPT - A functional module capable of detecting interrupt requests
+ HANDLER and initiating appropriate responses.
+ MASTER - The combination of a MASTER, REQUESTER, INTERRUPT HANDLER, and
+ SUB-SYSTEM (optionally) an INTERRUPTER, which function together and which
+ must be on the same card.
+
+ NOTE! All MASTERS, REQUESTERS, and INTERRUPT HANDLERS must be pieces of a
+ MASTER SUB-SYSTEM.
+
+ SLAVE - A functional module capable of responding to data transfer
+ operations generated by a MASTER.
+ INTERRUPTER - A functional module capable of requesting service from a MASTER
+ SUB-SYSTEM by generating an interrupt request.
+ SLAVE - The combination of a SLAVE and INTERRUPTER which function together
+ SUB-SYSTEM and which must be on the same card.
+
+ NOTE! All INTERRUPTERS must be part of either SLAVE SUB-SYSTEMS or MASTER
+ SUB-SYSTEMS. However, SLAVES may exist as stand-alone elements.
+ Such SLAVES will never be called SLAVE SUB-SYSTEMS.
+
+ CONTROLLER - The combination of modules used to provide utility and emergency
+ SUB-SYSTEM signals for the VERSAbus. There will always be one and only one
+ CONTROLLER SUB-SYSTEM. It can contain the following functional
+ modules:
+
+ a. Data Transfer Bus ARBITER
+ b. Emergency Data Transfer Bus REQUESTER
+ c. Power up/power down MASTER
+ d. System clock driver
+ e. System reset driver
+ f. System test controller
+ g. Power monitor (for AC clock and AC fail driver)
+
+ In any VERSAbus system, only one each of the above functional modules will exist.
+ The slot numbered Al is designated as the controller sub-system slot because the
+ user will typically provide modules a through d on the board residing in this
+ slot. System reset and the system test controller are typically connected to
+ an operator control panel and may be located elsewhere. The power monitor is
+ interfaced to the incoming AC power source and may also be located remotely.
+*/
+
+#include "emu.h"
+#include "vme.h"
+#include "bus/vme/mzr8105.h"
+#include "bus/vme/mzr8300.h"
+
+#define LOG_GENERAL 0x01
+#define LOG_SETUP 0x02
+#define LOG_PRINTF 0x04
+
+#define VERBOSE 0 //(LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
+
+#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
+#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
+
+#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
+
+#define logerror printf // logerror is not available here
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type VME_P1_SLOT = &device_creator<vme_p1_slot_device>;
+
+//-------------------------------------------------
+// vme_p1_slot_device - constructor
+//-------------------------------------------------
+vme_p1_slot_device::vme_p1_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, VME_P1_SLOT, "VME_P1_SLOT", tag, owner, clock, "vme_p1_slot", __FILE__)
+ ,device_slot_interface(mconfig, *this)
+ ,m_vme_p1_tag(nullptr)
+ ,m_vme_p1_slottag(nullptr)
+ ,m_vme_j1_callback(*this)
+{
+ LOG("%s %s\n", tag, FUNCNAME);
+}
+
+vme_p1_slot_device::vme_p1_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_slot_interface(mconfig, *this)
+ ,m_vme_p1_tag(nullptr)
+ ,m_vme_p1_slottag(nullptr)
+ ,m_vme_j1_callback(*this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void vme_p1_slot_device::static_set_vme_p1_slot(device_t &device, const char *tag, const char *slottag)
+{
+ LOG("%s %s - %s\n", FUNCNAME, tag, slottag);
+ vme_p1_slot_device &vme_card = dynamic_cast<vme_p1_slot_device&>(device);
+ vme_card.m_vme_p1_tag = tag;
+ vme_card.m_vme_p1_slottag = slottag;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void vme_p1_slot_device::device_start()
+{
+ device_vme_p1_card_interface *dev = dynamic_cast<device_vme_p1_card_interface *>(get_card_device());
+ LOG("%s %s - %s:%s\n", tag(), FUNCNAME, m_vme_p1_tag, m_vme_p1_slottag);
+ if (dev) device_vme_p1_card_interface::static_set_vme_p1_tag(*dev, m_vme_p1_tag, m_vme_p1_slottag);
+
+ // m_card = dynamic_cast<device_vme_p1_card_interface *>(get_card_device());
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+void vme_p1_slot_device::device_config_complete()
+{
+ LOG("%s %s\n", tag(), FUNCNAME);
+}
+
+//-------------------------------------------------
+// P1 D8 read
+//-------------------------------------------------
+READ8_MEMBER(vme_p1_slot_device::read8)
+{
+ uint16_t result = 0x00;
+ LOG("%s %s\n", tag(), FUNCNAME);
+ // printf("%s %s\n", tag(), FUNCNAME);
+ // if (m_card) result = m_card->read8(space, offset);
+ return result;
+}
+
+//-------------------------------------------------
+// P1 D8 write
+//-------------------------------------------------
+WRITE8_MEMBER(vme_p1_slot_device::write8)
+{
+ LOG("%s %s\n", tag(), FUNCNAME);
+ // printf("%s %s\n", tag(), FUNCNAME);
+ // if (m_card) m_card->write8(space, offset, data);
+}
+
+SLOT_INTERFACE_START( vme_p1_slot1 )
+ SLOT_INTERFACE("mzr8105", VME_MZR8105)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( vme_p1_slots )
+ SLOT_INTERFACE("mzr8105", VME_MZR8105)
+ SLOT_INTERFACE("mzr8300", VME_MZR8300)
+SLOT_INTERFACE_END
+
+//
+// VME device P1
+//
+
+const device_type VME_P1 = &device_creator<vme_p1_device>;
+
+vme_p1_device::vme_p1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, VME_P1, "VME_P1", tag, owner, clock, "vme_p1", __FILE__)
+{
+}
+
+vme_p1_device::vme_p1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+vme_p1_device::~vme_p1_device()
+{
+ m_device_list.detach_all();
+}
+
+void vme_p1_device::device_start()
+{
+}
+
+void vme_p1_device::device_reset()
+{
+}
+
+void vme_p1_device::add_vme_p1_card(device_vme_p1_card_interface *card)
+{
+ m_device_list.append(*card);
+}
+
+void vme_p1_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask)
+{
+ cpu_device *m_maincpu = machine().device<cpu_device>("maincpu");
+
+ // printf("%s", __func__);
+
+ int buswidth = m_maincpu->space_config(AS_PROGRAM)->m_databus_width;
+ switch(buswidth)
+ {
+ case 32:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
+ break;
+ case 64:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
+ break;
+ default:
+ fatalerror("VME_P1: Bus width %d not supported\n", buswidth);
+ }
+}
+
+void vme_p1_device::install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask)
+{
+ cpu_device *m_maincpu = machine().device<cpu_device>("maincpu");
+ int buswidth = m_maincpu->space_config(AS_PROGRAM)->m_databus_width;
+ switch(buswidth)
+ {
+ case 32:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
+ break;
+ case 64:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
+ break;
+ default:
+ fatalerror("VME_P1: Bus width %d not supported\n", buswidth);
+ }
+}
+
+void vme_p1_device::install_device(offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, uint32_t mask)
+{
+ cpu_device *m_maincpu = machine().device<cpu_device>("maincpu");
+ int buswidth = m_maincpu->space_config(AS_PROGRAM)->m_databus_width;
+ switch(buswidth)
+ {
+ case 32:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
+ break;
+ case 64:
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
+ break;
+ default:
+ fatalerror("VME_P1: Bus width %d not supported\n", buswidth);
+ }
+}
+
+//
+// Card interface
+//
+device_vme_p1_card_interface::device_vme_p1_card_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+ ,m_vme_p1(nullptr)
+ ,m_vme_p1_tag(nullptr)
+ ,m_vme_p1_slottag(nullptr)
+ ,m_slot(0)
+ ,m_next(nullptr)
+{
+ m_device = &device;
+ LOG("%s %s\n", m_device->tag(), FUNCNAME);
+}
+
+device_vme_p1_card_interface::~device_vme_p1_card_interface()
+{
+ LOG("%s %s\n", m_device->tag(), FUNCNAME);
+}
+
+void device_vme_p1_card_interface::static_set_vme_p1_tag(device_t &device, const char *tag, const char *slottag)
+{
+ device_vme_p1_card_interface &vme_p1_card = dynamic_cast<device_vme_p1_card_interface &>(device);
+ vme_p1_card.m_vme_p1_tag = tag;
+ vme_p1_card.m_vme_p1_slottag = slottag;
+}
+
+void device_vme_p1_card_interface::set_vme_p1_device()
+{
+ LOG("%s %s\n", m_device->tag(), FUNCNAME);
+ m_vme_p1 = dynamic_cast<vme_p1_device *>(device().machine().device(m_vme_p1_tag));
+ // printf("*** %s %sfound\n", m_vme_p1_tag, m_vme_p1 ? "" : "not ");
+ if (m_vme_p1) m_vme_p1->add_vme_p1_card(this);
+}
+
+/* VME D8 accesses */
+READ8_MEMBER(device_vme_p1_card_interface::read8)
+{
+ uint8_t result = 0x00;
+ LOG("%s %s Offset:%08x\n", m_device->tag(), FUNCNAME, offset);
+ return result;
+}
+
+WRITE8_MEMBER(device_vme_p1_card_interface::write8)
+{
+ LOG("%s %s Offset:%08x\n", m_device->tag(), FUNCNAME, offset);
+}
+
+//--------------- P2 connector below--------------------------
+#if 0
+/*
+The VME P2 connector only specifies the mid row B of the connector
+and leaves row A and C to be system specific. This has resulted in
+a number of variants that has been more or less standardized:
+
+- VMXbus was available on the first VME boards but not standardized hence
+an almost compatible variant was developed by Motorola called MVMX32bus.
+- VSBbus replaced VMX and MVMX32and was approved by IEEE in 1988
+- SCSA is a P2 standardization for telephony voice and facsimile applications
+- SkyChannel is packet switched P2 architecture from Sky Computers and standardized
+through VITA/VSO.
+- RACEway is a 40Mhz P2 bus allowing 480MBps throughput from Mercusry Computers and
+standardized through VITA/VSO.
+- VME64 adds two more rows, called 'z' and 'd', of user defined pins to the P2 connector
+- P2CI adds a PCI bus onto a VME64 P2 connector
+
+URL:s
+http://rab.ict.pwr.wroc.pl/dydaktyka/supwa/vme/secbuses.html
+http://www.interfacebus.com/Design_Connector_VME_P2_Buses.html
+
+TODO: Figure out a good way to let all these variants coexist and interconnect in a VME system
+
+*/
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type VME_P2_SLOT = &device_creator<vme_p2_slot_device>;
+
+//-------------------------------------------------
+// vme_p2_slot_device - constructor
+//-------------------------------------------------
+vme_p2_slot_device::vme_p2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, VME_P2_SLOT, "VME P2 connector", tag, owner, clock, "vme_p2_connector", __FILE__),
+ device_slot_interface(mconfig, *this),
+ m_vme_j2_callback(*this)
+{
+}
+
+void vme_p2_slot_device::device_start()
+{
+ m_vme_p2 = dynamic_cast<device_vme_p2_interface *>(get_card_device());
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void vme_p2_slot_device::device_config_complete()
+{
+ // set brief and instance name
+ update_names();
+}
+
+//-------------------------------------------------
+// P2 read
+//-------------------------------------------------
+READ32_MEMBER(vme_p2_slot_device::write32)
+{
+ uint8_t result = 0x00;
+ if (m_vme_p2)
+ result = m_vme_p2->read32(space, offset);
+ return result;
+}
+
+//-------------------------------------------------
+// P2 write
+//-------------------------------------------------
+WRITE32_MEMBER(vme_p2_slot_device::read32)
+{
+ if (m_vme_p2)
+ m_vme_p2->write32(space, offset, data);
+}
+#endif