diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2019-08-28 18:52:23 -0400 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2019-08-28 19:19:27 -0400 |
commit | 0b039c68e1508b0b85e3d2058a99b9de97c8e7c0 (patch) | |
tree | 23182334c078127005597b0336d20e02881ebec5 | |
parent | bff35b50416b870f4af271fb300f4668b6997b22 (diff) |
Add dump and emulation of Alpha Micro AM-310 Communications Controller [AJR, Bitsavers]
-rw-r--r-- | scripts/src/bus.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/s100/am310.cpp | 378 | ||||
-rw-r--r-- | src/devices/bus/s100/am310.h | 18 |
3 files changed, 398 insertions, 0 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 1bb852c7aaa..853b52dcf9d 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1676,6 +1676,8 @@ if (BUSES["S100"]~=null) then files { MAME_DIR .. "src/devices/bus/s100/s100.cpp", MAME_DIR .. "src/devices/bus/s100/s100.h", + MAME_DIR .. "src/devices/bus/s100/am310.cpp", + MAME_DIR .. "src/devices/bus/s100/am310.h", MAME_DIR .. "src/devices/bus/s100/dg640.cpp", MAME_DIR .. "src/devices/bus/s100/dg640.h", MAME_DIR .. "src/devices/bus/s100/dj2db.cpp", diff --git a/src/devices/bus/s100/am310.cpp b/src/devices/bus/s100/am310.cpp new file mode 100644 index 00000000000..82a121adc93 --- /dev/null +++ b/src/devices/bus/s100/am310.cpp @@ -0,0 +1,378 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Alpha Micro Systems AM-310 Communications Controller + + This S-100 serial communications board for the S-100 originally used + a Signetics 2651 PCI for each of its four ports. Some boards populate + their locations with the (compatible) SCN2661C instead. + + The S-100 host interface is a quartet of 74LS374 latches. The status + and command latches are written and read (respectively) by the Z80, + while data latches provide indirect access to the 2K of onboard SRAM + through the 9517 DMA controller. + +***************************************************************************/ + +#include "emu.h" +#include "am310.h" + +#include "bus/rs232/rs232.h" +#include "cpu/z80/z80.h" +#include "machine/am9517a.h" +#include "machine/gen_latch.h" +#include "machine/input_merger.h" +#include "machine/mc2661.h" + +class s100_am310_device : public device_t, public device_s100_card_interface +{ +public: + // construction/destruction + s100_am310_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + // device_s100_card_interface overrides + virtual u8 s100_sinp_r(offs_t offset) override; + virtual void s100_sout_w(offs_t offset, u8 data) override; + +private: + // internal read/write handlers + u8 dma_memr(offs_t offset); + void dma_memw(offs_t offset, u8 data); + u8 dma_ior(); + void dma_iow(u8 data); + u8 int_r(offs_t offset); + void int_w(offs_t offset, u8 data); + + // address map + void z80_map(address_map &map); + + // object finders + required_device<z80_device> m_z80; + required_device<generic_latch_8_device> m_dolatch; + required_device<generic_latch_8_device> m_cmdlatch; + required_device<generic_latch_8_device> m_dilatch; + required_device<generic_latch_8_device> m_statlatch; + required_device<am9517a_device> m_dma; + required_device_array<mc2661_device, 4> m_pci; + required_ioport m_adr; + required_ioport m_intr; +}; + +DEFINE_DEVICE_TYPE_PRIVATE(S100_AM310, device_s100_card_interface, s100_am310_device, "s100_am310", "Alpha Micro AM-310 Communications Controller") + +s100_am310_device::s100_am310_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, S100_AM310, tag, owner, clock) + , device_s100_card_interface(mconfig, *this) + , m_z80(*this, "z80") + , m_dolatch(*this, "dolatch") + , m_cmdlatch(*this, "cmdlatch") + , m_dilatch(*this, "dilatch") + , m_statlatch(*this, "statlatch") + , m_dma(*this, "dma") + , m_pci(*this, "pci%u", 0U) + , m_adr(*this, "ADR") + , m_intr(*this, "INTR") +{ +} + + +void s100_am310_device::device_start() +{ +} + +void s100_am310_device::device_reset() +{ + m_dma->dreq0_w(0); + int_w(8, 0); +} + + +u8 s100_am310_device::s100_sinp_r(offs_t offset) +{ + if ((offset & 0x00fe) == (m_adr->read() << 1)) + { + if (BIT(offset, 0)) + return m_statlatch->read(); + else + { + if (!machine().side_effects_disabled()) + m_dma->dreq0_w(1); + return m_dilatch->read(); + } + } + + return 0xff; +} + +void s100_am310_device::s100_sout_w(offs_t offset, u8 data) +{ + if ((offset & 0x00fe) == (m_adr->read() << 1)) + { + if (BIT(offset, 0)) + m_cmdlatch->write(data); + else + { + if (!machine().side_effects_disabled()) + m_dma->dreq0_w(1); + m_dolatch->write(data); + } + } +} + +u8 s100_am310_device::dma_memr(offs_t offset) +{ + return m_z80->space(AS_PROGRAM).read_byte(offset); +} + +void s100_am310_device::dma_memw(offs_t offset, u8 data) +{ + m_z80->space(AS_PROGRAM).write_byte(offset, data); +} + +u8 s100_am310_device::dma_ior() +{ + if (!machine().side_effects_disabled()) + m_dma->dreq0_w(0); + return m_dolatch->read(); +} + +void s100_am310_device::dma_iow(u8 data) +{ + m_dilatch->write(data); + if (!machine().side_effects_disabled()) + m_dma->dreq0_w(0); +} + +u8 s100_am310_device::int_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + int_w(offset, 0); + return 0; +} + +void s100_am310_device::int_w(offs_t offset, u8 data) +{ + u8 intr = m_intr->read(); + if (!BIT(intr, 0)) + m_bus->vi0_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 1)) + m_bus->vi1_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 2)) + m_bus->vi2_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 3)) + m_bus->vi3_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 4)) + m_bus->vi4_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 5)) + m_bus->vi5_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 6)) + m_bus->vi6_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); + if (!BIT(intr, 7)) + m_bus->vi7_w(BIT(offset, 3) ? CLEAR_LINE : ASSERT_LINE); +} + +void s100_am310_device::z80_map(address_map &map) +{ + map(0x0000, 0x07ff).mirror(0x3800).rom().region("prom", 0); + map(0x4000, 0x47ff).mirror(0x3000).ram(); // AB11 is actually decoded as well as AB10 + map(0x8000, 0x800f).mirror(0x3ff0).rw(m_dma, FUNC(am9517a_device::read), FUNC(am9517a_device::write)); + map(0xc000, 0xc000).mirror(0x3fc7).w(m_statlatch, FUNC(generic_latch_8_device::write)); + map(0xc008, 0xc008).mirror(0x3fc7).r(m_cmdlatch, FUNC(generic_latch_8_device::read)); + map(0xc010, 0xc013).mirror(0x3fc0).r(m_pci[0], FUNC(mc2661_device::read)); + map(0xc014, 0xc017).mirror(0x3fc0).w(m_pci[0], FUNC(mc2661_device::write)); + map(0xc018, 0xc01b).mirror(0x3fc0).r(m_pci[1], FUNC(mc2661_device::read)); + map(0xc01c, 0xc01f).mirror(0x3fc0).w(m_pci[1], FUNC(mc2661_device::write)); + map(0xc020, 0xc023).mirror(0x3fc0).r(m_pci[2], FUNC(mc2661_device::read)); + map(0xc024, 0xc027).mirror(0x3fc0).w(m_pci[2], FUNC(mc2661_device::write)); + map(0xc028, 0xc02b).mirror(0x3fc0).r(m_pci[3], FUNC(mc2661_device::read)); + map(0xc02c, 0xc02f).mirror(0x3fc0).w(m_pci[3], FUNC(mc2661_device::write)); + map(0xc030, 0xc030).mirror(0x3fc7).select(8).rw(FUNC(s100_am310_device::int_r), FUNC(s100_am310_device::int_w)); +} + + +static INPUT_PORTS_START(s100_am310) + // The physical positions of the jumper blocks are not numbered on the PCB. + + PORT_START("ADR") + PORT_DIPNAME(0x3f, 0x2c, "I/O Address Block") PORT_DIPLOCATION("ADR:6,4,2,1,5,3") + PORT_DIPSETTING(0x00, "00-01") + PORT_DIPSETTING(0x01, "04-05") + PORT_DIPSETTING(0x02, "08-09") + PORT_DIPSETTING(0x03, "0C-0D") + PORT_DIPSETTING(0x04, "10-11") + PORT_DIPSETTING(0x05, "14-15") + PORT_DIPSETTING(0x06, "18-19") + PORT_DIPSETTING(0x07, "1C-1D") + PORT_DIPSETTING(0x08, "20-21") + PORT_DIPSETTING(0x09, "24-25") + PORT_DIPSETTING(0x0a, "28-29") + PORT_DIPSETTING(0x0b, "2C-2D") + PORT_DIPSETTING(0x0c, "30-31") + PORT_DIPSETTING(0x0d, "34-35") + PORT_DIPSETTING(0x0e, "38-39") + PORT_DIPSETTING(0x0f, "3C-3D") + PORT_DIPSETTING(0x10, "40-41") + PORT_DIPSETTING(0x11, "44-45") + PORT_DIPSETTING(0x12, "48-49") + PORT_DIPSETTING(0x13, "4C-4D") + PORT_DIPSETTING(0x14, "50-51") + PORT_DIPSETTING(0x15, "54-55") + PORT_DIPSETTING(0x16, "58-59") + PORT_DIPSETTING(0x17, "5C-1D") + PORT_DIPSETTING(0x18, "60-61") + PORT_DIPSETTING(0x19, "64-65") + PORT_DIPSETTING(0x1a, "68-69") + PORT_DIPSETTING(0x1b, "6C-6D") + PORT_DIPSETTING(0x1c, "70-71") + PORT_DIPSETTING(0x1d, "74-75") + PORT_DIPSETTING(0x1e, "78-79") + PORT_DIPSETTING(0x1f, "7C-7D") + PORT_DIPSETTING(0x20, "80-81") + PORT_DIPSETTING(0x21, "84-85") + PORT_DIPSETTING(0x22, "88-89") + PORT_DIPSETTING(0x23, "8C-8D") + PORT_DIPSETTING(0x24, "90-91") + PORT_DIPSETTING(0x25, "94-95") + PORT_DIPSETTING(0x26, "98-99") + PORT_DIPSETTING(0x27, "9C-9D") + PORT_DIPSETTING(0x28, "A0-A1") + PORT_DIPSETTING(0x29, "A4-A5") + PORT_DIPSETTING(0x2a, "A8-A9") + PORT_DIPSETTING(0x2b, "AC-AD") + PORT_DIPSETTING(0x2c, "B0-B1") + PORT_DIPSETTING(0x2d, "B4-B5") + PORT_DIPSETTING(0x2e, "B8-B9") + PORT_DIPSETTING(0x2f, "BC-BD") + PORT_DIPSETTING(0x30, "C0-C1") + PORT_DIPSETTING(0x31, "C4-C5") + PORT_DIPSETTING(0x32, "C8-C9") + PORT_DIPSETTING(0x33, "CC-CD") + PORT_DIPSETTING(0x34, "D0-D1") + PORT_DIPSETTING(0x35, "D4-D5") + PORT_DIPSETTING(0x36, "D8-D9") + PORT_DIPSETTING(0x37, "DC-DD") + PORT_DIPSETTING(0x38, "E0-E1") + PORT_DIPSETTING(0x39, "E4-E5") + PORT_DIPSETTING(0x3a, "E8-E9") + PORT_DIPSETTING(0x3b, "EC-ED") + PORT_DIPSETTING(0x3c, "F0-F1") + PORT_DIPSETTING(0x3d, "F4-F5") + PORT_DIPSETTING(0x3e, "F8-F9") + PORT_DIPSETTING(0x3f, "FC-FD") + + PORT_START("INTR") + PORT_DIPNAME(0xff, 0xfd, "Interrupt Line") PORT_DIPLOCATION("INTR:1,2,3,4,5,6,7,8") + PORT_DIPSETTING(0xff, "None") + PORT_DIPSETTING(0xfe, "VI0") + PORT_DIPSETTING(0xfd, "VI1") + PORT_DIPSETTING(0xfb, "VI2") + PORT_DIPSETTING(0xf7, "VI3") + PORT_DIPSETTING(0xef, "VI4") + PORT_DIPSETTING(0xdf, "VI5") + PORT_DIPSETTING(0xbf, "VI6") + PORT_DIPSETTING(0x7f, "VI7") +INPUT_PORTS_END + +ioport_constructor s100_am310_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(s100_am310); +} + + +void s100_am310_device::device_add_mconfig(machine_config &config) +{ + Z80(config, m_z80, 4_MHz_XTAL); + m_z80->set_addrmap(AS_PROGRAM, &s100_am310_device::z80_map); + + input_merger_device &irq(INPUT_MERGER_ANY_HIGH(config, "irq")); // open collector + irq.output_handler().set_inputline(m_z80, INPUT_LINE_IRQ0); + + AM9517A(config, m_dma, 4_MHz_XTAL); + m_dma->out_hreq_callback().set_inputline(m_z80, INPUT_LINE_HALT); + m_dma->out_hreq_callback().append(m_dma, FUNC(am9517a_device::hack_w)); + m_dma->in_memr_callback().set(FUNC(s100_am310_device::dma_memr)); + m_dma->out_memw_callback().set(FUNC(s100_am310_device::dma_memw)); + m_dma->in_ior_callback<0>().set(FUNC(s100_am310_device::dma_ior)); + m_dma->out_iow_callback<0>().set(FUNC(s100_am310_device::dma_iow)); + + GENERIC_LATCH_8(config, m_dolatch); // U38 + GENERIC_LATCH_8(config, m_cmdlatch); // U39 + GENERIC_LATCH_8(config, m_dilatch); // U40 + GENERIC_LATCH_8(config, m_statlatch); // U41 + + MC2661(config, m_pci[0], 5.0688_MHz_XTAL); // U30 + m_pci[0]->rts_handler().set("ch1", FUNC(rs232_port_device::write_rts)); + m_pci[0]->dtr_handler().set("ch1", FUNC(rs232_port_device::write_dtr)); + m_pci[0]->txd_handler().set("ch1", FUNC(rs232_port_device::write_txd)); + m_pci[0]->txemt_dschg_handler().set("irq", FUNC(input_merger_device::in_w<0>)); + m_pci[0]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<1>)); + m_pci[0]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<2>)); + + MC2661(config, m_pci[1], 5.0688_MHz_XTAL); // U28 + m_pci[1]->rts_handler().set("ch2", FUNC(rs232_port_device::write_rts)); + m_pci[1]->dtr_handler().set("ch2", FUNC(rs232_port_device::write_dtr)); + m_pci[1]->txd_handler().set("ch2", FUNC(rs232_port_device::write_txd)); + m_pci[1]->txemt_dschg_handler().set("irq", FUNC(input_merger_device::in_w<3>)); + m_pci[1]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<4>)); + m_pci[1]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<5>)); + + MC2661(config, m_pci[2], 5.0688_MHz_XTAL); // U27 + m_pci[2]->rts_handler().set("ch3", FUNC(rs232_port_device::write_rts)); + m_pci[2]->dtr_handler().set("ch3", FUNC(rs232_port_device::write_dtr)); + m_pci[2]->txd_handler().set("ch3", FUNC(rs232_port_device::write_txd)); + m_pci[2]->txemt_dschg_handler().set("irq", FUNC(input_merger_device::in_w<6>)); + m_pci[2]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<7>)); + m_pci[2]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<8>)); + + MC2661(config, m_pci[3], 5.0688_MHz_XTAL); // U29 + m_pci[3]->rts_handler().set("ch4", FUNC(rs232_port_device::write_rts)); + m_pci[3]->dtr_handler().set("ch4", FUNC(rs232_port_device::write_dtr)); + m_pci[3]->txd_handler().set("ch4", FUNC(rs232_port_device::write_txd)); + m_pci[3]->txemt_dschg_handler().set("irq", FUNC(input_merger_device::in_w<9>)); + m_pci[3]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<10>)); + m_pci[3]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<11>)); + + rs232_port_device &ch1(RS232_PORT(config, "ch1", default_rs232_devices, nullptr)); // J2 + ch1.rxd_handler().set(m_pci[0], FUNC(mc2661_device::rx_w)); + ch1.dcd_handler().set(m_pci[0], FUNC(mc2661_device::dcd_w)); + ch1.dsr_handler().set(m_pci[0], FUNC(mc2661_device::dsr_w)); + ch1.cts_handler().set(m_pci[0], FUNC(mc2661_device::cts_w)); + + rs232_port_device &ch2(RS232_PORT(config, "ch2", default_rs232_devices, nullptr)); // J3 + ch2.rxd_handler().set(m_pci[1], FUNC(mc2661_device::rx_w)); + ch2.dcd_handler().set(m_pci[1], FUNC(mc2661_device::dcd_w)); + ch2.dsr_handler().set(m_pci[1], FUNC(mc2661_device::dsr_w)); + ch2.cts_handler().set(m_pci[1], FUNC(mc2661_device::cts_w)); + + rs232_port_device &ch3(RS232_PORT(config, "ch3", default_rs232_devices, nullptr)); // J4 + ch3.rxd_handler().set(m_pci[2], FUNC(mc2661_device::rx_w)); + ch3.dcd_handler().set(m_pci[2], FUNC(mc2661_device::dcd_w)); + ch3.dsr_handler().set(m_pci[2], FUNC(mc2661_device::dsr_w)); + ch3.cts_handler().set(m_pci[2], FUNC(mc2661_device::cts_w)); + + rs232_port_device &ch4(RS232_PORT(config, "ch4", default_rs232_devices, nullptr)); // J5 + ch4.rxd_handler().set(m_pci[3], FUNC(mc2661_device::rx_w)); + ch4.dcd_handler().set(m_pci[3], FUNC(mc2661_device::dcd_w)); + ch4.dsr_handler().set(m_pci[3], FUNC(mc2661_device::dsr_w)); + ch4.cts_handler().set(m_pci[3], FUNC(mc2661_device::cts_w)); +} + + +ROM_START(s100_am310) + ROM_REGION(0x800, "prom", 0) + ROM_LOAD("311-02_a00.u33", 0x000, 0x800, CRC(1f771ec8) SHA1(20716814381eb751261ee0607f3efff0d5375bd5)) +ROM_END + +const tiny_rom_entry *s100_am310_device::device_rom_region() const +{ + return ROM_NAME(s100_am310); +} diff --git a/src/devices/bus/s100/am310.h b/src/devices/bus/s100/am310.h new file mode 100644 index 00000000000..e3740b6ad5f --- /dev/null +++ b/src/devices/bus/s100/am310.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Alpha Micro Systems AM-310 Communications Controller + +**********************************************************************/ + +#ifndef MAME_BUS_S100_AM310_H +#define MAME_BUS_S100_AM310_H 1 + +#pragma once + +#include "bus/s100/s100.h" + +DECLARE_DEVICE_TYPE(S100_AM310, device_s100_card_interface) + +#endif // MAME_BUS_S100_AM310_H |