diff options
Diffstat (limited to 'src/devices/bus/vme/vme.cpp')
-rw-r--r-- | src/devices/bus/vme/vme.cpp | 411 |
1 files changed, 411 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..381b7e3075e --- /dev/null +++ b/src/devices/bus/vme/vme.cpp @@ -0,0 +1,411 @@ +// license:BSD-3-Clause +// copyright-holders:Joakim Larsson Edstrom +/* + * vme.cpp + * + * 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"); + + int buswidth = m_maincpu->space_config(AS_PROGRAM)->m_databus_width; + LOG("%s width:%d\n", FUNCNAME, buswidth); + switch(buswidth) + { + case 32: + logerror("A32:D8 handler requires a P2 connector - not implemented yet\n"); + break; + case 24: + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask); + break; + case 16: + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0xffff)); + break; + default: + fatalerror("VME_P1 D8: 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; + LOG("%s width:%d\n", FUNCNAME, buswidth); + switch(buswidth) + { + case 32: + logerror("A32:D16 handler requires a P2 connector - not implemented yet\n"); + break; + case 24: + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask); + break; + case 16: + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0xffff)); + break; + default: + fatalerror("VME_P1 D16: 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; + LOG("%s width:%d\n", FUNCNAME, buswidth); + switch(buswidth) + { + case 32: + logerror("A32:D32 handler requires a P2 connector - not implemented yet\n"); + break; + case 24: + logerror("A24:D32 handler requires a P2 connector - not implemented yet\n"); + // m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask); + break; + case 16: + logerror("A16:D32 handler requires a P2 connector - not implemented yet\n"); + // m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0xffff)); + break; + default: + fatalerror("VME_P1 D32: 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 |