mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
pcmx2: boot to monitor
* refactored into cards * boots to firmware monitor
This commit is contained in:
parent
1f6c4266e2
commit
2b5755845b
@ -4647,6 +4647,10 @@ if (BUSES["MULTIBUS"]~=null) then
|
||||
MAME_DIR .. "src/devices/bus/multibus/multibus.h",
|
||||
MAME_DIR .. "src/devices/bus/multibus/isbc202.cpp",
|
||||
MAME_DIR .. "src/devices/bus/multibus/isbc202.h",
|
||||
MAME_DIR .. "src/devices/bus/multibus/cpuap.cpp",
|
||||
MAME_DIR .. "src/devices/bus/multibus/cpuap.h",
|
||||
MAME_DIR .. "src/devices/bus/multibus/serad.cpp",
|
||||
MAME_DIR .. "src/devices/bus/multibus/serad.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
222
src/devices/bus/multibus/cpuap.cpp
Normal file
222
src/devices/bus/multibus/cpuap.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
// 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")
|
||||
, m_installed(false)
|
||||
{
|
||||
}
|
||||
|
||||
// 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:7")
|
||||
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:6")
|
||||
PORT_DIPSETTING(0x00, "Disk")
|
||||
PORT_DIPSETTING(0x40, "Monitor")
|
||||
|
||||
PORT_DIPNAME(0x20, 0x00, "S7:5") PORT_DIPLOCATION("S7:5")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x20, DEF_STR(On))
|
||||
PORT_DIPNAME(0x10, 0x00, "S7:4") PORT_DIPLOCATION("S7:4")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x10, DEF_STR(On))
|
||||
PORT_DIPNAME(0x08, 0x00, "S7:3") PORT_DIPLOCATION("S7:3")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x08, DEF_STR(On))
|
||||
PORT_DIPNAME(0x04, 0x00, "S7:2") PORT_DIPLOCATION("S7:2")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x04, DEF_STR(On))
|
||||
PORT_DIPNAME(0x02, 0x00, "S7:1") PORT_DIPLOCATION("S7:1")
|
||||
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:0")
|
||||
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()
|
||||
{
|
||||
if (!m_installed)
|
||||
{
|
||||
// TODO: what's exposed to the Multibus?
|
||||
|
||||
m_bus->int_callback<0>().set(m_icu, FUNC(ns32202_device::ir_w<0>));
|
||||
m_bus->int_callback<1>().set(m_icu, FUNC(ns32202_device::ir_w<1>));
|
||||
m_bus->int_callback<2>().set(m_icu, FUNC(ns32202_device::ir_w<3>));
|
||||
m_bus->int_callback<3>().set(m_icu, FUNC(ns32202_device::ir_w<4>));
|
||||
m_bus->int_callback<4>().set(m_icu, FUNC(ns32202_device::ir_w<6>));
|
||||
m_bus->int_callback<5>().set(m_icu, FUNC(ns32202_device::ir_w<7>));
|
||||
m_bus->int_callback<6>().set(m_icu, FUNC(ns32202_device::ir_w<8>));
|
||||
m_bus->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); });
|
||||
|
||||
m_installed = true;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
60
src/devices/bus/multibus/cpuap.h
Normal file
60
src/devices/bus/multibus/cpuap.h
Normal file
@ -0,0 +1,60 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_BUS_MULTIBUS_CPUAP_H
|
||||
#define MAME_BUS_MULTIBUS_CPUAP_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "multibus.h"
|
||||
|
||||
#include "cpu/ns32000/ns32000.h"
|
||||
#include "machine/ns32081.h"
|
||||
#include "machine/ns32082.h"
|
||||
#include "machine/ns32202.h"
|
||||
#include "machine/mc146818.h"
|
||||
|
||||
|
||||
class cpuap_device
|
||||
: public device_t
|
||||
, public device_multibus_interface
|
||||
{
|
||||
public:
|
||||
cpuap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
template <unsigned ST> void cpu_map(address_map &map);
|
||||
|
||||
void bus_timeout(u8 data);
|
||||
void bus_mem_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_PROGRAM).write_word(0xe00000 | offset << 1, data, mem_mask); }
|
||||
u16 bus_mem_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_PROGRAM).read_word(0xe00000 | offset << 1, mem_mask); }
|
||||
void bus_pio_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_IO).write_word(offset << 1, data, mem_mask); }
|
||||
u16 bus_pio_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_IO).read_word(offset << 1, mem_mask); }
|
||||
|
||||
required_device<ns32016_device> m_cpu;
|
||||
required_device<ns32081_device> m_fpu;
|
||||
required_device<ns32082_device> m_mmu;
|
||||
required_device<ns32202_device> m_icu;
|
||||
required_device<mc146818_device> m_rtc;
|
||||
required_ioport m_s7;
|
||||
required_ioport m_s8;
|
||||
memory_view m_boot;
|
||||
|
||||
u8 m_prdia;
|
||||
u8 m_poff;
|
||||
u8 m_nmi;
|
||||
|
||||
bool m_installed;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(CPUAP, cpuap_device)
|
||||
|
||||
#endif // MAME_BUS_MULTIBUS_CPUAP_H
|
204
src/devices/bus/multibus/serad.cpp
Normal file
204
src/devices/bus/multibus/serad.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Siemens S26361-D279 SERAD serial interface board.
|
||||
*
|
||||
* This Multibus card was used with several Multibus-based computers from
|
||||
* Siemens, including the PC-MX2, MX300 and MX500. It has 3 SCN2681 DUARTs,
|
||||
* giving a total of two V24 and four SS97 serial ports. These are controlled
|
||||
* by an on-board 8085A microcontroller, with a dual-port RAM mailbox used to
|
||||
* communicate with the host.
|
||||
*
|
||||
* 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?5EF287A1ABC3F4DCAFEA2BC2FAB8C504041A
|
||||
*
|
||||
* TODO:
|
||||
* - multibus lock/unlock/interrupt
|
||||
* - SS97 ports with power on/reset signals
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "serad.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SERAD, serad_device, "serad", "Siemens S26361-D279 SERAD")
|
||||
|
||||
serad_device::serad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SERAD, tag, owner, clock)
|
||||
, device_multibus_interface(mconfig, *this)
|
||||
, m_cpu(*this, "cpu")
|
||||
, m_mbx(*this, "mbx")
|
||||
, m_rst65(*this, "rst65")
|
||||
, m_duart(*this, "duart%u", 0U)
|
||||
, m_port(*this, "port%u", 0U)
|
||||
, m_installed(false)
|
||||
{
|
||||
}
|
||||
|
||||
ROM_START(serad)
|
||||
ROM_REGION(0x2000, "cpu", 0)
|
||||
ROM_LOAD("361d0279d031__e00422_tex.d31", 0x0000, 0x2000, CRC(369f5fd1) SHA1(6a1c2d351d5552d54d835b7726b3f9b921605d0e))
|
||||
ROM_END
|
||||
|
||||
static INPUT_PORTS_START(serad)
|
||||
PORT_START("MEM")
|
||||
PORT_DIPNAME(0xfff, 0xef7, "Base Address")
|
||||
PORT_DIPSETTING(0xef7, "EF7000")
|
||||
PORT_DIPSETTING(0xef6, "EF6000")
|
||||
PORT_DIPSETTING(0xef5, "EF5000")
|
||||
PORT_DIPSETTING(0xef4, "EF4000")
|
||||
PORT_DIPSETTING(0xef3, "EF3000")
|
||||
|
||||
PORT_START("PIO")
|
||||
PORT_DIPNAME(0xff, 0x10, "I/O Address")
|
||||
PORT_DIPSETTING(0x0f, "0F00")
|
||||
PORT_DIPSETTING(0x10, "1000")
|
||||
PORT_DIPSETTING(0x11, "1100")
|
||||
PORT_DIPSETTING(0x12, "1200")
|
||||
PORT_DIPSETTING(0x13, "1300")
|
||||
|
||||
PORT_START("IRQ")
|
||||
PORT_DIPNAME(0xff, 0x00, "Interrupt")
|
||||
PORT_DIPSETTING(0x00, "None")
|
||||
PORT_DIPSETTING(0x01, "0")
|
||||
PORT_DIPSETTING(0x02, "1")
|
||||
PORT_DIPSETTING(0x04, "2")
|
||||
PORT_DIPSETTING(0x08, "3")
|
||||
PORT_DIPSETTING(0x10, "4")
|
||||
PORT_DIPSETTING(0x20, "5")
|
||||
PORT_DIPSETTING(0x40, "6")
|
||||
PORT_DIPSETTING(0x80, "7")
|
||||
INPUT_PORTS_END
|
||||
|
||||
const tiny_rom_entry *serad_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(serad);
|
||||
}
|
||||
|
||||
ioport_constructor serad_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(serad);
|
||||
}
|
||||
|
||||
void serad_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void serad_device::device_reset()
|
||||
{
|
||||
if (!m_installed)
|
||||
{
|
||||
u32 const mem = ioport("MEM")->read() << 12;
|
||||
u32 const pio = ioport("PIO")->read() << 8;
|
||||
|
||||
m_bus->space(AS_PROGRAM).install_ram(mem, mem | 0xfff, m_mbx.target());
|
||||
m_bus->space(AS_IO).install_write_handler(pio, pio | 0xff, write8smo_delegate(*this, &serad_device::rst55_w<1>, "serad_device::rst55_w"));
|
||||
|
||||
m_installed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void serad_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
I8085A(config, m_cpu, 20_MHz_XTAL / 2); // P8085AH-2
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &serad_device::mem_map);
|
||||
m_cpu->set_addrmap(AS_IO, &serad_device::pio_map);
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, m_rst65);
|
||||
m_rst65->output_handler().set_inputline(m_cpu, I8085_RST65_LINE);
|
||||
|
||||
SCN2681(config, m_duart[0], 7.3728_MHz_XTAL / 2);
|
||||
SCN2681(config, m_duart[1], 7.3728_MHz_XTAL / 2);
|
||||
SCN2681(config, m_duart[2], 7.3728_MHz_XTAL / 2);
|
||||
|
||||
m_duart[0]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<0>));
|
||||
m_duart[1]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<1>));
|
||||
m_duart[2]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<2>));
|
||||
|
||||
RS232_PORT(config, m_port[0], default_rs232_devices, nullptr); // SS97
|
||||
RS232_PORT(config, m_port[1], default_rs232_devices, nullptr); // SS97
|
||||
RS232_PORT(config, m_port[2], default_rs232_devices, nullptr); // V24
|
||||
RS232_PORT(config, m_port[3], default_rs232_devices, nullptr); // SS97
|
||||
RS232_PORT(config, m_port[4], default_rs232_devices, nullptr); // SS97
|
||||
RS232_PORT(config, m_port[5], default_rs232_devices, nullptr); // V24
|
||||
|
||||
m_duart[0]->a_tx_cb().set(m_port[0], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[0]->b_tx_cb().set(m_port[1], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[0]->outport_cb().set(
|
||||
[this](u8 data)
|
||||
{
|
||||
// clear 0
|
||||
// clear 1
|
||||
// -
|
||||
// -
|
||||
m_duart[1]->ip0_w(BIT(data, 4)); // rxrdy0
|
||||
m_duart[1]->ip1_w(BIT(data, 5)); // rxrdy1
|
||||
m_duart[0]->ip0_w(BIT(data, 6)); // txrdy0
|
||||
m_duart[0]->ip1_w(BIT(data, 7)); // txrdy1
|
||||
}
|
||||
);
|
||||
|
||||
m_duart[1]->a_tx_cb().set(m_port[2], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[1]->b_tx_cb().set(m_port[3], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[1]->outport_cb().set(
|
||||
[this](u8 data)
|
||||
{
|
||||
m_port[2]->write_rts(BIT(data, 0)); // s2.k2 (rts)
|
||||
// clear 3
|
||||
// -
|
||||
m_port[2]->write_dtr(BIT(data, 3)); // s1.k2 (dtr)
|
||||
m_duart[1]->ip2_w(BIT(data, 4)); // rxrdy2
|
||||
m_duart[1]->ip3_w(BIT(data, 5)); // rxrdy3
|
||||
m_duart[0]->ip2_w(BIT(data, 6)); // txrdy2
|
||||
m_duart[0]->ip3_w(BIT(data, 7)); // txrdy3
|
||||
}
|
||||
);
|
||||
|
||||
m_duart[2]->a_tx_cb().set(m_port[4], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[2]->b_tx_cb().set(m_port[5], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[2]->outport_cb().set(
|
||||
[this](u8 data)
|
||||
{
|
||||
// clear 4
|
||||
m_port[5]->write_rts(BIT(data, 1)); // s2.k5 (rts)
|
||||
// resled
|
||||
m_port[5]->write_dtr(BIT(data, 3)); // s1.k5 (dtr)
|
||||
m_duart[1]->ip4_w(BIT(data, 4)); // rxrdy4
|
||||
m_duart[1]->ip5_w(BIT(data, 5)); // rxrdy5
|
||||
m_duart[0]->ip4_w(BIT(data, 6)); // txrdy4
|
||||
m_duart[0]->ip5_w(BIT(data, 7)); // txrdy5
|
||||
}
|
||||
);
|
||||
|
||||
m_port[0]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_a_w));
|
||||
m_port[1]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_b_w));
|
||||
m_port[2]->rxd_handler().set(m_duart[1], FUNC(scn2681_device::rx_a_w));
|
||||
m_port[2]->cts_handler().set(m_duart[2], FUNC(scn2681_device::ip0_w));
|
||||
m_port[3]->rxd_handler().set(m_duart[1], FUNC(scn2681_device::rx_b_w));
|
||||
m_port[4]->rxd_handler().set(m_duart[2], FUNC(scn2681_device::rx_a_w));
|
||||
m_port[5]->rxd_handler().set(m_duart[2], FUNC(scn2681_device::rx_b_w));
|
||||
m_port[5]->cts_handler().set(m_duart[2], FUNC(scn2681_device::ip1_w));
|
||||
}
|
||||
|
||||
void serad_device::mem_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x1fff).rom().region("cpu", 0).mirror(0x2000);
|
||||
map(0x4000, 0x4fff).ram().share("mbx").mirror(0x3000);
|
||||
map(0x8000, 0x87ff).ram();
|
||||
}
|
||||
|
||||
void serad_device::pio_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x0f).rw(m_duart[0], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 0
|
||||
map(0x10, 0x1f).rw(m_duart[1], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 2
|
||||
map(0x20, 0x2f).rw(m_duart[2], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 4
|
||||
//map(0x30, 0x3f); // TODO: multibus interrupt
|
||||
map(0x40, 0x4f).nopw(); // TODO: multibus lock
|
||||
map(0x50, 0x5f).nopw(); // TODO: multibus unlock
|
||||
map(0x60, 0x6f).w(FUNC(serad_device::rst55_w<0>));
|
||||
//map(0x70, 0x7f); // TODO: power
|
||||
}
|
49
src/devices/bus/multibus/serad.h
Normal file
49
src/devices/bus/multibus/serad.h
Normal file
@ -0,0 +1,49 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_BUS_MULTIBUS_SERAD_H
|
||||
#define MAME_BUS_MULTIBUS_SERAD_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "multibus.h"
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "machine/mc68681.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
class serad_device
|
||||
: public device_t
|
||||
, public device_multibus_interface
|
||||
{
|
||||
public:
|
||||
serad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
void mem_map(address_map &map);
|
||||
void pio_map(address_map &map);
|
||||
|
||||
template <unsigned S> void rst55_w(u8 data) { m_cpu->set_input_line(I8085_RST55_LINE, S); }
|
||||
void apzint_w(u8 data) { int_w(2, 0); }
|
||||
|
||||
required_device<i8085a_cpu_device> m_cpu;
|
||||
required_shared_ptr<u8> m_mbx;
|
||||
required_device<input_merger_any_high_device> m_rst65;
|
||||
required_device_array<scn2681_device, 3> m_duart;
|
||||
required_device_array<rs232_port_device, 6> m_port;
|
||||
|
||||
bool m_installed;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SERAD, serad_device)
|
||||
|
||||
#endif // MAME_BUS_MULTIBUS_SERAD_H
|
@ -5,25 +5,29 @@
|
||||
* Siemens PC-MX2
|
||||
*
|
||||
* Sources:
|
||||
* - http://www.cpu-ns32k.net/Siemens.html
|
||||
* - https://mx300i.narten.de/view_board.cfm?5EF287A1ABC3F4DCAFEA2BC2FAB8C4000E50392BD4C3E389826E8E68AC9F53F3BE16A107EFC767
|
||||
* - http://www.cpu-ns32k.net/Siemens.html
|
||||
* - https://oldcomputers-ddns.org/public/pub/rechner/siemens/mx-rm/pc-mx2/manuals/pc-mx2_betriebsanleitung_1987_(v2-1a).pdf
|
||||
* - https://oldcomputers-ddns.org/public/pub/rechner/siemens/mx-rm/pc-mx2/manuals/pc-mx2_pc2000_9780_logik.pdf
|
||||
*
|
||||
* TODO:
|
||||
* - skeleton only
|
||||
* - front panel
|
||||
* - storager
|
||||
*/
|
||||
/*
|
||||
* WIP notes:
|
||||
* - currently there's no disk controller, so only possible to boot into the monitor
|
||||
* - start with a terminal connected to SERAD port 0, i.e.: mame pcmx2 -slot:3:serad:port0 terminal
|
||||
* - configure terminal for 38400 bps, 7 data bits, odd parity
|
||||
* - set CPUAP board Boot Option to Monitor
|
||||
* - press Enter at the "*" prompt to display monitor help
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
// cpu board hardware
|
||||
#include "cpu/ns32000/ns32000.h"
|
||||
#include "machine/ns32081.h"
|
||||
#include "machine/ns32082.h"
|
||||
#include "machine/ns32202.h"
|
||||
#include "machine/mc146818.h"
|
||||
|
||||
// dueai board hardware
|
||||
#include "cpu/i86/i186.h"
|
||||
#include "machine/z80scc.h"
|
||||
#include "bus/multibus/multibus.h"
|
||||
#include "bus/multibus/cpuap.h"
|
||||
//#include "bus/multibus/dueai.h"
|
||||
#include "bus/multibus/serad.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
@ -35,14 +39,7 @@ class pcmx2_state : public driver_device
|
||||
public:
|
||||
pcmx2_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "cpu")
|
||||
, m_fpu(*this, "fpu")
|
||||
, m_mmu(*this, "mmu")
|
||||
, m_icu(*this, "icu")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_dueai_cpu(*this, "dueai_cpu")
|
||||
, m_dueai_scc(*this, "dueai_scc")
|
||||
, m_boot_view(*this, "boot_view")
|
||||
, m_bus(*this, "slot")
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,27 +48,12 @@ protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
// address maps
|
||||
template <unsigned ST> void cpu_map(address_map &map);
|
||||
void dueai_mem_map(address_map &map);
|
||||
void dueai_pio_map(address_map &map);
|
||||
|
||||
public:
|
||||
// machine config
|
||||
void pcmx2(machine_config &config);
|
||||
|
||||
protected:
|
||||
required_device<ns32016_device> m_cpu;
|
||||
required_device<ns32081_device> m_fpu;
|
||||
required_device<ns32082_device> m_mmu;
|
||||
required_device<ns32202_device> m_icu;
|
||||
required_device<mc146818_device> m_rtc;
|
||||
|
||||
required_device<i80186_cpu_device> m_dueai_cpu;
|
||||
required_device<z80scc_device> m_dueai_scc;
|
||||
|
||||
private:
|
||||
memory_view m_boot_view;
|
||||
required_device<multibus_device> m_bus;
|
||||
};
|
||||
|
||||
void pcmx2_state::machine_start()
|
||||
@ -80,72 +62,33 @@ void pcmx2_state::machine_start()
|
||||
|
||||
void pcmx2_state::machine_reset()
|
||||
{
|
||||
m_boot_view.select(0);
|
||||
}
|
||||
|
||||
template <unsigned ST> void pcmx2_state::cpu_map(address_map &map)
|
||||
static void pcmx2_cards(device_slot_interface &device)
|
||||
{
|
||||
if (ST == 0)
|
||||
{
|
||||
map(0x000000, 0x0fffff).view(m_boot_view);
|
||||
|
||||
m_boot_view[0](0x000000, 0x007fff).rom().region("eprom", 0);
|
||||
m_boot_view[1](0x000000, 0x0fffff).ram();
|
||||
}
|
||||
|
||||
map(0xfe0000, 0xfe7fff).rom().region("eprom", 0);
|
||||
|
||||
map(0xff8500, 0xff8500).lw8([this](u8 data) { m_boot_view.select(data); }, "boot_view_w");
|
||||
|
||||
map(0xfffe00, 0xfffeff).m(m_icu, FUNC(ns32202_device::map<BIT(ST, 1)>)).umask16(0x00ff);
|
||||
}
|
||||
|
||||
void pcmx2_state::dueai_mem_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x01ffff).ram();
|
||||
|
||||
map(0x0fe000, 0x0fffff).rom().region("dueai", 0);
|
||||
}
|
||||
|
||||
void pcmx2_state::dueai_pio_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x0003).rw(m_dueai_scc, FUNC(z80scc_device::ab_dc_r), FUNC(z80scc_device::ab_dc_w));
|
||||
device.option_add("cpuap", CPUAP);
|
||||
//device.option_add("dueai", DUEAI);
|
||||
device.option_add("serad", SERAD);
|
||||
}
|
||||
|
||||
void pcmx2_state::pcmx2(machine_config &config)
|
||||
{
|
||||
NS32016(config, m_cpu, 20_MHz_XTAL / 2);
|
||||
m_cpu->set_addrmap(0, &pcmx2_state::cpu_map<0>);
|
||||
m_cpu->set_addrmap(4, &pcmx2_state::cpu_map<4>);
|
||||
MULTIBUS(config, m_bus, 20_MHz_XTAL / 2);
|
||||
|
||||
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();
|
||||
|
||||
MC146818(config, m_rtc, 32.768_kHz_XTAL);
|
||||
|
||||
I80186(config, m_dueai_cpu, 16_MHz_XTAL / 2);
|
||||
m_dueai_cpu->set_addrmap(AS_PROGRAM, &pcmx2_state::dueai_mem_map);
|
||||
m_dueai_cpu->set_addrmap(AS_IO, &pcmx2_state::dueai_pio_map);
|
||||
|
||||
SCC8530N(config, m_dueai_scc, 7.3728_MHz_XTAL);
|
||||
MULTIBUS_SLOT(config, "slot:1", m_bus, pcmx2_cards, nullptr, false); // DTC 86-1 or Storager
|
||||
MULTIBUS_SLOT(config, "slot:2", m_bus, pcmx2_cards, nullptr, false);
|
||||
MULTIBUS_SLOT(config, "slot:3", m_bus, pcmx2_cards, "serad", false);
|
||||
MULTIBUS_SLOT(config, "slot:4", m_bus, pcmx2_cards, nullptr, false);
|
||||
MULTIBUS_SLOT(config, "slot:5", m_bus, pcmx2_cards, nullptr, false);
|
||||
MULTIBUS_SLOT(config, "slot:6", m_bus, pcmx2_cards, "cpuap", false);
|
||||
MULTIBUS_SLOT(config, "slot:7", m_bus, pcmx2_cards, nullptr, false); // MEM
|
||||
MULTIBUS_SLOT(config, "slot:8", m_bus, pcmx2_cards, nullptr, false);
|
||||
}
|
||||
|
||||
ROM_START(pcmx2)
|
||||
ROM_REGION16_LE(0x8000, "eprom", 0)
|
||||
ROMX_LOAD("361d0333d053__e01735_ine.d53", 0x0000, 0x4000, CRC(b5eefb64) SHA1(a71a7daf9a8f0481d564bfc4d7ed5eb955f8665f), ROM_SKIP(1))
|
||||
ROMX_LOAD("361d0333d054__e01725_ine.d54", 0x0001, 0x4000, CRC(3a3c6b6e) SHA1(5302fd79c89e0b4d164c639e2d73f4b9a279ddcb), ROM_SKIP(1))
|
||||
|
||||
ROM_REGION16_LE(0x2000, "dueai", 0)
|
||||
ROM_LOAD("d277__e00_410__d3_17e4.d61", 0x0000, 0x2000, CRC(31415348) SHA1(1407dac077b1f9aec5f9063711c3ab2c517cc9e8))
|
||||
ROM_END
|
||||
|
||||
}
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP(1986?, pcmx2, 0, 0, pcmx2, 0, pcmx2_state, empty_init, "Siemens", "PC-MX2", MACHINE_IS_SKELETON)
|
||||
COMP(1985, pcmx2, 0, 0, pcmx2, 0, pcmx2_state, empty_init, "Siemens", "PC-MX2", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
|
||||
|
Loading…
Reference in New Issue
Block a user