New machines marked as NOT_WORKING

---
IBM RT PC [Bitsavers]
This commit is contained in:
Patrick Mackinlay 2021-01-08 15:10:31 +07:00
parent 2ee5ac358c
commit 89b519f58e
9 changed files with 2759 additions and 0 deletions

View File

@ -165,6 +165,7 @@ CPUS["GTRON"] = true
CPUS["M88000"] = true
CPUS["XAVIX2"] = true
CPUS["UPD78K"] = true
CPUS["ROMP"] = true
--------------------------------------------------
-- specify available sound cores; some of these are
@ -920,6 +921,7 @@ BUSES["PSX_PARALLEL"] = true
BUSES["QL"] = true
BUSES["QBUS"] = true
BUSES["RS232"] = true
BUSES["RTPC_KBD"] = true
BUSES["S100"] = true
BUSES["SAMCOUPE_DRIVE_PORT"] = true
BUSES["SAMCOUPE_EXPANSION"] = true
@ -1334,6 +1336,7 @@ function linkProjects_mame_mess(_target, _subtarget)
"rockwell",
"roland",
"rolm",
"rtpc",
"sage",
"saitek",
"samcoupe",
@ -3432,6 +3435,15 @@ files {
MAME_DIR .. "src/mame/drivers/aim65_40.cpp",
}
createMESSProjects(_target, _subtarget, "rtpc")
files {
MAME_DIR .. "src/mame/drivers/rtpc.cpp",
MAME_DIR .. "src/mame/machine/rosetta.cpp",
MAME_DIR .. "src/mame/machine/rosetta.h",
MAME_DIR .. "src/mame/machine/rtpc_iocc.cpp",
MAME_DIR .. "src/mame/machine/rtpc_iocc.h",
}
createMESSProjects(_target, _subtarget, "sage")
files {
MAME_DIR .. "src/mame/drivers/sage2.cpp",

768
src/mame/drivers/rtpc.cpp Normal file
View File

@ -0,0 +1,768 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* IBM RT PC.
*
* Sources:
* - http://bitsavers.org/pdf/ibm/pc/rt/75X0232_RT_PC_Technical_Reference_Volume_1_Jun87.pdf
* - http://www.cs.cmu.edu/afs/andrew.cmu.edu/usr/shadow/www/ibmrt.html
* - http://ps-2.kev009.com/ohlandl/6152/rt_index.html
*
* TODO:
* - finish refactoring iocc
* - additional machine variants
* - configurable RAM size
*/
/*
* https://www-01.ibm.com/common/ssi/ShowDoc.wss?docURL=/common/ssi/rep_ca/6/897/ENUS186-006/index.html
* https://www-01.ibm.com/common/ssi/ShowDoc.wss?docURL=/common/ssi/rep_ca/1/897/ENUS187-021/index.html
* https://www-01.ibm.com/common/ssi/ShowDoc.wss?docURL=/common/ssi/rep_ca/0/897/ENUS188-120/index.html
*
* Model Chassis CPU RAM HDD Release Price Notes
* 010 6151 032 1M/4M 40M Jan 1986 $11,700
* 015 6151 032 2M/4M 70M Nov 1986 $10,050
* 020 6150 032 1M/4M 40M Jan 1986 $14,945
* 025 6150 032 2M/4M 70M Jan 1986 $17,940
* A25 6150 032 2M/4M 70M Jan 1986 $19,510 5080 attachment/no keyboard
* 115 6151 Adv 4M/16M 70M Feb 1987 $10,600 AFPA
* 125 6150 Adv 4M/16M 70M Feb 1987 $16,100 AFPA
* B25 6150 Adv 4M/16M 70M Feb 1987 $17,670 AFPA, 5080 attachment/no keyboard
* 130 6151 Enh 16M 114M Jul 1988 $23,220 EAFPA
* 135 6150 Enh 16M 114M Jul 1988 $30,595 EAFPA
* B35 6150 Enh 16M 114M Jul 1988 $32,165 EAFPA, 5080 attachment/no keyboard
*
* 032 (aka SGP), 170ns (23.5294 MHz crystal / 4 == 5.882350 MHz == 170ns), 1MB/2MB/4MB memory boards
* Advanced, 100ns 4MB (6151) external (6150) (presume ~40MHz crystal/4), 4MB/8MB memory boards
* Enhanced, 80ns, 16MB soldered, EAFPA standard, CMOS (49.400 MHz crystal/4 == 12.350MHz == 80.971ns)
*
* AFPA is M68881 @ 20MHz
* EAFPA is AD90221-2 ADSP-3210 (multiplier) + AD90222-2 ADSP-3221 (fp alu) + AD90220-2 ADSP-1401 (program sequencer)
*
* system processor real memory address map
* 0000'0000-00ff'ffff 16MB memory management unit
* 0100'0000-efff'ffff -- not defined
*
* system board I/O addresses (all in segment F)
* f000'0000-f0ff'ffff 16MB i/o channel i/o map
* f100'0000-f3ff'ffff 48MB reserved
* f400'0000-f4ff'ffff 16MB i/o channel memory map
* f500'0000-f7ff'ffff reserved?
* f800'0000-fbff'ffff reserved
* fc00'0000-fdff'ffff mc68881
* fe00'0000-feff'ffff fpa2
* ff00'0000-ffff'ffff 16MB floating point accelerator
*
* system processor i/o address map
* 00'0000-7f'ffff 8MB not defined
* 80'0000-80'ffff 64KB processor channel device initialization
* 81'0000-81'ffff 64KB memory management unit
* 82'0000-ff'ffff 8064KB not defined
*
* advanced processor
* 80'0400 i/o interface 1 i/o base
* 80'0100 i/o interface 2 i/o base
*
*/
/*
* WIP
* - diagnostic disk 1 fails with code 67
* - aix vrm disk 1 fails with alternating code a6/13
*/
#include "emu.h"
// cpu and memory
#include "cpu/romp/romp.h"
#include "cpu/mcs51/mcs51.h"
// various hardware
#include "machine/rosetta.h"
#include "machine/rtpc_iocc.h"
#include "machine/am9517a.h"
#include "machine/pic8259.h"
#include "machine/i8255.h"
#include "machine/mc146818.h"
#include "machine/z80scc.h"
#include "machine/timer.h"
// isa bus
#include "bus/isa/isa.h"
#include "bus/isa/isa_cards.h"
#include "bus/isa/mda.h"
#include "bus/isa/fdc.h"
#include "bus/isa/ide.h"
// busses and connectors
#include "bus/rs232/rs232.h"
#include "bus/rtpc/kbd_con.h"
#include "bus/rtpc/kbd.h"
#include "sound/spkrdev.h"
#include "machine/input_merger.h"
#include "imagedev/floppy.h"
#include "formats/pc_dsk.h"
#define LOG_GENERAL (1U << 0)
#define LOG_KLS (1U << 1)
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
#include "debugger.h"
#include "rtpc.lh"
namespace {
class rtpc_state : public driver_device
{
public:
rtpc_state(machine_config const &mconfig, device_type type, char const *tag)
: driver_device(mconfig, type, tag)
, m_cpu(*this, "cpu")
, m_mcu(*this, "mcu")
, m_mmu(*this, "mmu")
, m_iocc(*this, "iocc")
, m_dma(*this, "dma%u", 0U)
, m_pic(*this, "pic%u", 0U)
, m_ppi(*this, "ppi")
, m_rtc(*this, "rtc")
, m_scc(*this, "scc")
, m_isa(*this, "isa")
, m_kbd_con(*this, "kbd_con")
, m_speaker(*this, "kbd_con:kbd:speaker")
, m_ipl(*this, "ipl")
{
}
void ibm6150(machine_config &config);
void ibm6151(machine_config &config);
void init_common();
protected:
// driver_device overrides
virtual void machine_start() override;
virtual void machine_reset() override;
template <bool SCC> void iocc_pio_map(address_map &map);
void common(machine_config &config);
DECLARE_FLOPPY_FORMATS(floppy_formats);
void mcu_port1_w(u8 data);
void mcu_port2_w(u8 data);
void mcu_port3_w(u8 data);
void ppi_portc_w(u8 data);
void kls_cmd_w(offs_t offset, u16 data, u16 mem_mask);
void crra_w(u8 data);
void crrb_w(u8 data);
void dia_w(u8 data);
void mcu_timer(timer_device &timer, void *ptr, s32 param)
{
m_mcu_p3 ^= 0x10;
m_mcu->set_input_line(MCS51_T0_LINE, BIT(m_mcu_p3, 4));
}
void speaker()
{
if (m_speaker)
m_speaker->level_w(!BIT(m_mcu_p2, 7) ? m_mcu_p1 >> 6 : 0);
}
// devices
required_device<romp_device> m_cpu;
required_device<i8051_device> m_mcu;
required_device<rosetta_device> m_mmu;
required_device<rtpc_iocc_device> m_iocc;
required_device_array<am9517a_device, 2> m_dma;
required_device_array<pic8259_device, 2> m_pic;
required_device<i8255_device> m_ppi;
required_device<mc146818_device> m_rtc;
optional_device<z80scc_device> m_scc;
required_device<isa16_device> m_isa;
required_device<rtpc_kbd_con_device> m_kbd_con;
optional_device<speaker_sound_device> m_speaker;
required_region_ptr<u32> m_ipl;
u8 m_mcu_p0;
u8 m_mcu_p1;
u8 m_mcu_p2;
u8 m_mcu_p3;
u8 m_ppi_pb;
u8 m_mcu_uart;
u8 m_ch8er; // dma channel 8 enable register
u8 m_crra; // component reset register a
u8 m_crrb; // component reset register b
u8 m_ext[2]; // external serial registers
};
static double const speaker_levels[4] = { 0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0 };
void rtpc_state::machine_start()
{
m_mcu_p0 = 0;
m_mcu_p1 = 0;
m_mcu_p2 = 0;
m_mcu_p3 = 0;
m_ppi_pb = 0;
m_crra = 0xff;
m_crrb = 0xff;
}
void rtpc_state::machine_reset()
{
}
void rtpc_state::init_common()
{
if (m_speaker)
m_speaker->set_levels(4, speaker_levels);
}
template <bool SCC> void rtpc_state::iocc_pio_map(address_map &map)
{
if (SCC)
{
map(0x00'8000, 0x00'8003).rw(m_scc, FUNC(z80scc_device::dc_ab_r), FUNC(z80scc_device::dc_ab_w));
map(0x00'8020, 0x00'8020).lrw8([this]() { return m_ext[0]; }, "ext_a_r", [this](u8 data) { m_ext[0] = data; }, "ext_a_w");
map(0x00'8040, 0x00'8040).lrw8([this]() { return m_ext[1]; }, "ext_b_r", [this](u8 data) { m_ext[1] = data; }, "ext_b_w");
map(0x00'8060, 0x00'8060).lr8([this]() { return u8(m_scc->m1_r()); }, "intack");
}
// delay 1µs per byte written
map(0x00'80e0, 0x00'80e3).lw8([this](u8 data) { m_cpu->eat_cycles(m_cpu->clock() / 1000000 + 1); }, "io_delay");
map(0x00'8400, 0x00'8403).mirror(0x7c).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write));
map(0x00'8400, 0x00'8401).mirror(0x78).w(FUNC(rtpc_state::kls_cmd_w));
map(0x00'8800, 0x00'883f).rw(m_rtc, FUNC(mc146818_device::read_direct), FUNC(mc146818_device::write_direct));
map(0x00'8840, 0x00'884f).mirror(0x10).rw(m_dma[0], FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0x00'8860, 0x00'887f).umask16(0xff00).rw(m_dma[1], FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0x00'8880, 0x00'8881).mirror(0x1e).rw(m_pic[0], FUNC(pic8259_device::read), FUNC(pic8259_device::write));
map(0x00'88a0, 0x00'88a1).mirror(0x1e).rw(m_pic[1], FUNC(pic8259_device::read), FUNC(pic8259_device::write));
map(0x00'88c0, 0x00'88c0).mirror(0x1f).rw(m_iocc, FUNC(rtpc_iocc_device::dbr_r), FUNC(rtpc_iocc_device::dbr_w));
map(0x00'88e0, 0x00'88e0).mirror(0x1f).rw(m_iocc, FUNC(rtpc_iocc_device::dmr_r), FUNC(rtpc_iocc_device::dmr_w));
map(0x00'8c00, 0x00'8c00).mirror(0x03).lrw8([this]() { return m_ch8er; }, "ch8er_r", [this](u8 data) { m_ch8er = data; }, "ch8er_w");
map(0x00'8c20, 0x00'8c20).mirror(0x03).rw(m_iocc, FUNC(rtpc_iocc_device::ccr_r), FUNC(rtpc_iocc_device::ccr_w));
map(0x00'8c40, 0x00'8c40).mirror(0x03).lr8([this]() { return m_crra; }, "crra_r");
map(0x00'8c40, 0x00'8c40).mirror(0x03).w(FUNC(rtpc_state::crra_w));
map(0x00'8c60, 0x00'8c60).mirror(0x03).lr8([this]() { return m_crrb; }, "crrb_r");
map(0x00'8c60, 0x00'8c60).mirror(0x03).w(FUNC(rtpc_state::crrb_w));
// memory config reg (cc=2x8M, dd=2x2M, 88=2x4M)
map(0x00'8c80, 0x00'8c80).mirror(0x03).lr8([this]() { return 0xf8; }, "mcr");
map(0x00'8ca0, 0x00'8ca0).mirror(0x03).w(FUNC(rtpc_state::dia_w));
map(0x01'0000, 0x01'07ff).rw(m_iocc, FUNC(rtpc_iocc_device::tcw_r), FUNC(rtpc_iocc_device::tcw_w));
map(0x01'0800, 0x01'0801).mirror(0x7fc).rw(m_iocc, FUNC(rtpc_iocc_device::csr_r<1>), FUNC(rtpc_iocc_device::csr_w));
map(0x01'0802, 0x01'0803).mirror(0x7fc).rw(m_iocc, FUNC(rtpc_iocc_device::csr_r<0>), FUNC(rtpc_iocc_device::csr_w));
}
FLOPPY_FORMATS_MEMBER(rtpc_state::floppy_formats)
FLOPPY_PC_FORMAT
FLOPPY_FORMATS_END
void rtpc_state::mcu_port1_w(u8 data)
{
// bit function
// 6 speaker volume 0
// 7 speaker volume 1
LOGMASKED(LOG_KLS, "mcu_port1_w volume %d\n", data >> 6);
m_mcu_p1 = (m_mcu_p1 & 0x3f) | (data & 0xc0);
// speaker volume wraps to ppi port b.6 and b.5
m_ppi_pb &= ~0x60;
m_ppi_pb |= (data >> 1) & 0x60;
speaker();
}
void rtpc_state::mcu_port2_w(u8 data)
{
// bit dst
// 0 ppi port c.0 (iid0)
// 1 ppi port c.1 (iid1)
// 2 ppi port c.2 (iid2)
// 3 i/o channel system reset (active low)
// 4 ppi port c.4
// 5 (input)
// 6 ppi port c.6 (-ack)
// 7 speaker frequency
// interrupts
// 0 informational
// 1 received byte from keyboard
// 2 received byte from uart
// 3 returning byte requested by system
// 4 block transfer ready
// 5 unassigned
// 6 self-test performed
// 7 error condition
if ((data ^ m_mcu_p2) & 7)
LOGMASKED(LOG_KLS, "mcu_port2_w interrupt %d\n", data & 7);
if ((data ^ m_mcu_p2) & 8)
LOGMASKED(LOG_KLS, "mcu_port2_w system reset %d\n", data & 8);
m_ppi->pc4_w(BIT(data, 4));
m_ppi->pc6_w(BIT(data, 6));
m_mcu_p2 &= ~0xdf;
m_mcu_p2 |= data & 0xdf;
// speaker frequency wraps to ppi port b.7
m_ppi_pb &= ~0x80;
m_ppi_pb |= ~data & 0x80;
speaker();
}
void rtpc_state::mcu_port3_w(u8 data)
{
// bit i/o function
// 0 i uart rx
// 1 o uart tx
// 2 i kbd clock in
// 3 i obf/int1
// 4 i 32 kHz
// 5 i kbd data in
// 6 o kbd data out
// 7 o kbd clock out
LOGMASKED(LOG_KLS, "mcu_port3_w 0x%02x\n", data);
m_kbd_con->data_write_from_mb(BIT(data, 6));
m_kbd_con->clock_write_from_mb(BIT(data, 7));
m_mcu_p3 = (m_mcu_p3 & ~0xc2) | (data & 0xc2);
}
void rtpc_state::ppi_portc_w(u8 data)
{
LOGMASKED(LOG_KLS, "ppi_portc_w 0x%02x\n", data);
// bit 3 -> i/o channel (irq)
m_pic[0]->ir5_w(BIT(data, 3));
// bit 5 -> mcu p2.5 (ibf)
if (BIT(data, 5))
m_mcu_p2 |= 0x20;
else
m_mcu_p2 &= ~0x20;
// bit 7 -> mcu p3.3(-int1) (-obf)
if (BIT(data, 7))
m_mcu_p3 |= 0x08;
else
m_mcu_p3 &= ~0x08;
m_mcu->set_input_line(MCS51_INT1_LINE, !BIT(data, 7));
}
void rtpc_state::kls_cmd_w(offs_t offset, u16 data, u16 mem_mask)
{
LOGMASKED(LOG_KLS, "kls_cmd_w command 0x%02x data 0x%02x mask 0x%04x\n", u8(data), data >> 8, mem_mask);
// 00cc cccc dddd dddd
switch (mem_mask)
{
case 0xff00:
m_ppi->write(0, data);
break;
case 0x00ff:
m_ppi->write(1, data);
break;
case 0xffff:
m_mcu_p1 = (m_mcu_p1 & ~0x3f) | (data & 0x3f);
m_ppi->write(0, data >> 8);
break;
}
}
void rtpc_state::crra_w(u8 data)
{
LOG("crra_w 0x%02x\n", data);
// bit function
// 0 i/o slot 1
// 1 i/o slot 2
// 2 i/o slot 3
// 3 i/o slot 4
// 4 i/o slot 5
// 5 i/o slot 6
// 6 i/o slot 7
// 7 i/o slot 8
m_crra = data;
}
void rtpc_state::crrb_w(u8 data)
{
LOG("crrb_w 0x%02x\n", data);
// bit function
// 0 8530
// 1 rs232 interface
// 2 8051
// 3 dmac1
// 4 dmac2
// 5 arbitor
// 6 reserved
// 7 reserved
if (BIT(data, 0))
m_scc->reset();
// TODO: rs232 if
m_mcu->set_input_line(INPUT_LINE_RESET, !BIT(data, 2));
// TODO: dmac !ready
// TODO: arbitor
m_crrb = data;
}
void rtpc_state::dia_w(u8 data)
{
bool const state = BIT(data, 0);
LOG("dia_w 0x%02x (%s)\n", data, machine().describe_context());
m_pic[0]->ir0_w(state);
m_pic[0]->ir1_w(state);
m_pic[0]->ir2_w(state);
m_pic[0]->ir3_w(state);
m_pic[0]->ir4_w(state);
m_pic[0]->ir5_w(state);
m_pic[0]->ir6_w(state);
m_pic[0]->ir7_w(state);
m_pic[1]->ir0_w(state);
m_pic[1]->ir1_w(state);
m_pic[1]->ir2_w(state);
m_pic[1]->ir3_w(state);
m_pic[1]->ir4_w(state);
m_pic[1]->ir5_w(state);
m_pic[1]->ir6_w(state);
m_pic[1]->ir7_w(state);
}
void rtpc_state::common(machine_config &config)
{
ROMP(config, m_cpu, 23'529'400 / 4);
m_cpu->set_mmu(m_mmu);
m_cpu->set_iou(m_iocc);
input_merger_device &reqi2(INPUT_MERGER_ANY_LOW(config, "reqi2"));
reqi2.output_handler().set_inputline(m_cpu, INPUT_LINE_IRQ2).invert();
// TODO: hole for 1M/4M memory boards
// 2/2 rams 4M
// 2/1 rams 4M
// 1/1 rams 4M hole 1M
// 4/0 rams 4M
// 4/4 rams 16M hole 4M
ROSETTA(config, m_mmu, m_cpu->clock(), rosetta_device::RAM_4M);
m_mmu->set_mem(m_cpu, AS_PROGRAM);
m_mmu->set_rom("ipl");
m_mmu->out_pchk().set(reqi2, FUNC(input_merger_device::in_w<0>));
m_mmu->out_mchk().set_inputline(m_cpu, INPUT_LINE_NMI);
// keyboard, locator, speaker adapter
// P8051AH 2075
// 61X6310 8811
// (c)IBM 1986
// (c)INTEL '80
I8051(config, m_mcu, 9.216_MHz_XTAL);
m_mcu->port_in_cb<0>().set([this]() { return m_ppi->pa_r(); });
m_mcu->port_out_cb<0>().set([this](u8 data) { m_mcu_p0 = data; });
m_mcu->port_in_cb<1>().set([this]() { return m_mcu_p1 & 0x1f; });
m_mcu->port_out_cb<1>().set(FUNC(rtpc_state::mcu_port1_w));
m_mcu->port_in_cb<2>().set([this]() { return m_mcu_p2; });
m_mcu->port_out_cb<2>().set(FUNC(rtpc_state::mcu_port2_w));
m_mcu->port_out_cb<3>().set(FUNC(rtpc_state::mcu_port3_w));
m_mcu->port_in_cb<3>().set([this]() { return m_mcu_p3 & 0x3d; });
m_mcu->serial_tx_cb().set(
[this](u8 data)
{
if (BIT(m_mcu_p1, 5))
{
m_mcu_uart = data;
m_mcu->set_input_line(MCS51_RX_LINE, 1);
}
else
logerror("uart tx 0x%02x\n", data);
});
m_mcu->serial_rx_cb().set([this]() { return m_mcu_uart; });
//m_mcu->out_?().set_inputline(m_cpu, INPUT_LINE_IRQ0);
TIMER(config, "mcu_timer").configure_periodic(FUNC(rtpc_state::mcu_timer), attotime::from_hz(32768));
RTPC_IOCC(config, m_iocc, 0);
m_iocc->out_int().set(reqi2, FUNC(input_merger_device::in_w<1>));
m_iocc->out_rst().set_inputline(m_dma[0], INPUT_LINE_RESET);
m_iocc->out_rst().append_inputline(m_dma[1], INPUT_LINE_RESET);
// ISA bus
ISA16(config, m_isa, 14'318'180 / 3);
m_isa->set_memspace(m_iocc, AS_PROGRAM);
m_isa->set_iospace(m_iocc, AS_IO);
//m_isa->iochck_callback().set(FUNC(at_mb_device::iochck_w));
// NEC
// D8237AC-5
// 8903HV101
AM9517A(config, m_dma[0], m_isa->clock());
// chan usage
// 0 serial port A
// 1 serial port B
// 2 diskette drive, serial port A
// 3 pc network, serial port B
m_isa->drq0_callback().set(m_dma[0], FUNC(am9517a_device::dreq_w<0>));
m_isa->drq1_callback().set(m_dma[0], FUNC(am9517a_device::dreq_w<1>));
m_isa->drq2_callback().set(m_dma[0], FUNC(am9517a_device::dreq_w<2>));
m_isa->drq3_callback().set(m_dma[0], FUNC(am9517a_device::dreq_w<3>));
m_dma[0]->out_hreq_callback().set(m_dma[0], FUNC(am9517a_device::hack_w));
m_dma[0]->out_dack_callback<0>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<2>));
m_dma[0]->out_dack_callback<1>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<1>));
m_dma[0]->out_dack_callback<2>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<0>));
m_dma[0]->out_dack_callback<3>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<3>));
m_dma[0]->in_memr_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_b_r));
m_dma[0]->out_memw_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_b_w));
// NEC
// D8237AC-5
// 8903HV101
AM9517A(config, m_dma[1], m_isa->clock());
// chan usage
// 5 reserved
// 6 reserved
// 7 reserved
// 8 286 coprocessor
m_isa->drq5_callback().set(m_dma[1], FUNC(am9517a_device::dreq_w<1>));
m_isa->drq6_callback().set(m_dma[1], FUNC(am9517a_device::dreq_w<2>));
m_isa->drq7_callback().set(m_dma[1], FUNC(am9517a_device::dreq_w<3>));
m_dma[1]->out_hreq_callback().set(m_dma[1], FUNC(am9517a_device::hack_w));
m_dma[1]->out_dack_callback<0>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<4>));
m_dma[1]->out_dack_callback<1>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<5>));
m_dma[1]->out_dack_callback<2>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<6>));
m_dma[1]->out_dack_callback<3>().set(m_iocc, FUNC(rtpc_iocc_device::dack_w<7>));
m_dma[1]->in_memr_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_w_r));
m_dma[1]->out_memw_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_w_w));
// NEC
// D8259AC
PIC8259(config, m_pic[0]);
m_pic[0]->out_int_callback().set_inputline(m_cpu, INPUT_LINE_IRQ3).invert();
// irq source
// 0 iocc irq 0: dma tc
// 1 iocc irq 10: (multiport async)
// 2 iocc irq 9: pc network, (multiport async), enhanced color graphics adapter, 3278/79 emulation adapter
// 3 iocc irq 3: serial port 2, pc network
// 4 iocc irq 4: serial port 1
// 5 iocc irq 1: kbd
// 6 iocc irq 2: 8530
// 7 iocc irq 7: parallel port 1, monochrome/printer
m_isa->irq10_callback().set(m_pic[0], FUNC(pic8259_device::ir1_w));
m_isa->irq2_callback().set(m_pic[0], FUNC(pic8259_device::ir2_w));
m_isa->irq3_callback().set(m_pic[0], FUNC(pic8259_device::ir3_w));
m_isa->irq4_callback().set(m_pic[0], FUNC(pic8259_device::ir4_w));
m_isa->irq7_callback().set(m_pic[0], FUNC(pic8259_device::ir7_w));
// NEC
// D8259AC
PIC8259(config, m_pic[1]);
m_pic[1]->out_int_callback().set_inputline(m_cpu, INPUT_LINE_IRQ4).invert();
// irq source
// 0 iocc irq 8: reserved
// 1 iocc irq 11: (advanced monochrome graphics display) (multiport async)
// 2 iocc irq 14: fixed disk
// 3 iocc irq 12: (ibm rt pc streaming tape drive adapter)
// 4 iocc irq 6: diskette drive
// 5 iocc irq 5: parallel port 2
// 6 iocc irq 15: (286 coprocessor)
// 7 iocc irq 13: serial port ex ct1 irpt
m_isa->irq11_callback().set(m_pic[1], FUNC(pic8259_device::ir1_w));
m_isa->irq14_callback().set(m_pic[1], FUNC(pic8259_device::ir2_w));
m_isa->irq12_callback().set(m_pic[1], FUNC(pic8259_device::ir3_w));
m_isa->irq6_callback().set(m_pic[1], FUNC(pic8259_device::ir4_w));
m_isa->irq5_callback().set(m_pic[1], FUNC(pic8259_device::ir5_w));
m_isa->irq15_callback().set(m_pic[1], FUNC(pic8259_device::ir6_w));
// P8255A-5
// L6430434
// (C)INTEL '81
I8255A(config, m_ppi);
// port A: read/write 8051
// port B: input
// port C lower: input
// port C upper: 8051 handshake
// port C & 0x20 -> irq
m_ppi->in_pa_callback().set([this]() { return m_mcu_p0; });
// TODO: bits 4-1 "non-adapter system board signals"
// TODO: bit 0 "uart rxd signal"
m_ppi->in_pb_callback().set([this]() { return m_ppi_pb; });
m_ppi->out_pc_callback().set(FUNC(rtpc_state::ppi_portc_w));
m_ppi->in_pc_callback().set([this]() { return m_mcu_p2 & 0x57; });
RTPC_KBD_CON(config, m_kbd_con);
m_kbd_con->option_add("kbd", RTPC_KBD);
m_kbd_con->set_default_option("kbd");
m_kbd_con->out_data_cb().set([this](int state) { if (state) m_mcu_p3 |= 0x20; else m_mcu_p3 &= ~0x20; });
m_kbd_con->out_clock_cb().set(
[this](int state)
{
if (state)
m_mcu_p3 |= 0x04;
else
m_mcu_p3 &= ~0x04;
m_mcu->set_input_line(MCS51_INT0_LINE, !state);
});
// MC146818AP
// IL 0A46D8729
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->sqw().set(m_cpu, FUNC(romp_device::clk_w));
m_rtc->sqw().append(
[this](int state)
{
if (state)
m_ppi_pb |= 0x08;
else
m_ppi_pb &= ~0x08;
});
m_rtc->irq().set_inputline(m_cpu, INPUT_LINE_IRQ1).invert();
m_rtc->irq().append(
[this](int state)
{
if (!state)
m_ppi_pb |= 0x10;
else
m_ppi_pb &= ~0x10;
});
config.set_default_layout(layout_rtpc);
}
void rtpc_isa8_cards(device_slot_interface &device)
{
device.option_add("mda", ISA8_MDA);
}
void rtpc_isa16_cards(device_slot_interface &device)
{
// FIXME: need 16-bit combined hdc/fdc card
device.option_add("hdc", ISA16_IDE);
device.option_add("fdc", ISA8_FDC_AT);
}
void rtpc_state::ibm6150(machine_config &config)
{
common(config);
m_iocc->set_addrmap(2, &rtpc_state::iocc_pio_map<true>);
SCC8530N(config, m_scc, 3'580'000);
m_scc->configure_channels(3'072'000, 3'072'000, 3'072'000, 3'072'000);
m_scc->out_int_callback().set(m_pic[0], FUNC(pic8259_device::ir6_w));
// port: TXD, DTR, RTS, RI, RXD, DSR, CTS, DCD
// external registers: DTR, DSR, RI
// scc: TXD, RTS, RXD, CTS, DCD
// scc: DTR/REQ, SYNC not connected
rs232_port_device &port0(RS232_PORT(config, "serial0", default_rs232_devices, nullptr));
port0.cts_handler().set(m_scc, FUNC(z80scc_device::ctsa_w));
port0.dcd_handler().set(m_scc, FUNC(z80scc_device::dcda_w));
port0.rxd_handler().set(m_scc, FUNC(z80scc_device::rxa_w));
m_scc->out_rtsa_callback().set(port0, FUNC(rs232_port_device::write_rts));
m_scc->out_txda_callback().set(port0, FUNC(rs232_port_device::write_txd));
rs232_port_device &port1(RS232_PORT(config, "serial1", default_rs232_devices, nullptr));
// TXD, DTR, RTS, RI, RXD, DSR, CTS, DCD
port1.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w));
port1.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w));
port1.rxd_handler().set(m_scc, FUNC(z80scc_device::rxb_w));
m_scc->out_rtsb_callback().set(port1, FUNC(rs232_port_device::write_rts));
m_scc->out_txdb_callback().set(port1, FUNC(rs232_port_device::write_txd));
// ISA slots
ISA16_SLOT(config, "isa1", 0, m_isa, rtpc_isa16_cards, "fdc", false); // slot 1: disk/diskette adapter
ISA16_SLOT(config, "isa2", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 2: option
ISA8_SLOT(config, "isa3", 0, m_isa, rtpc_isa8_cards, "mda", false); // slot 3: option
ISA16_SLOT(config, "isa4", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 4: option
ISA16_SLOT(config, "isa5", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 5: option
ISA8_SLOT(config, "isa6", 0, m_isa, rtpc_isa8_cards, nullptr, false); // slot 6: option
ISA16_SLOT(config, "isa7", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 7: option
ISA16_SLOT(config, "isa8", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 8: coprocessor/option
}
void rtpc_state::ibm6151(machine_config &config)
{
common(config);
m_iocc->set_addrmap(2, &rtpc_state::iocc_pio_map<false>);
// ISA slots
ISA8_SLOT(config, "isa1", 0, m_isa, rtpc_isa8_cards, "mda", false); // slot 1: option
ISA16_SLOT(config, "isa2", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 2: option
ISA16_SLOT(config, "isa3", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 2: option
ISA16_SLOT(config, "isa4", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 4: option
ISA16_SLOT(config, "isa5", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 5: coprocessor/option
ISA16_SLOT(config, "isa6", 0, m_isa, rtpc_isa16_cards, nullptr, false); // slot 6: disk/diskette adapter
}
ROM_START(ibm6150)
ROM_REGION32_BE(0x10000, "ipl", 0)
ROM_SYSTEM_BIOS(0, "ipl", "IPL")
ROMX_LOAD("79x3456.bin", 0x00000, 0x4000, CRC(0a45a9ba) SHA1(02ca637c6a871c180dbfebf2ec68d8ec5a998c76), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3458.bin", 0x00001, 0x4000, CRC(7bd08ab6) SHA1(aabcfbb8fa1a5f8a08fb5cfd90ca6fe05258fde9), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3460.bin", 0x00002, 0x4000, CRC(897586e0) SHA1(528772635903f27235ebba2622b03386b84e4e17), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3462.bin", 0x00003, 0x4000, CRC(12aca906) SHA1(58f95b95768ef131d8d9d552506a9fe9c9c6077d), ROM_BIOS(0) | ROM_SKIP(3))
ROM_REGION(0x1000, "mcu", 0)
ROM_LOAD("61x6310_8051.bin", 0x0000, 0x1000, CRC(296c16c1) SHA1(83858109c39d5be37e49f24d1db4e2b15f38843e))
ROM_END
ROM_START(ibm6151)
ROM_REGION32_BE(0x10000, "ipl", 0)
ROM_SYSTEM_BIOS(0, "ipl", "IPL")
ROMX_LOAD("79x3456.bin", 0x00000, 0x4000, CRC(0a45a9ba) SHA1(02ca637c6a871c180dbfebf2ec68d8ec5a998c76), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3458.bin", 0x00001, 0x4000, CRC(7bd08ab6) SHA1(aabcfbb8fa1a5f8a08fb5cfd90ca6fe05258fde9), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3460.bin", 0x00002, 0x4000, CRC(897586e0) SHA1(528772635903f27235ebba2622b03386b84e4e17), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3462.bin", 0x00003, 0x4000, CRC(12aca906) SHA1(58f95b95768ef131d8d9d552506a9fe9c9c6077d), ROM_BIOS(0) | ROM_SKIP(3))
// Version: 073
// Date: 85 289 (16 Oct 1985)
// Checksum: 0xc8 0xe8
ROM_REGION(0x1000, "mcu", 0)
ROM_LOAD("61x6310_8051.bin", 0x0000, 0x1000, CRC(296c16c1) SHA1(83858109c39d5be37e49f24d1db4e2b15f38843e))
ROM_END
#define rom_rtpc010 rom_ibm6151
#define rom_rtpc015 rom_ibm6151
#define rom_rtpc020 rom_ibm6150
#define rom_rtpc025 rom_ibm6150
#define rom_rtpca25 rom_ibm6150
} // anonymous namespace
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP(1986, rtpc010, 0, 0, ibm6151, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 010", MACHINE_NOT_WORKING)
COMP(1986, rtpc015, 0, 0, ibm6151, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 015", MACHINE_NOT_WORKING)
COMP(1986, rtpc020, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 020", MACHINE_NOT_WORKING)
COMP(1986, rtpc025, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 025", MACHINE_NOT_WORKING)
COMP(1986, rtpca25, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model A25", MACHINE_NOT_WORKING)

69
src/mame/layout/rtpc.lay Normal file
View File

@ -0,0 +1,69 @@
<?xml version="1.0"?>
<!--
license:CC0
copyright-holders:Patrick Mackinlay
IBM RT PC diagnostic and keyboard LEDs
-->
<mamelayout version="2">
<element name="led" defstate="0">
<led7seg>
<color red="1.0" green="0.0" blue="0.0" />
</led7seg>
</element>
<element name="kbd_led" defstate="0">
<disk state="1">
<color red="0.0" green="0.75" blue="0.0" />
</disk>
</element>
<element name="num_lock">
<text string="Num Lock">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="caps_lock">
<text string="Caps Lock">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="scroll_lock">
<text string="Scroll Lock">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<view name="Graphics">
<screen index="0">
<!-- assume MDA for now -->
<bounds x="0" y="0" width="720" height="350" />
</screen>
<element name="num_text" ref="num_lock">
<bounds x="10" y="370" width="40" height="15" />
</element>
<element name="kbd_led0" ref="kbd_led">
<bounds x="25" y="385" width="10" height="10" />
</element>
<element name="caps_text" ref="caps_lock">
<bounds x="60" y="370" width="40" height="15" />
</element>
<element name="kbd_led1" ref="kbd_led">
<bounds x="75" y="385" width="10" height="10" />
</element>
<element name="scroll_text" ref="scroll_lock">
<bounds x="110" y="370" width="40" height="15" />
</element>
<element name="kbd_led2" ref="kbd_led">
<bounds x="125" y="385" width="10" height="10" />
</element>
<element name="led0" ref="led">
<bounds x="700" y="375" width="15" height="20" />
</element>
<element name="led1" ref="led">
<bounds x="680" y="375" width="15" height="20" />
</element>
</view>
</mamelayout>

1202
src/mame/machine/rosetta.cpp Normal file

File diff suppressed because it is too large Load Diff

181
src/mame/machine/rosetta.h Normal file
View File

@ -0,0 +1,181 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_MACHINE_ROSETTA_H
#define MAME_MACHINE_ROSETTA_H
#pragma once
#include "cpu/romp/rsc.h"
class rosetta_device
: public device_t
, public rsc_cpu_interface
{
public:
// ram size in doublewords
enum ram_size : unsigned
{
RAM_NONE = 0,
RAM_1M = 0x0004'0000,
RAM_2M = 0x0008'0000,
RAM_4M = 0x0010'0000,
RAM_8M = 0x0020'0000,
RAM_16M = 0x0040'0000,
};
rosetta_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, ram_size ram = RAM_NONE);
template <typename T> void set_mem(T &&tag, int spacenum) { m_mem_space.set_tag(std::forward<T>(tag), spacenum); }
template <typename T> void set_rom(T &&tag) { m_rom.set_tag(std::forward<T>(tag)); }
auto out_pchk() { return m_out_pchk.bind(); }
auto out_mchk() { return m_out_mchk.bind(); }
using rsc_mode = rsc_bus_interface::rsc_mode;
// rsc_cpu_interface overrides
virtual bool fetch(u32 address, u16 &data, rsc_mode const mode) override;
virtual bool ior(u32 address, u32 &data) override;
virtual bool iow(u32 address, u32 data) override;
// rsc_bus_interface overrides
virtual bool load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return load<u8>(address, data, mode, sp); }
virtual bool load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load<u16>(address, data, mode, sp); }
virtual bool load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load<u32>(address, data, mode, sp); }
virtual bool store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store<u8>(address, data, mode, sp); }
virtual bool store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store<u16>(address, data, mode, sp); }
virtual bool store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store<u32>(address, data, mode, sp); }
virtual bool modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode) override { return modify<u8>(address, f, mode); }
virtual bool modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return modify<u16>(address, f, mode); }
virtual bool modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return modify<u32>(address, f, mode); }
protected:
// device_t overrides
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override;
// virtual address translation
bool translate(u32 &address, bool system_processor, bool store);
// rsc_bus_interface implementation
template <typename T> bool load(u32 address, T &data, rsc_mode const mode, bool sp);
template <typename T> bool store(u32 address, T data, rsc_mode const mode, bool sp);
template <typename T> bool modify(u32 address, std::function<T(T)> f, rsc_mode const mode);
// register read handlers
u32 segment_r(offs_t offset);
u32 control_r(offs_t offset);
u32 tlb_r(offs_t offset);
// register write handlers
void segment_w(offs_t offset, u32 data);
void control_w(offs_t offset, u32 data);
void tlb_w(offs_t offset, u32 data);
// memory read handlers
u32 rom_r(offs_t offset, u32 mem_mask);
u32 ram_r(offs_t offset, u32 mem_mask);
u32 rca_r(offs_t offset);
// memory write handlers
void rom_w(offs_t offset, u32 data, u32 mem_mask);
void ram_w(offs_t offset, u32 data, u32 mem_mask);
void rca_w(offs_t offset, u32 data);
u8 compute_ecc(u32 const data) const;
unsigned check_ecc(u32 &data, u8 const ecc) const;
struct tlb_entry
{
u32 field0 = 0; // address tag
u32 field1 = 0; // real page, valid, key
u32 field2 = 0; // write, transaction identifier, lockbits
};
tlb_entry tlb_search(u64 const virtual_address, bool const special);
u32 tlb_reload(tlb_entry &tlb_entry, u64 const virtual_address, bool special = false);
void tlb_inv_all(u32 data);
void tlb_inv_segment(u32 data);
void tlb_inv_address(u32 data);
void compute_address(u32 data);
void config_map();
void config_tlb();
enum mear_state : u32
{
UNLOCKED,
LOCKED,
MEMORY,
};
void set_mear(u32 const address, mear_state lock);
void set_rmdr(u8 const ecc, bool lock);
void set_pchk(bool state)
{
if (state != m_pchk_state)
{
m_pchk_state = state;
// program check line is active low
m_out_pchk(!m_pchk_state);
}
}
void set_mchk(bool state)
{
// assume edge-triggered, active low
if (state)
{
m_out_mchk(0);
m_out_mchk(1);
}
else
m_out_mchk(1);
}
private:
required_address_space m_mem_space;
required_region_ptr<u32> m_rom;
output_finder<2> m_leds;
devcb_write_line m_out_pchk;
devcb_write_line m_out_mchk;
memory_access<24, 2, 0, ENDIANNESS_BIG>::cache m_mem;
// registers
u32 m_segment[16];
u32 m_control[9];
// lock and line state
mear_state m_mear_lock;
bool m_rmdr_lock;
bool m_led_lock;
bool m_pchk_state;
// tlb state
tlb_entry m_tlb[16][2];
u16 m_tlb_lru;
// storage
std::unique_ptr<u32[]> m_ram;
std::unique_ptr<u8[]> m_ecc;
std::unique_ptr<u8[]> m_rca;
// address translation constants
u32 m_atag_mask;
u32 m_page_mask;
unsigned m_page_shift;
u32 m_hat_base;
u16 m_hat_mask;
ram_size const m_ram_size;
};
DECLARE_DEVICE_TYPE(ROSETTA, rosetta_device)
#endif // MAME_MACHINE_ROSETTA_H

View File

@ -0,0 +1,349 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* IBM RT PC I/O Channel Converter/Controller
*
* Sources:
* - http://bitsavers.org/pdf/ibm/pc/rt/75X0232_RT_PC_Technical_Reference_Volume_1_Jun87.pdf
*
* TODO:
* - bus spaces should be little endian
* - alternate controllers, region mode dma
* - improve rsc interface
* - state saving
* - refactoring and cleanup
*/
#include "emu.h"
#include "rtpc_iocc.h"
#define LOG_GENERAL (1U << 0)
#define LOG_DMA (1U << 1)
#define LOG_WIDEPIO (1U << 2)
//#define VERBOSE (LOG_GENERAL|LOG_DMA)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(RTPC_IOCC, rtpc_iocc_device, "rtpc_iocc", "RT PC I/O Channel Converter/Controller")
rtpc_iocc_device::rtpc_iocc_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, RTPC_IOCC, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, rsc_bus_interface(mconfig, *this)
, m_mem_config("mem", ENDIANNESS_BIG, 16, 24, 0)
, m_pio_config("pio", ENDIANNESS_BIG, 16, 24, 0)
, m_out_int(*this)
, m_out_rst(*this)
, m_rsc(*this, "^mmu")
, m_csr(0)
, m_ccr(0)
, m_dbr(0)
, m_dmr(0)
, m_tcw{}
, m_adc(0)
, m_out_int_state(false)
{
}
device_memory_interface::space_config_vector rtpc_iocc_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(AS_PROGRAM, &m_mem_config),
std::make_pair(AS_IO, &m_pio_config)
};
}
void rtpc_iocc_device::device_start()
{
m_out_int.resolve_safe();
m_out_rst.resolve_safe();
save_item(NAME(m_csr));
save_item(NAME(m_ccr));
save_item(NAME(m_dbr));
save_item(NAME(m_dmr));
save_item(NAME(m_tcw));
save_item(NAME(m_adc));
save_item(NAME(m_out_int_state));
}
void rtpc_iocc_device::device_reset()
{
m_csr = 0;
set_int(false);
}
u8 rtpc_iocc_device::dma_b_r(offs_t offset)
{
u8 data = 0;
if (!BIT(m_dmr, 7 - m_adc))
{
u16 const tcw = m_tcw[(m_adc << 6) | (offset >> 11)];
u32 const real = ((tcw & TCW_PFX) << 11) | (offset & 0x7ff);
LOGMASKED(LOG_DMA, "dma0 tcw 0x%04x real 0x%08x\n", tcw, real);
if (tcw & TCW_IOC)
data = space(AS_PROGRAM).read_byte(real);
else
{
if (!m_rsc->load(real, data, RSC_N))
{
// on dma exception
// - assert interrupt (level 2)
// - csr | DE | ~PER | INTP
m_csr &= ~CSR_PER;
m_csr |= (CSR_DE0 >> m_adc) | CSR_DEXK;
m_out_rst(1);
set_int(true);
}
}
}
else
fatalerror("rtpc_iocc_device::dma_b_r() invalid dma operation\n");
return data;
}
void rtpc_iocc_device::dma_b_w(offs_t offset, u8 data)
{
LOGMASKED(LOG_DMA, "dma0 offset 0x%04x data 0x%02x\n", offset, data);
if (!BIT(m_dmr, 7 - m_adc))
{
u16 const tcw = m_tcw[(m_adc << 6) | (offset >> 11)];
u32 const real = ((tcw & TCW_PFX) << 11) | (offset & 0x7ff);
LOGMASKED(LOG_DMA, "dma0 tcw 0x%04x real 0x%08x\n", tcw, real);
if (tcw & TCW_IOC)
space(AS_PROGRAM).write_byte(real, data);
else
m_rsc->store(real, data, RSC_N);
}
else
fatalerror("rtpc_iocc_device::dma_b_w() invalid dma operation\n");
}
u8 rtpc_iocc_device::dma_w_r(offs_t offset)
{
u16 data = 0;
if (!BIT(m_dmr, 7 - m_adc))
{
u16 const tcw = m_tcw[(m_adc << 6) | (offset >> 10)];
u32 const real = ((tcw & TCW_PFX) << 11) | (offset & 0x7ff);
LOGMASKED(LOG_DMA, "dma1 tcw 0x%04x real 0x%08x\n", tcw, real);
if (tcw & TCW_IOC)
data = space(AS_PROGRAM).read_word(real);
else
m_rsc->load(real, data, RSC_N);
}
else
fatalerror("rtpc_iocc_device::dma_w_r() invalid dma operation\n");
return data;
}
void rtpc_iocc_device::dma_w_w(offs_t offset, u8 data)
{
LOGMASKED(LOG_DMA, "dma1 offset 0x%04x data 0x%02x\n", offset, data);
if (!BIT(m_dmr, 7 - m_adc))
{
u16 const tcw = m_tcw[(m_adc << 6) | (offset >> 10)];
u32 const real = ((tcw & TCW_PFX) << 11) | ((offset & 0x7ff) << 1);
LOGMASKED(LOG_DMA, "dma1 tcw 0x%04x real 0x%08x\n", tcw, real);
// FIXME: upper data bits
if (tcw & TCW_IOC)
space(AS_PROGRAM).write_word(real, data);
else
m_rsc->store(real, u16(data), RSC_N);
}
else
fatalerror("rtpc_iocc_device::dma_w_w() invalid dma operation\n");
}
template <typename T> bool rtpc_iocc_device::load(u32 address, T &data, rsc_mode const mode)
{
unsigned const s = (address >> 24) & 15 ? AS_PROGRAM : AS_IO;
if (s == AS_PROGRAM && (mode & RSC_U) && !(m_ccr & CCR_MMP))
{
LOG("load mem protection violation (%s)\n", machine().describe_context());
m_csr |= CSR_EXR | CSR_PER | CSR_PD | CSR_PVIO;
return false;
}
if (s == AS_IO)
{
if ((mode & RSC_U) && (address == 0xf001'0800U || !(m_ccr & CCR_IMP)))
{
LOG("load pio protection violation (%s)\n", machine().describe_context());
m_csr |= CSR_EXR | CSR_PER | CSR_PD | CSR_PVIO;
return false;
}
}
switch (sizeof(T))
{
case 1: data = space(s).read_byte(address); break;
case 2:
if (s == 2 && target_size(address) < sizeof(T))
{
LOGMASKED(LOG_WIDEPIO, "load pio w<-b 0x%08x (%s)\n", address, machine().describe_context());
data = u16(space(s).read_byte(address)) << 8;
data |= space(s).read_byte(address);
}
else
data = space(s).read_word(address);
break;
case 4:
if (s == 2 && target_size(address) < sizeof(T))
{
if (target_size(address) == 1)
{
LOGMASKED(LOG_WIDEPIO, "load pio d<-b 0x%08x (%s)\n", address, machine().describe_context());
data = u32(space(s).read_byte(address)) << 24;
data |= u32(space(s).read_byte(address)) << 16;
data |= u32(space(s).read_byte(address)) << 8;
data |= space(s).read_byte(address);
}
else
{
LOGMASKED(LOG_WIDEPIO, "load pio d<-w 0x%08x (%s)\n", address, machine().describe_context());
data = u32(space(s).read_word(address)) << 16;
data |= space(s).read_word(address);
}
}
else
data = space(s).read_dword(address);
break;
}
return true;
}
#ifdef _MSC_VER
// avoid incorrect MSVC warnings about excessive shift sizes below
#pragma warning(disable:4333)
#endif
template <typename T> bool rtpc_iocc_device::store(u32 address, T data, rsc_mode const mode)
{
unsigned const spacenum = (address >> 24) & 15 ? AS_PROGRAM : AS_IO;
if (spacenum == AS_PROGRAM && (mode & RSC_U) && !(m_ccr & CCR_MMP))
{
LOG("store mem protection violation (%s)\n", machine().describe_context());
m_csr |= CSR_PER | CSR_PD | CSR_PVIO;
if (mode & RSC_T)
{
m_csr |= CSR_EXR;
return false;
}
else
set_int(true);
return true;
}
if (spacenum == AS_IO && (mode & RSC_U))
{
if (address == 0xf001'0800U || !(m_ccr & CCR_IMP))
{
LOG("store pio protection violation (%s)\n", machine().describe_context());
m_csr |= CSR_PER | CSR_PD | CSR_PVIO;
if (mode & RSC_T)
{
m_csr |= CSR_EXR;
return false;
}
else
set_int(true);
return true;
}
}
switch (sizeof(T))
{
case 1: space(spacenum).write_byte(address, data); break;
case 2:
if (spacenum == AS_IO && target_size(address) < sizeof(T))
{
LOGMASKED(LOG_WIDEPIO, "store pio w->b 0x%08x data 0x%04x (%s)\n", address, data, machine().describe_context());
space(spacenum).write_byte(address, u8(data >> 8));
space(spacenum).write_byte(address, u8(data >> 0));
}
else
space(spacenum).write_word(address, data);
break;
case 4:
if (spacenum == AS_IO && target_size(address) < sizeof(T))
{
if (target_size(address) == 1)
{
LOGMASKED(LOG_WIDEPIO, "store pio d->b 0x%08x data 0x%08x (%s)\n", address, data, machine().describe_context());
space(spacenum).write_byte(address, u8(data >> 24));
space(spacenum).write_byte(address, u8(data >> 16));
space(spacenum).write_byte(address, u8(data >> 8));
space(spacenum).write_byte(address, u8(data >> 0));
}
else
{
LOGMASKED(LOG_WIDEPIO, "store pio d->w 0x%08x data 0x%08x (%s)\n", address, data, machine().describe_context());
space(spacenum).write_word(address, u16(data >> 16));
space(spacenum).write_word(address, u16(data >> 0));
}
}
else
space(spacenum).write_dword(address, data);
break;
}
return true;
}
template <typename T> bool rtpc_iocc_device::modify(u32 address, std::function<T(T)> f, rsc_mode const mode)
{
unsigned const spacenum = (address >> 24) & 15 ? AS_PROGRAM : AS_IO;
if (spacenum == AS_PROGRAM && (mode & RSC_U) && !(m_ccr & CCR_MMP))
{
LOG("modify mem protection violation (%s)\n", machine().describe_context());
m_csr |= CSR_PER | CSR_PD | CSR_PVIO;
if (mode & RSC_T)
{
m_csr |= CSR_EXR;
return false;
}
else
set_int(true);
return true;
}
if (spacenum == AS_IO)
{
LOG("modify pio space invalid operation (%s)\n", machine().describe_context());
m_csr |= CSR_EXR | CSR_PER | CSR_PD | CSR_INVOP;
return false;
}
switch (sizeof(T))
{
case 1: space(spacenum).write_byte(address, f(space(spacenum).read_byte(address))); break;
case 2: space(spacenum).write_word(address, f(space(spacenum).read_word(address))); break;
case 4: space(spacenum).write_dword(address, f(space(spacenum).read_dword(address))); break;
}
return true;
}

View File

@ -0,0 +1,170 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_MACHINE_RTPC_IOCC_H
#define MAME_MACHINE_RTPC_IOCC_H
#pragma once
#include "cpu/romp/rsc.h"
class rtpc_iocc_device
: public device_t
, public device_memory_interface
, public rsc_bus_interface
{
public:
rtpc_iocc_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
auto out_int() { return m_out_int.bind(); }
auto out_rst() { return m_out_rst.bind(); }
enum ccr_mask : u8
{
CCR_RFE = 0x02, // refresh enable
CCR_RFT = 0x04, // refresh period (0=14.9µs, 1=6.4µs)
CCR_MMP = 0x08, // memory map privilege
CCR_IMP = 0x10, // i/o map privilege
CCR_DKA = 0x20, // dma keyboard access
CCR_DSA = 0x40, // dma i/o subsystem access
CCR_DCA = 0x80, // dma control register access
};
enum csr_mask : u32
{
CSR_EXR = 0x80000000, // exception reported
CSR_INTP = 0x40000000, // interrupt pending
CSR_EPOW = 0x10000000, // early power off warning
CSR_SRST = 0x08000000, // soft reset
CSR_SAT = 0x04000000, // system attention
CSR_PER = 0x01000000, // pio error
CSR_DE0 = 0x00800000, // dma error channel 0
CSR_DE1 = 0x00400000, // dma error channel 1
CSR_DE2 = 0x00200000, // dma error channel 2
CSR_DE3 = 0x00100000, // dma error channel 3
CSR_DE5 = 0x00080000, // dma error channel 5
CSR_DE6 = 0x00040000, // dma error channel 6
CSR_DE7 = 0x00020000, // dma error channel 7
CSR_DE8 = 0x00010000, // dma error channel 8
CSR_PD = 0x00008000, // pio/dma
CSR_PVIO = 0x00004000, // protection violation
CSR_INVOP = 0x00002000, // invalid operation
CSR_IOCK = 0x00001000, // i/o channel check
CSR_DEXK = 0x00000800, // dma exception
CSR_CRC = 0x00000400, // channel reset captured
CSR_SBB = 0x00000200, // system board busy
CSR_PRP = 0x00000100, // pio request pending
CSR_RSV = 0x220000ff, // reserved
};
enum tcw_mask : u16
{
TCW_PFX = 0x1fff, // translation prefix
TCW_IOC = 0x4000, // i/o channel destination
TCW_VIR = 0x8000, // virtual access
};
using rsc_mode = rsc_bus_interface::rsc_mode;
// rsc_pio_interface overrides
virtual bool load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return load<u8>(address, data, mode); }
virtual bool load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load<u16>(address, data, mode); }
virtual bool load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load<u32>(address, data, mode); }
virtual bool store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store<u8>(address, data, mode); }
virtual bool store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store<u16>(address, data, mode); }
virtual bool store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store<u32>(address, data, mode); }
virtual bool modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode) override { return modify<u8>(address, f, mode); }
virtual bool modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return modify<u16>(address, f, mode); }
virtual bool modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return modify<u32>(address, f, mode); }
u8 ccr_r() { return m_ccr; }
void ccr_w(u8 data) { m_ccr = data; }
template <unsigned Word> u16 csr_r() { return u16((m_csr | CSR_RSV) >> (16 * Word)); }
void csr_w(u16 data) { set_int(false); m_csr = 0; }
u8 dma_b_r(offs_t offset);
u8 dma_w_r(offs_t offset);
void dma_b_w(offs_t offset, u8 data);
void dma_w_w(offs_t offset, u8 data);
u8 dmr_r() { return m_dmr; }
u8 dbr_r() { return m_dbr; }
void dmr_w(u8 data) { m_dmr = data; }
void dbr_w(u8 data) { m_dbr = data; }
u16 tcw_r(offs_t offset) { return m_tcw[offset]; }
void tcw_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_tcw[offset]); }
template <unsigned Channel> void dack_w(int state) { if (!state) m_adc = Channel; }
protected:
// device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
//virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
template <typename T> bool load(u32 address, T &data, rsc_mode const mode);
template <typename T> bool store(u32 address, T data, rsc_mode const mode);
template <typename T> bool modify(u32 address, std::function<T(T)> f, rsc_mode const mode);
void set_int(bool state)
{
if (state != m_out_int_state)
{
if (state)
m_csr |= CSR_INTP;
m_out_int_state = state;
m_out_int(!m_out_int_state);
}
}
unsigned target_size(u32 const address) const
{
if (address < 0xf000'8000U)
{
if (address == 0xf000'0110U || address == 0xf000'0112U)
return 2;
else
// FIXME: get size from isa bus
return 1;
}
else if (address == 0xf000'8400U)
// exception for kls
return 2;
else if (address < 0xf001'0000U)
return 1;
else if (address < 0xf001'0800U)
return 2;
else
return 4;
}
private:
address_space_config m_mem_config;
address_space_config m_pio_config;
devcb_write_line m_out_int;
devcb_write_line m_out_rst;
required_device<rsc_bus_interface> m_rsc;
u32 m_csr; // channel status register
u8 m_ccr; // channel control register
u8 m_dbr; // dma buffer register
u8 m_dmr; // dma mode register
u16 m_tcw[1024]; // dma translation control words
unsigned m_adc; // active dma channel
bool m_out_int_state;
};
DECLARE_DEVICE_TYPE(RTPC_IOCC, rtpc_iocc_device)
#endif // MAME_MACHINE_RTPC_IOCC_H

View File

@ -35828,6 +35828,13 @@ rt1715 //
rt1715lc // (latin/cyrillic)
rt1715w //
@source:rtpc.cpp
rtpc010 // IBM RT PC Model 010
rtpc015 // IBM RT PC Model 015
rtpc020 // IBM RT PC Model 020
rtpc025 // IBM RT PC Model 025
rtpc025 // IBM RT PC Model A25
@source:runaway.cpp
qwak // (proto) (c) 1982
runaway // (proto) (c) 1982

View File

@ -850,6 +850,7 @@ roland_tr707.cpp
roland_tr909.cpp
roland_u20.cpp
rt1715.cpp
rtpc.cpp
rvoice.cpp
rx78.cpp
rz1.cpp