summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/vme/sys68k_cpu1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/vme/sys68k_cpu1.cpp')
-rw-r--r--src/devices/bus/vme/sys68k_cpu1.cpp671
1 files changed, 671 insertions, 0 deletions
diff --git a/src/devices/bus/vme/sys68k_cpu1.cpp b/src/devices/bus/vme/sys68k_cpu1.cpp
new file mode 100644
index 00000000000..160a14ad3e8
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu1.cpp
@@ -0,0 +1,671 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Force SYS68K CPU-1/CPU-6 VME SBC drivers, initially based on the 68ksbc.c
+ *
+ * 13/06/2015
+ *
+ * The info found on the links below is for a later revisions of the board I have
+ * but it is somewhat compatible so I got the system ROM up and running in terminal.
+ * My CPU-1 board has proms from 1983 and the PCB has no rev markings so probably
+ * the original or a very early design. The board real estate differs from the later
+ * CPU-1:s I found pictures of but has the same main chips and functions.
+ *
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/1988_Force_VMEbus_Products.pdf
+ * http://www.artisantg.com/info/P_wUovN.pdf
+ *
+ * Some info from those documents:
+ *
+ * Address Map
+ * ----------------------------------------------------------
+ * Address Range Description
+ * ----------------------------------------------------------
+ * 000 000 - 000 007 Initialisation vectors from system EPROM
+ * 000 008 - 01F FFF Dynamic RAM on CPU-1 B
+ * 000 008 - 07F FFF Dynamic RAM on CPU-1 D
+ * 080 008 - 09F FFF SYSTEM EPROM Area
+ * OAO 000 - OBF FFF USER EPROMArea
+ * 0C0 041 - 0C0 043 ACIA (P3) Host
+ * 0C0 080 - 0C0 082 ACIA (P4) Terminal
+ * 0C0 101 - 0C0 103 ACIA (P5) Remote device (eg serial printer)
+ * 0C0 401 - 0C0 42F RTC
+ * OEO 001 - 0E0 035 PI/T (eg centronics printer)
+ * OEO 200 - 0E0 2FF FPU
+ * OEO 300 - 0E0 300 Reset Off
+ * OEO 380 - 0E0 380 Reset On
+ * 100 000 - FEF FFF VMEbus addresses (A24)
+ * FFO 000 - FFF FFF VMEbus Short I/O (A16)
+ * ----------------------------------------------------------
+ *
+ * Interrupt sources
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ * ABORT Switch 7 31
+ * Real Time Clock (RTC) 58167A 6 30
+ * Parallel/Timer (PI/T) 68230 5 29
+ * Terminal ACIA 6850 4 28
+ * Remote ACIA 6850 3 27
+ * Host ACIA 6850 2 26
+ * ACFAIL, SYSFAIL VME 5 29
+ * Off board Sources (other VME boards)
+ * 6 Port Serial I/O board SIO 4 64-75 0xb00000
+ * 8 Port Serial I/O board ISIO 4 76-83 0x960000
+ * Disk Controller WFC 3 119 0xb01000
+ * SCSI Controller ISCSI 4 119 0xa00000
+ * Slot 1 Controller Board ASCU 7 31 0xb02000
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - Add internal layout with switches and leds
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "sys68k_cpu1.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/clock.h"
+#include "softlist.h"
+
+/*
+ * The baudrate on the Force68k CPU-1 to CPU-6 is generated by a Motorola 14411 bitrate generator
+ * The CPU-6 documents matches the circuits that I could find on the CPU-1 board.
+ *
+ * From the documents:
+ *
+ * 3 RS232C interfaces, strap selectable baud rate from 110-9600 or 600-19200 baud (CPU-1B datasheet)
+ * or
+ * 3 RS232C interfaces, strap selectable baud rate from 60-9600 or 240-38400 baud (CPU-6 Users manual)
+ *
+ * Default Jumper Settings of B7:
+ * --------------------------------
+ * GND 10 - 11 RSA input on 14411
+ * F1 on 14411 1 - 20 Baud selector of the terminal port
+ * F1 on 14411 3 - 18 Baud selector of the host port
+ * F1 on 14411 5 - 16 Baud selector of the remote port
+ *
+ * The RSB input on the 14411 is kept high always so RSA=0, RSB=1 and a 1.8432MHz crystal
+ * generates 153600 on the F1 output pin which by default strapping is connected to all
+ * three 6850 acias on the board. These can be strapped separatelly to speedup downloads.
+ *
+ * The selectable outputs from 14411, F1-F16:
+ * X16 RSA=0,RSB=1: 153600, 115200, 76800, 57600, 38400, 28800, 19200, 9600, 4800, 3200, 2153.3, 1758.8, 1200, 921600, 1843000
+ * X64 RSA=1,RSB=1: 614400, 460800, 307200, 230400, 153600, 115200, 76800, 57600, 38400, 28800, 19200, 9600, 4800, 921600, 1843000
+ *
+ * However, the datasheet says baudrate is strapable for 110-9600 but the output is 153600
+ * so the system rom MUST setup the acia to divide by 16 to generate the correct baudrate.
+ *
+ * There are multiple ways to achieve some of the baud rates and we have only seen a CPU-6 users manual so
+ * emulation mimics a CPU-6 board at the moment until further information has been gathered.
+ */
+
+//**************************************************************************
+// CONFIGURABLE LOGGING
+//**************************************************************************
+
+#define LOG_SETUP (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL | LOG_SETUP)
+//#define LOG_OUTPUT_FUNC printf
+#include "logmacro.h"
+
+// #define LOG(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) // defined in logmacro.h
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU1, vme_sys68k_cpu1_card_device, "sys68k_cpu1", "Force Computers SYS68K/CPU-1")
+
+vme_sys68k_cpu1_card_device::vme_sys68k_cpu1_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_SYS68K_CPU1, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_rtc(*this, "rtc")
+ , m_pit(*this, "pit")
+ , m_brg(*this, "brg")
+ , m_aciahost(*this, "aciahost")
+ , m_aciaterm(*this, "aciaterm")
+ , m_aciaremt(*this, "aciaremt")
+ , m_centronics(*this, "centronics")
+ , m_centronics_ack(0)
+ , m_centronics_busy(0)
+ , m_centronics_perror(0)
+ , m_centronics_select(0)
+ , m_serial_brf(*this, "SERIAL_BRF")
+ , m_serial_p3(*this, "SERIAL_P3")
+ , m_serial_p4(*this, "SERIAL_P4")
+ , m_serial_p5(*this, "SERIAL_P5")
+ , m_cart(*this, "exp_rom1")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
+{
+}
+
+void vme_sys68k_cpu1_card_device::force68k_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x000000, 0x01ffff).ram().share("ram"); /* DRAM CPU-1B */
+// map(0x020000, 0x07ffff).ram(); /* Additional DRAM CPU-1D */
+ map(0x080000, 0x09ffff).rom().region("eprom", 0); /* System EPROM Area 128Kb DEBUGGER supplied as default on CPU-1B/D */
+ //map(0x0a0000, 0x0bffff).rom().region("user", 0); /* User EPROM/SRAM Area, max 128Kb mapped by a cartslot */
+ map(0x0c0040, 0x0c0043).rw(m_aciahost, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0x00ff);
+ map(0x0c0080, 0x0c0083).rw(m_aciaterm, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
+ map(0x0c0100, 0x0c0103).rw(m_aciaremt, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0x00ff);
+ map(0x0c0400, 0x0c042f).rw(m_rtc, FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);
+ map(0x0e0000, 0x0e0035).rw(m_pit, FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
+// map(0x0e0200, 0x0e0380).rw(FUNC(vme_sys68k_cpu1_card_device::fpu_r), FUNC(vme_sys68k_cpu1_card_device::fpu_w)); /* optional FPCP 68881 FPU interface */
+ map(0x100000, 0xfeffff).rw(FUNC(vme_sys68k_cpu1_card_device::vme_a24_r), FUNC(vme_sys68k_cpu1_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) */
+ map(0xff0000, 0xffffff).rw(FUNC(vme_sys68k_cpu1_card_device::vme_a16_r), FUNC(vme_sys68k_cpu1_card_device::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (sys68k_cpu1)
+
+ PORT_START("SERIAL_BRF")
+ PORT_CONFNAME(0x80 , 0x00 , "Baud Rate Factor") // RSA pin on MC14411
+ PORT_CONFSETTING(0x00, "1x (Lo)")
+ PORT_CONFSETTING(0x80, "4x (Hi)")
+
+ PORT_START("SERIAL_P3")
+ PORT_CONFNAME(0x0F , 0x00 , "P3 Host Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+ PORT_START("SERIAL_P4")
+ PORT_CONFNAME(0x0F , 0x00 , "P4 Terminal Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+ PORT_START("SERIAL_P5")
+ PORT_CONFNAME(0x0F , 0x00 , "P5 Remote Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+INPUT_PORTS_END
+
+/*
+ * Centronics support
+ *
+ * The system ROMs has support for a parallel printer interface but the signals are just routed to row A
+ * of the VME P2 connector so no on board Centronics connector is available but assumed to be added on a
+ * separate I/O board. After some detective work I found that the ROM works as follows:
+ *
+ * The 'PA' (Printer Attach) command issues a <cr> on Port A and sends a strobe on H2 it then loops over
+ * the select signal, bit 0 on Port B, and the ack signal on HS1, both to be non zero. The support is really
+ * flawed as the strobe signal goes high instead of low ( this might assume an inverting driver on the
+ * P2 board ) and the busy signal is not checked at all. Or I might have assumed it all wrong, but it now
+ * works with the generic centronics printer driver. Need the printer board documentation to improve further.
+ *
+ * When the 'PA' command is successful everything printed to screen is mirrored on the printer. Use the
+ * 'NOPA' command to stop mirroring. I had no printer ROMs so could not test it with a "real" printer.
+ *
+ * Force CPU-1 init sequence for MC68230 PIT
+ * -----------------------------------------
+ * 0801E6 0E0000 W 00 -> PGCR Mode 0 (uni8), H34 dis, H12 dis, H1234 HZ
+ * 0801E6 0E0002 W 00 -> PSRR PC4, PC5, H1S>H2S>H3S>H4S
+ * 0801E6 0E0004 W FF -> PADDR Port A all Outputs
+ * 0801E6 0E0006 W 00 -> PBDDR Port B all Inputs
+ * 0801EA 0E000C W 60 -> PACR Port A Mode 01, pin def, dbfr H1 data rec, H2 status/int, H2 output neg, H2S clrd
+ * 0801F0 0E000E W A0 -> PBCR Port B mode 1x, H4 output neg, H4S clrd, H3 int dis, H3 edg input, H3S set by assrt edg
+ * 0801F6 0E0000 W 30 -> PGCR H34 enable, H12enable
+ * 0801FC 0E000E W A8 -> PBCR +H4 asserted
+ * 08020A 0E000E W A0 -> PBCR +H4 negated
+ *
+ * Upon PA (Printer Attach) command enabling the Centronics printer mode
+ * ---------------------------------------------------------------------
+ * 081DB4 0E0011 W D0 -> PADR Data to Port A
+ * 081DB8 0E000D W 68 -> PACR H2 output asserted Centronics Strobe
+ * 081DC0 0E000D W 60 -> PACR H2 output negated
+ * 081DD0 0E0013 R 00 <- PBDR Port B polled for 01 (data) & 03 (mask)
+ *
+ */
+
+/* Centronics ACK handler
+ * The centronics ack signal is expected by the ROM to arrive at H1 input line
+ */
+void vme_sys68k_cpu1_card_device::centronics_ack_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_ack = state;
+ m_pit->h1_set(state);
+}
+
+/* Centronics BUSY handler
+ * The centronics busy signal is not used by the ROM driver afaik
+ */
+void vme_sys68k_cpu1_card_device::centronics_busy_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_busy = state;
+}
+
+/* Centronics PERROR handler
+ * The centronics perror signal is not used by the ROM driver afaik
+ */
+void vme_sys68k_cpu1_card_device::centronics_perror_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_perror = state;
+}
+
+/* Centronics SELECT handler
+ * The centronics select signal is expected by the ROM on Port B bit 0
+ */
+void vme_sys68k_cpu1_card_device::centronics_select_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_select = state;
+ m_pit->portb_setbit(0, state);
+}
+
+/* Start it up */
+void vme_sys68k_cpu1_card_device::device_start()
+{
+ LOG("%s\n", FUNCNAME);
+
+ save_item(NAME(m_centronics_busy));
+ save_item(NAME(m_centronics_ack));
+ save_item(NAME(m_centronics_select));
+ save_item(NAME(m_centronics_perror));
+
+ /* Map user ROM/RAM socket(s) */
+ if (m_cart->exists())
+ {
+ m_usrrom = (uint16_t*)m_cart->get_rom_base();
+#if 0 // This should be the correct way but produces odd and even bytes swapped
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
+#else // So we install a custom very inefficient handler for now until we understand how to solve the problem better
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*this, FUNC(vme_sys68k_cpu1_card_device::read16_rom)));
+#endif
+ }
+}
+
+/* Reset it */
+void vme_sys68k_cpu1_card_device::device_reset()
+{
+ LOG("%s\n", FUNCNAME);
+
+ // Set up the BRG divider. RSA is a jumper setting and RSB is always set High
+ m_brg->rsa_w(m_serial_brf->read() == 0x80 ? ASSERT_LINE : CLEAR_LINE);
+ m_brg->rsb_w(ASSERT_LINE);
+
+ // Disable all configured timers, only enabling the used ones
+ m_brg->timer_disable_all();
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p3->read(), true);
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p4->read(), true);
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p5->read(), true);
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
+}
+
+/* A very inefficient User cart emulation of two 8 bit sockets (odd and even) */
+uint16_t vme_sys68k_cpu1_card_device::read16_rom(offs_t offset)
+{
+ offset = offset % m_cart->common_get_size("rom"); // Don't read outside buffer...
+ return swapendian_int16(m_usrrom [offset]);
+}
+
+/* 10. The VMEbus (text from board documentation)
+ * ---------------
+ * The implemented VMEbus Interface includes 24 address, 16 data,
+ * 6 address modifier and the asynchronous control signals.
+ * A single level bus arbiter is provided to build multi master
+ * systems. In addition to the bus arbiter, a separate slave bus
+ * arbitration allows selection of the arbitration level (0-3).
+ *
+ * The address modifier range .,Short 110 Access can be selected
+ * via a jumper for variable system generation. The 7 interrupt
+ * request levels of the VMEbus are fully supported from the
+ * SYS68K1CPU-1 B/D. For multi-processing, each IRQ signal can be
+ * enabled/disabled via a jumper field.
+ *
+ * Additionally, the SYS68K1CPU-1 B/D supports the ACFAIL, SYSRESET,
+ * SYSFAIL and SYSCLK signal (16 MHz).
+ */
+
+/* Dummy VME access methods until the VME bus device is ready for use */
+uint16_t vme_sys68k_cpu1_card_device::vme_a24_r()
+{
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_sys68k_cpu1_card_device::vme_a24_w(uint16_t data)
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+uint16_t vme_sys68k_cpu1_card_device::vme_a16_r()
+{
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_sys68k_cpu1_card_device::vme_a16_w(uint16_t data)
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+/*
+ * Serial port clock sources can all be driven by different or the same output(s) of the MC14411
+ */
+void vme_sys68k_cpu1_card_device::write_acia_clocks(int id, int state)
+{
+ if (id == m_serial_p3->read())
+ {
+ m_aciahost->write_txc(state);
+ m_aciahost->write_rxc(state);
+ }
+ if (id == m_serial_p4->read())
+ {
+ m_aciaterm->write_txc(state);
+ m_aciaterm->write_rxc(state);
+ }
+ if (id == m_serial_p5->read())
+ {
+ m_aciaremt->write_txc(state);
+ m_aciaremt->write_rxc(state);
+ }
+}
+
+/*
+ * 4. The USER Area (Text from the board manual)
+ The USER area contains two 28 pin sockets with JEDEC compatible pin out.
+ To allow the usage of static RAM's, the access to the USER area is byte
+ oriented. Table 3. lists the usable device types.
+
+ Bits Bytes EPROM SRAM
+ --------------------------
+ 2Kx16 4 Kbyte 2716 6116
+ 4Kx16 8 Kbyte 2732
+ 8Kx16 16 Kbyte 2764 6264
+ 16Kx16 32 Kbyte 27128
+ 32Kx16 64 Kbyte 27256
+ --------------------------
+*/
+// Implementation of static 2 x 64K EPROM in sockets J10/J11 as 16 bit wide cartridge for easier
+// software handling. TODO: make configurable according to table above.
+void vme_sys68k_cpu1_card_device::fccpu1_eprom_sockets(machine_config &config)
+{
+ generic_cartslot_device &exp_rom1(GENERIC_CARTSLOT(config, "exp_rom1", generic_plain_slot, "fccpu1_cart", "bin,rom"));
+ exp_rom1.set_width(GENERIC_ROM16_WIDTH);
+ exp_rom1.set_endian(ENDIANNESS_BIG);
+ exp_rom1.set_device_load(FUNC(vme_sys68k_cpu1_card_device::exp1_load));
+// SOFTWARE_LIST(config, "cart_list").set_original("fccpu1_cart");
+}
+
+/***************************
+ Rom loading functions
+****************************/
+std::pair<std::error_condition, std::string> vme_sys68k_cpu1_card_device::force68k_load_cart(device_image_interface &image, generic_slot_device *slot)
+{
+ uint32_t size = slot->common_get_size("rom");
+
+ if (size > 0x2'0000) // Max 128Kb
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Cartridge size %d exceeds max size (128K)", size));
+ }
+
+ slot->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_BIG);
+ slot->common_load_rom(slot->get_rom_base(), size, "rom");
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+/*
+ * Machine configuration
+ */
+void vme_sys68k_cpu1_card_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68000(config, m_maincpu, XTAL(16'000'000) / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+
+ /* P3/Host Port config
+ * LO command causes ROM monitor to expect S-records on HOST port by default
+ * Implementation through nullmodem currently does not support handshakes so
+ * the ROM monitor is over-run while checking for checksums etc if used with
+ * UI mount <file> feature.
+ */
+ ACIA6850(config, m_aciahost, 0);
+ m_aciahost->txd_handler().set("rs232host", FUNC(rs232_port_device::write_txd));
+ m_aciahost->rts_handler().set("rs232host", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232host(RS232_PORT(config, "rs232host", default_rs232_devices, "null_modem"));
+ rs232host.rxd_handler().set(m_aciahost, FUNC(acia6850_device::write_rxd));
+ rs232host.cts_handler().set(m_aciahost, FUNC(acia6850_device::write_cts));
+
+ /* P4/Terminal Port config */
+ ACIA6850(config, m_aciaterm, 0);
+ m_aciaterm->txd_handler().set("rs232trm", FUNC(rs232_port_device::write_txd));
+ m_aciaterm->rts_handler().set("rs232trm", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232trm(RS232_PORT(config, "rs232trm", default_rs232_devices, "terminal"));
+ rs232trm.rxd_handler().set(m_aciaterm, FUNC(acia6850_device::write_rxd));
+ rs232trm.cts_handler().set(m_aciaterm, FUNC(acia6850_device::write_cts));
+
+ /* P5/Remote Port config */
+ ACIA6850(config, m_aciaremt, 0);
+
+ /* Bit Rate Generator */
+ MC14411(config, m_brg, XTAL(1'843'200));
+ m_brg->out_f<1>().set(FUNC(vme_sys68k_cpu1_card_device::write_f1_clock));
+ m_brg->out_f<3>().set(FUNC(vme_sys68k_cpu1_card_device::write_f3_clock));
+ m_brg->out_f<5>().set(FUNC(vme_sys68k_cpu1_card_device::write_f5_clock));
+ m_brg->out_f<7>().set(FUNC(vme_sys68k_cpu1_card_device::write_f7_clock));
+ m_brg->out_f<8>().set(FUNC(vme_sys68k_cpu1_card_device::write_f8_clock));
+ m_brg->out_f<9>().set(FUNC(vme_sys68k_cpu1_card_device::write_f9_clock));
+ m_brg->out_f<11>().set(FUNC(vme_sys68k_cpu1_card_device::write_f11_clock));
+ m_brg->out_f<13>().set(FUNC(vme_sys68k_cpu1_card_device::write_f13_clock));
+ m_brg->out_f<15>().set(FUNC(vme_sys68k_cpu1_card_device::write_f15_clock));
+
+ /* RTC Real Time Clock device */
+ MM58167(config, m_rtc, XTAL(32'768));
+
+ /* PIT Parallel Interface and Timer device, assuming strapped for on board clock */
+ PIT68230(config, m_pit, XTAL(16'000'000) / 2);
+ m_pit->pa_out_callback().set("cent_data_out", FUNC(output_latch_device::write));
+ m_pit->h2_out_callback().set(m_centronics, FUNC(centronics_device::write_strobe));
+
+ // Centronics
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->ack_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_ack_w));
+ m_centronics->busy_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_busy_w));
+ m_centronics->perror_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_perror_w));
+ m_centronics->select_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_select_w));
+
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ m_centronics->set_output_latch(latch);
+
+ // EPROM sockets
+ fccpu1_eprom_sockets(config);
+}
+
+#if 0 /*
+ * CPU-6 family is device and adressmap compatible with CPU-1 but with additions
+ * such as an optional 68881 FPU
+ */
+void vme_sys68k_cpu1_card_device::fccpu6(machine_config &config)
+{
+ M68000(config, m_maincpu, XTAL(8'000'000)); /* Jumper B10 Mode B */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6a(machine_config &config)
+{
+ M68000(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6v(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(8'000'000)); /* Jumper B10 Mode B */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6va(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6vb(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+#endif
+
+/* ROM definitions */
+ROM_START (sys68k_cpu1)
+ ROM_REGION16_BE(0x20000, "eprom", 0)
+ ROM_DEFAULT_BIOS("forcebug-1.1")
+
+ ROM_SYSTEM_BIOS(0, "forcemon-1.0l", "Force Computers SYS68K/CPU-1 Force Monitor 1.0L")
+ ROMX_LOAD ("fccpu1v1.0l.j8.bin", 0x0001, 0x2000, CRC (3ac6f08f) SHA1 (502f6547b508d8732bd68bbbb2402d8c30fefc3b), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD ("fccpu1v1.0l.j9.bin", 0x0000, 0x2000, CRC (035315fb) SHA1 (90dc44d9c25d28428233e6846da6edce2d69e440), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "forcebug-1.1", "Force Computers SYS68K/CPU-1 Force Debugger 1.1")
+ ROMX_LOAD ("fccpu1v1.1.j8.bin", 0x0001, 0x4000, CRC (116dcbf0) SHA1 (6870b71606933f84afe27ad031c651d201b93f99), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD ("fccpu1v1.1.j9.bin", 0x0000, 0x4000, CRC (aefd5b0b) SHA1 (1e24530a6d5dc4fb77fde67acae08d371e59fc0f), ROM_SKIP(1) | ROM_BIOS(1))
+
+/*
+ * System ROM terminal commands
+ *
+ * COMMAND SUMMARY DESCRIPTION (From CPU-1B datasheet, ROMs were dumped
+ * from a CPU-1 board so some features might be missing or different)
+ * ---------------------------------------------------------------------------
+ * BF <address1> <address2> <data> <CR> Block Fill memory - from addr1 through addr2 with data
+ * BM <address1> <address2> <address 3> <CR> Block Move - move from addr1 through addr2to addr3
+ * BR [<address> [; <count>] ... ] <CR> Set/display Breakpoint
+ * BS <address1> <address2> <data> <CR> Block Search - search addr1 through addr2 for data
+ * BT <address1> <address2> <CR> Block Test of memory
+ * DC <expression> <CR> Data Conversion
+ * DF <CR> Display Formatted registers
+ * DU [n] <address1> <address2>[<string>] <CR> Dump memory to object file
+ * GO or G [<address] <CR> Execute program.
+ * GD [<address] <CR> Go Direct
+ * GT <address> <CR> Exec prog: temporary breakpoint
+ * HE<CR> Help; display monitor commands
+ * LO [n] [;<options] <CR> Load Object file
+ * MD <address> [<count>] <CR> Memory Display
+ * MM or M <address> [<data<][;<options>] <CR> Memory Modify
+ * MS <address> <data1 > <data2> < ... <CR> Memory Set - starting at addr with data 1. data 2 ...
+ * NOBR [<address> ... ] <CR> Remove Breakpoint
+ * NOPA <CR> Printer Detach (Centronics on PIT/P2)
+ * OF <CR> Offset
+ * PA <CR> Printer Attach (Centronics on PIT/P2)
+ * PF[n] <CR> Set/display Port Format
+ * RM <CR> Register Modify
+ * TM [<exit character>] <CR> Transparent Mode
+ * TR OR T [<count] <CR> Trace
+ * TT <address> <CR> Trace: temporary breakpoint
+ * VE [n] [<string] <CR> Verify memory/object file
+ * ----------------------------------------------------------------------------
+ * .AO - .A7 [<expression] <CR> Display/set address register
+ * .00 - .07 [<expression] <CR> Display/set data register
+ * .RO - .R6 [<expression] <CR> Display/set offset register
+ * .PC [<expression] <CR> Display/set program counter
+ * .SR [<expression] <CR> Display/set status register
+ * .SS [<expression] <CR> Display/set supervisor stack
+ * .US [<expression] <CR> Display/set user stack
+ * ----------------------------------------------------------------------------
+ * MD <address> [<count>]; DI <CR> Disassemble memory location
+ * MM <address>; DI <CR> Disassemble/Assemble memory location
+ * ----------------------------------------------------------------------------
+ * Undocumented commands found in ROM table at address 0x80308
+ * .* No WHAT message displayed, no action seen.
+ */
+ROM_END
+
+/*
+ * CPU-6 ROMs were generally based om VMEPROM which contained the PDOS RTOS from Eyring Research.
+ * I don't have these but if anyone can dump them and send to me I can verify that they work as expected.
+ */
+#if 0
+ROM_START (fccpu6)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6a)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6v)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6va)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6vb)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+#endif
+
+const tiny_rom_entry *vme_sys68k_cpu1_card_device::device_rom_region() const
+{
+ return ROM_NAME(sys68k_cpu1);
+}
+
+ioport_constructor vme_sys68k_cpu1_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sys68k_cpu1);
+}
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+//COMP( 1983, fccpu1, 0, 0, fccpu1, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-1", MACHINE_NO_SOUND_HW )
+//COMP( 1989, fccpu6, 0, 0, fccpu6, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6a, 0, 0, fccpu6a, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6a", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6v, 0, 0, fccpu6v, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6v", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6va, 0, 0, fccpu6va, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6va", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6vb, 0, 0, fccpu6vb, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6vb", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )