diff options
Diffstat (limited to 'src/devices/bus/multibus/cpuap.cpp')
-rw-r--r-- | src/devices/bus/multibus/cpuap.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/devices/bus/multibus/cpuap.cpp b/src/devices/bus/multibus/cpuap.cpp new file mode 100644 index 00000000000..415b9e7e94d --- /dev/null +++ b/src/devices/bus/multibus/cpuap.cpp @@ -0,0 +1,214 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * Siemens S26361-D333 CPUAP processor board. + * + * This Multibus card was in Siemens PC-MX2 systems. It has a 10MHz NS32016 + * CPU with the complete set of NS32000 support chips and 1MiB of on-board RAM. + * The board connects to optional memory expansion boards through a dedicated + * connector (not the Multibus). It has no on-board UART, so depends on a SERAD + * or DUEAI board installed in the system to communicate with a console. + * + * Sources: + * - https://oldcomputers-ddns.org/public/pub/rechner/siemens/mx-rm/pc-mx2/manuals/pc-mx2_pc2000_9780_logik.pdf + * - https://mx300i.narten.de/view_board.cfm?5EF287A1ABC3F4DCAFEA2BC2FAB8C4000E50392BD499 + * + * TODO: + * - led output + * - nmi generation + * - figure out how to pass-through multibus addresses + */ + +#include "emu.h" +#include "cpuap.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(CPUAP, cpuap_device, "cpuap", "Siemens S26361-D333 CPUAP") + +cpuap_device::cpuap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, CPUAP, tag, owner, clock) + , device_multibus_interface(mconfig, *this) + , m_cpu(*this, "cpu") + , m_fpu(*this, "fpu") + , m_mmu(*this, "mmu") + , m_icu(*this, "icu") + , m_rtc(*this, "rtc") + , m_s7(*this, "S7") + , m_s8(*this, "S8") + , m_boot(*this, "boot") +{ +} + +// processor diagnostic register +enum prdia_mask : u8 +{ + LED1 = 0x01, + LED2 = 0x02, + LED3 = 0x04, + LED4 = 0x08, + LED5 = 0x10, + LED6 = 0x20, + ERRORLED = 0x40, + ENNMI = 0x80, +}; + +enum nmi_mask : u8 +{ + PAR2 = 0x01, + DEBUGI = 0x02, + ACF = 0x04, + PERLO = 0x08, // parity error lo + PERHI = 0x10, // parity error hi + BTIMOUT = 0x20, // bus timeout + INT7 = 0x40, +}; + +ROM_START(cpuap) + ROM_REGION16_LE(0x10000, "eprom", 0) + ROM_SYSTEM_BIOS(0, "rev9", "D333 Monitor Rev 9.0 16.06.1988") + ROMX_LOAD("361d0333d053__e01735_ine.d53", 0x0000, 0x4000, CRC(b5eefb64) SHA1(a71a7daf9a8f0481d564bfc4d7ed5eb955f8665f), ROM_SKIP(1) | ROM_BIOS(0)) + ROMX_LOAD("361d0333d054__e01725_ine.d54", 0x0001, 0x4000, CRC(3a3c6b6e) SHA1(5302fd79c89e0b4d164c639e2d73f4b9a279ddcb), ROM_SKIP(1) | ROM_BIOS(0)) + ROMX_FILL(0x8000, 0x8000, 0xff, ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "rev3", "D333 Monitor Rev 3 09.12.1985") + ROMX_LOAD("d333__d56_g53__lb.d56", 0x0000, 0x2000, CRC(0892ff90) SHA1(e84ceb8eb3c13de3692297c46632dbfafaad675f), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("d333__d55_g53__hb.d55", 0x0001, 0x2000, CRC(821e1e41) SHA1(0800249eab8db490c1fb6fea6d65bc7e874c9a0c), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_FILL(0x4000, 0xc000, 0xff, ROM_BIOS(1)) +ROM_END + +static INPUT_PORTS_START(cpuap) + PORT_START("S7") + + // Offen: Ausgabe des Urladers über Diagnose-Stecker, keine SERAD/G Baugruppe gesteckt + // Open: boot loader output via diagnostic plug, no SERAD/G module plugged in + PORT_DIPNAME(0x80, 0x00, "Diagnostic") PORT_DIPLOCATION("S7:8") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x80, DEF_STR(On)) + + // Offen: Monitor-Programm nach Testende + // Open: enter monitor after test + PORT_DIPNAME(0x40, 0x00, "Boot Option") PORT_DIPLOCATION("S7:7") + PORT_DIPSETTING(0x00, "Disk") + PORT_DIPSETTING(0x40, "Monitor") + + PORT_DIPNAME(0x20, 0x00, "S7:5") PORT_DIPLOCATION("S7:6") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x20, DEF_STR(On)) + PORT_DIPNAME(0x10, 0x00, "S7:4") PORT_DIPLOCATION("S7:5") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x10, DEF_STR(On)) + PORT_DIPNAME(0x08, 0x00, "S7:3") PORT_DIPLOCATION("S7:4") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x08, DEF_STR(On)) + PORT_DIPNAME(0x04, 0x00, "S7:2") PORT_DIPLOCATION("S7:3") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x04, DEF_STR(On)) + PORT_DIPNAME(0x02, 0x00, "S7:1") PORT_DIPLOCATION("S7:2") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x02, DEF_STR(On)) + + // Offen: kein Reboot nach Systemabsturz + // Open: no reboot after system crash + PORT_DIPNAME(0x01, 0x00, "S7:0") PORT_DIPLOCATION("S7:1") // S7:0 not allowed, causes crash in the dips menu + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(0x01, DEF_STR(On)) + + PORT_START("S8") + PORT_DIPNAME(0x01, 0x00, "IRQ 7") + PORT_DIPSETTING(0x00, "ICU IR11") + PORT_DIPSETTING(0x01, "NMI") +INPUT_PORTS_END + +const tiny_rom_entry *cpuap_device::device_rom_region() const +{ + return ROM_NAME(cpuap); +} + +ioport_constructor cpuap_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(cpuap); +} + +void cpuap_device::device_start() +{ +} + +void cpuap_device::device_reset() +{ + m_boot.select(0); + m_nmi = 0xff; +} + +void cpuap_device::bus_timeout(u8 data) +{ + m_nmi &= ~BTIMOUT; + + if (m_prdia & ENNMI) + m_cpu->set_input_line(INPUT_LINE_NMI, 1); +} + +void cpuap_device::device_add_mconfig(machine_config &config) +{ + NS32016(config, m_cpu, 20_MHz_XTAL / 2); + m_cpu->set_addrmap(0, &cpuap_device::cpu_map<0>); + m_cpu->set_addrmap(4, &cpuap_device::cpu_map<4>); + + NS32081(config, m_fpu, 20_MHz_XTAL / 2); + m_cpu->set_fpu(m_fpu); + + NS32082(config, m_mmu, 20_MHz_XTAL / 2); + m_cpu->set_mmu(m_mmu); + + NS32202(config, m_icu, 20_MHz_XTAL / 2); + m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0).invert(); + + int_callback<0>().set(m_icu, FUNC(ns32202_device::ir_w<0>)); + int_callback<1>().set(m_icu, FUNC(ns32202_device::ir_w<1>)); + int_callback<2>().set(m_icu, FUNC(ns32202_device::ir_w<3>)); + int_callback<3>().set(m_icu, FUNC(ns32202_device::ir_w<4>)); + int_callback<4>().set(m_icu, FUNC(ns32202_device::ir_w<6>)); + int_callback<5>().set(m_icu, FUNC(ns32202_device::ir_w<7>)); + int_callback<6>().set(m_icu, FUNC(ns32202_device::ir_w<8>)); + int_callback<7>().set([this](int state) { m_s8->read() ? m_cpu->set_input_line(INPUT_LINE_NMI, !state) : m_icu->ir_w<11>(state); }); + + MC146818(config, m_rtc, 32.768_kHz_XTAL); +} + +template <unsigned ST> void cpuap_device::cpu_map(address_map &map) +{ + if (ST == 0) + { + map(0x000000, 0x0fffff).view(m_boot); + + m_boot[0](0x000000, 0x00ffff).rom().region("eprom", 0); + m_boot[1](0x000000, 0x0fffff).ram(); + + //map(0x100000, 0x3fffff); // first memory expansion + //map(0x400000, 0x6fffff); // second memory expansion + + map(0x700000, 0xdfffff).w(FUNC(cpuap_device::bus_timeout)); + + map(0xe00000, 0xefffff).rw(FUNC(cpuap_device::bus_mem_r), FUNC(cpuap_device::bus_mem_w)); // multibus mem + map(0xf00000, 0xf0ffff).rw(FUNC(cpuap_device::bus_pio_r), FUNC(cpuap_device::bus_pio_w)); // multibus i/o + + //map(0xf10000, 0xfdffff); // unused + map(0xfe0000, 0xfeffff).rom().region("eprom", 0); + + //map(0xff0000, 0xf7ffff); // unused + map(0xff8000, 0xff803f).rw(m_rtc, FUNC(mc146818_device::read_direct), FUNC(mc146818_device::write_direct)); + map(0xff8100, 0xff8100).lr8([this]() { return m_s7->read(); }, "s7_r"); + map(0xff8200, 0xff8200).lw8([this](u8 data) { LOG("prdia_w 0x%02x led 0x%x (%s)\n", data, ~data & 0x3f, machine().describe_context()); m_prdia = data; }, "prdia_w"); + map(0xff8300, 0xff8300).lrw8([this]() { return m_poff; }, "poff_r", [this](u8 data) { m_poff = data & 3; }, "poff_w"); // 3 pohopofi - power off interrupt? + //map(0xff8400, 0xff840f); // 4 csuart + map(0xff8500, 0xff8500).lw8([this](u8 data) { m_boot.select(BIT(data, 0)); }, "mapprom_w"); + map(0xff8600, 0xff863f).m(m_icu, FUNC(ns32202_device::map<0>)).umask16(0x00ff); + map(0xff8700, 0xff8700).lrw8( + [this]() { return m_nmi; }, "nmi_r", + [this](u8 data) { LOG("nmi_w 0x%02x (%s)\n", data, machine().describe_context()); m_nmi = 0xff; }, "nmi_w"); + } + + map(0xfffe00, 0xfffeff).m(m_icu, FUNC(ns32202_device::map<BIT(ST, 1)>)).umask16(0x00ff); +} |