summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/bus/coco/coco_multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/bus/coco/coco_multi.c')
-rw-r--r--src/emu/bus/coco/coco_multi.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/emu/bus/coco/coco_multi.c b/src/emu/bus/coco/coco_multi.c
new file mode 100644
index 00000000000..0f71766b516
--- /dev/null
+++ b/src/emu/bus/coco/coco_multi.c
@@ -0,0 +1,266 @@
+/***************************************************************************
+
+ coco_multi.c
+
+ Code for emulating CoCo's Multi-Pak Interface
+
+ The Multi-Pak interface multiplexes all I/O lines from the Color
+ Computer's expansion port to four identical ports. All I/O lines
+ are continuously multiplexed except:
+
+ Pin 36 - *SCS
+ Pin 32 - *CTS
+ Pin 8 - *CART
+
+ These I/O lines are switched in one of two ways. First, is the front
+ panel, four position switch. When adjusted the switch will direct the
+ MPI to target these three I/O lines to the selected slot.
+
+ Second, the MPI will listen to writes to 0xff7f and respond accordingly:
+
+ bit 0 --\___ Target *SCS to this slot number
+ bit 1 --/
+ bit 2 ------ Ignore
+ bit 3 ------ Ignore
+ bit 4 --\___ Target *CTS and *CART to this slot number
+ bit 5 --/
+ bit 6 ------ Ignore
+ bit 7 ------ Ignore
+
+ After writing to 0xff7f, the position of the physical switch has no
+ effect until reset.
+
+ Reading is supported on 0xff7f. It will reflect the position of the
+ physical switch. Until data is written to 0xff7f, then it will only
+ reflect what has been written until a reset.
+
+ A common modification users of the OS-9 operating system made was to
+ tie all of the *CART pins together on the MPI motherboard. The *CART
+ line is connected to the 6809's IRQ line. This allowed any hardware
+ device in any slot to signal an IRQ to the CPU, no matter what the
+ switch position was. OS-9 was designed from the very start to poll
+ each device attached on every IRQ signal.
+
+ Because of sloppy address decoding the original MPI also responds to
+ $FF9F. No software is known to take advantage of this. After the
+ introduction of the CoCo 3, which uses $FF9F internally, Tandy provided
+ free upgrades to any MPI to fix this problem.
+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/coco.h"
+#include "coco_multi.h"
+#include "coco_232.h"
+#include "coco_orch90.h"
+#include "coco_pak.h"
+#include "coco_fdc.h"
+
+#define SLOT1_TAG "slot1"
+#define SLOT2_TAG "slot2"
+#define SLOT3_TAG "slot3"
+#define SLOT4_TAG "slot4"
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static SLOT_INTERFACE_START(coco_cart_slot1_3)
+ SLOT_INTERFACE("rs232", COCO_232)
+ SLOT_INTERFACE("orch90", COCO_ORCH90)
+ SLOT_INTERFACE("banked_16k", COCO_PAK_BANKED)
+ SLOT_INTERFACE("pak", COCO_PAK)
+SLOT_INTERFACE_END
+static SLOT_INTERFACE_START(coco_cart_slot4)
+ SLOT_INTERFACE("fdcv11", COCO_FDC_V11)
+ SLOT_INTERFACE("rs232", COCO_232)
+ SLOT_INTERFACE("orch90", COCO_ORCH90)
+ SLOT_INTERFACE("banked_16k", COCO_PAK_BANKED)
+ SLOT_INTERFACE("pak", COCO_PAK)
+SLOT_INTERFACE_END
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_cart_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_cart_callback.writeline(this,state);
+}
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_nmi_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_nmi_callback.writeline(this,state);
+}
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_halt_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_halt_callback.writeline(this,state);
+}
+
+static const cococart_interface multi_cococart_interface =
+{
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_cart_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_nmi_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_halt_w)
+};
+
+static MACHINE_CONFIG_FRAGMENT(coco_multi)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT1_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT2_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT3_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT4_TAG, multi_cococart_interface, coco_cart_slot4, "fdcv11")
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_MULTIPAK = &device_creator<coco_multipak_device>;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_multipak_device - constructor
+//-------------------------------------------------
+
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_MULTIPAK, "CoCo Multi-Pak Interface", tag, owner, clock, "coco_multipak", __FILE__),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_multipak_device::device_start()
+{
+ // identify slots
+ m_slots[0] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT1_TAG));
+ m_slots[1] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT2_TAG));
+ m_slots[2] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT3_TAG));
+ m_slots[3] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT4_TAG));
+ m_owner = dynamic_cast<cococart_slot_device *>(owner());
+
+ // install $FF7F handler
+ write8_delegate wh = write8_delegate(FUNC(coco_multipak_device::ff7f_write), this);
+ machine().device(MAINCPU_TAG)->memory().space(AS_PROGRAM).install_write_handler(0xFF7F, 0xFF7F, wh);
+
+ // initial state
+ m_select = 0xFF;
+
+ // save state
+ save_item(NAME(m_select));
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_multipak_device::device_reset()
+{
+ m_select = 0xFF;
+}
+
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_multipak_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_multi );
+}
+
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+UINT8* coco_multipak_device::get_cart_base()
+{
+ return active_cts_slot()->get_cart_base();
+}
+
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+READ8_MEMBER(coco_multipak_device::read)
+{
+ return active_scs_slot()->read(space,offset);
+}
+
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_multipak_device::write)
+{
+ active_scs_slot()->write(space,offset,data);
+}
+
+
+
+//-------------------------------------------------
+// ff7f_write
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_multipak_device::ff7f_write)
+{
+ set_select(data);
+}
+
+
+
+//-------------------------------------------------
+// set_select
+//-------------------------------------------------
+
+void coco_multipak_device::set_select(UINT8 new_select)
+{
+ UINT8 xorval = m_select ^ new_select;
+ m_select = new_select;
+ if (xorval & 0x30)
+ cart_base_changed();
+}
+
+
+
+//-------------------------------------------------
+// active_scs_slot
+//-------------------------------------------------
+
+cococart_slot_device *coco_multipak_device::active_scs_slot(void)
+{
+ return m_slots[(m_select >> 0) & 0x03];
+}
+
+
+
+//-------------------------------------------------
+// active_cts_slot
+//-------------------------------------------------
+
+cococart_slot_device *coco_multipak_device::active_cts_slot(void)
+{
+ return m_slots[(m_select >> 4) & 0x03];
+}