From b877d9c15ecb224cc52e070d7929fc26ac31323e Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 16 Aug 2023 18:49:12 +0700 Subject: vme/enp10: add new device [CJ, System Source Computer Museum] --- scripts/src/bus.lua | 2 + src/devices/bus/vme/enp10.cpp | 166 ++++++++++++++++++++++++++++++++++++++++++ src/devices/bus/vme/enp10.h | 51 +++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 src/devices/bus/vme/enp10.cpp create mode 100644 src/devices/bus/vme/enp10.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index c369983f01a..463f8169a55 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2641,6 +2641,8 @@ end if (BUSES["VME"]~=null) then files { + MAME_DIR .. "src/devices/bus/vme/enp10.cpp", + MAME_DIR .. "src/devices/bus/vme/enp10.h", MAME_DIR .. "src/devices/bus/vme/mvme187.cpp", MAME_DIR .. "src/devices/bus/vme/mvme187.h", MAME_DIR .. "src/devices/bus/vme/tp881v.cpp", diff --git a/src/devices/bus/vme/enp10.cpp b/src/devices/bus/vme/enp10.cpp new file mode 100644 index 00000000000..a0955a44ce8 --- /dev/null +++ b/src/devices/bus/vme/enp10.cpp @@ -0,0 +1,166 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * Communication Machinery Corporation Ethernet Node Processor (ENP-10) + * + * Sources: + * - Ethernet Node Processor ENP-30 Reference Guide (6213000-05B), Communication Machinery Corporation, November 15, 1988 + * + * TODO: + * - vme interface + * - address/interrupt configuration + * - verify registers + * - uart? + */ + +/* + * WIP + * --- + * - 0xef'8010-0xef'802f appears to be a uart, but doesn't match scn2681 per ENP-30 documentation? + * - following text is output to 0xef'008025 at startup: + * CMC ENP/10 CMOS - 112708 Bytes Free + * Ethernet Address: 02CF1F123456 + * Allocating 30 receive buffers + * Allocating 30 transmit buffers + */ + +#include "emu.h" +#include "enp10.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(CMC_ENP10, cmc_enp10_device, "cmc_enp10", "CMC ENP-10") + +cmc_enp10_device::cmc_enp10_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, CMC_ENP10, tag, owner, clock) + , device_vme_card_interface(mconfig, *this) + , m_cpu(*this, "cpu") + , m_net(*this, "net") + , m_led(*this, "led%u", 0U) + , m_boot(*this, "boot") +{ +} + +ROM_START(enp10) + ROM_REGION16_BE(0x4000, "eprom", 0) + ROM_SYSTEM_BIOS(0, "enp10", "CMC ENP/10 CMOS") + ROMX_LOAD("link_10_2.0_nh_rev.4.1h.u4", 0x0000, 0x2000, CRC(7532f2b1) SHA1(bdef6c525f451fbc67f3d4625c9db18975e7e1e4), ROM_SKIP(1) | ROM_BIOS(0)) // AM2764A + ROMX_LOAD("link_10_2.0_nh_rev.k4.1l.u3", 0x0001, 0x2000, CRC(f2decb78) SHA1(795623274bfff6273790c30445e4dca4064859ed), ROM_SKIP(1) | ROM_BIOS(0)) // AM2764A + + // hand-crafted prom containing address 02:cf:1f:12:34:56 + ROM_REGION16_BE(0x20, "mac", 0) + ROM_LOAD("mac.bin", 0x00, 0x20, CRC(99ac9577) SHA1(b4d6bba88dd376cc492738d57742628f42e9265e)) +ROM_END + +static INPUT_PORTS_START(enp10) +INPUT_PORTS_END + +const tiny_rom_entry *cmc_enp10_device::device_rom_region() const +{ + return ROM_NAME(enp10); +} + +ioport_constructor cmc_enp10_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(enp10); +} + +void cmc_enp10_device::device_start() +{ + m_led.resolve(); + + save_item(NAME(m_ier)); + save_item(NAME(m_tir)); + save_item(NAME(m_rir)); + save_item(NAME(m_uir)); + save_item(NAME(m_exr)); + save_item(NAME(m_csr)); + save_item(NAME(m_rer)); + save_item(NAME(m_hir)); +} + +void cmc_enp10_device::device_reset() +{ + m_boot.select(0); + + m_ier = 0; + m_tir = 0; + m_rir = 0; + m_uir = 0; + m_exr = 0; + m_csr = 0; + m_rer = 0; + m_hir = 0; +} + +void cmc_enp10_device::device_add_mconfig(machine_config &config) +{ + M68000(config, m_cpu, 10_MHz_XTAL / 2); + m_cpu->set_addrmap(AS_PROGRAM, &cmc_enp10_device::cpu_mem); + + AM7990(config, m_net, 20_MHz_XTAL / 2); + m_net->intr_out().set_inputline(m_cpu, INPUT_LINE_IRQ6).invert(); + m_net->dma_in().set([this](offs_t offset) { return m_cpu->space(0).read_word(offset); }); + m_net->dma_out().set([this](offs_t offset, u16 data, u16 mem_mask) { m_cpu->space(0).write_word(offset, data, mem_mask); }); +} + +void cmc_enp10_device::cpu_mem(address_map &map) +{ + map(0xf8'0000, 0xf8'3fff).rom().region("eprom", 0).mirror(0x02'0000); + + map(0x00'0000, 0xf1'ffff).view(m_boot); + // map 1k of eprom at 0x00'0000 + m_boot[0](0x00'0000, 0x00'0fff).rom().region("eprom", 0); + m_boot[0](0xf0'0000, 0xf1'ffff).ram().share("ram"); + + // map 1k of ram at 0x00'0000, unmap at 0xf0'0000 + m_boot[1](0x00'0000, 0x01'ffff).ram().share("ram"); + m_boot[1](0x00'1000, 0x01'ffff).unmaprw(); + m_boot[1](0xf0'0000, 0xf1'ffff).ram().share("ram"); + m_boot[1](0xf0'0000, 0xf0'0fff).unmaprw(); + + // uart: 16 byte registers 10-2f? + map(0xef'8010, 0xef'802f).noprw(); + + // fe'0080 vector? w:host vectored interrupt, r:slave address msb + + map(0xfe'00a0, 0xfe'00a1).umask16(0x00ff).lrw8( + [this]() { return m_csr; }, "csr_r", + [this](u8 data) + { + LOG("csr_w 0x%02x\n", data); + + m_led[0] = BIT(data, 6); // fail? + m_led[1] = BIT(data, 5); // run? + + m_csr = data; + }, "csr_w"); + + map(0xfe'00c0, 0xfe'00c1).umask16(0x00ff).lrw8(NAME([this]() { return m_ier; }), NAME([this](u8 data) { m_ier = data; interrupt(); })); + map(0xfe'00c2, 0xfe'00c3).umask16(0x00ff).lrw8(NAME([this]() { return m_tir; }), NAME([this](u8 data) { m_tir = data; interrupt(); })); + map(0xfe'00c4, 0xfe'00c5).umask16(0x00ff).lrw8(NAME([this]() { return m_rir; }), NAME([this](u8 data) { m_rir = data; interrupt(); })); + map(0xfe'00c6, 0xfe'00c7).umask16(0x00ff).lrw8(NAME([this]() { return m_uir; }), NAME([this](u8 data) { m_uir = data; interrupt(); })); + map(0xfe'00ce, 0xfe'00cf).umask16(0x00ff).lrw8(NAME([this]() { return m_rer; }), NAME([this](u8 data) { m_rer = data; m_boot.select(BIT(data, 7)); })); + + map(0xfe'00e0, 0xfe'00e1).umask16(0x00ff).lrw8(NAME([this]() { return m_exr; }), NAME([this](u8 data) { m_exr = data; })); // TODO: bit 1 parity error? + map(0xfe'00ee, 0xfe'00ef).umask16(0x00ff).lr8(NAME([]() { return 0; })); // TODO: bit 1 enables additional ram test? + + map(0xfe'0200, 0xfe'0203).rw(m_net, FUNC(am7990_device::regs_r), FUNC(am7990_device::regs_w)); + map(0xfe'0400, 0xfe'041f).rom().region("mac", 0); + + // TODO: verify the next two registers + map(0xfe'0e00, 0xfe'0e01).umask16(0x00ff).lrw8(NAME([this]() { return m_hir; }), NAME([this](u8 data) { m_hir = data; interrupt(); })); + map(0xfe'0f00, 0xfe'0f01).umask16(0x00ff).lrw8(NAME([this]() { reset(); return 0; }), NAME([this](u8 data) { reset(); })); +} + +void cmc_enp10_device::interrupt() +{ + bool const enable = BIT(m_ier, 7); + + m_cpu->set_input_line(INPUT_LINE_IRQ2, enable && BIT(m_uir, 7)); + m_cpu->set_input_line(INPUT_LINE_IRQ3, enable && BIT(m_hir, 7)); + m_cpu->set_input_line(INPUT_LINE_IRQ4, enable && BIT(m_tir, 7)); + m_cpu->set_input_line(INPUT_LINE_IRQ5, enable && BIT(m_rir, 7)); +} diff --git a/src/devices/bus/vme/enp10.h b/src/devices/bus/vme/enp10.h new file mode 100644 index 00000000000..53fabaa6846 --- /dev/null +++ b/src/devices/bus/vme/enp10.h @@ -0,0 +1,51 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +#ifndef MAME_BUS_VME_ENP10_H +#define MAME_BUS_VME_ENP10_H + +#pragma once + +#include "cpu/m68000/m68000.h" +#include "machine/am79c90.h" +#include "bus/vme/vme.h" + +class cmc_enp10_device + : public device_t + , public device_vme_card_interface +{ +public: + cmc_enp10_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + +protected: + 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 cpu_mem(address_map &map); + + void interrupt(); + + required_device m_cpu; + required_device m_net; + + output_finder<2> m_led; + + u8 m_ier; // interrupt enable register + u8 m_tir; // transmit interrupt register + u8 m_rir; // receive interrupt register + u8 m_uir; // utility interrupt register + u8 m_exr; // exception register + u8 m_csr; // control/status register + u8 m_rer; // ram/rom enable register + u8 m_hir; // host interrupt register + + memory_view m_boot; +}; + +DECLARE_DEVICE_TYPE(CMC_ENP10, cmc_enp10_device) + +#endif // MAME_BUS_VME_ENP10_H -- cgit v1.2.3