From 07c20e3faf5b3dbcb596733ce4ffc004da29470b Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Fri, 6 Jan 2023 13:30:23 +0700 Subject: rtpc: wip, now able to boot from vrm floppy * rtpc: improve keyboard/locator/speaker adapter emulation * romp: fully decode memory and i/o access from processor channel * iocc: use emumem flags for isa bus i/o width detection * iocc: correct isa bus access endianness * iocc: internalize tcw and csr --- src/devices/bus/rtpc/kbd.cpp | 4 +- src/devices/cpu/romp/romp.cpp | 6 +- src/devices/cpu/romp/romp.h | 23 +++- src/devices/cpu/romp/rsc.h | 45 ++++--- src/mame/ibm/rosetta.h | 32 +++-- src/mame/ibm/rtpc.cpp | 268 ++++++++++++++++++++++++--------------- src/mame/ibm/rtpc_iocc.cpp | 282 +++++++++++++++++++++++++----------------- src/mame/ibm/rtpc_iocc.h | 85 +++++++------ 8 files changed, 450 insertions(+), 295 deletions(-) diff --git a/src/devices/bus/rtpc/kbd.cpp b/src/devices/bus/rtpc/kbd.cpp index 13cc1759a2d..921cfc03271 100644 --- a/src/devices/bus/rtpc/kbd.cpp +++ b/src/devices/bus/rtpc/kbd.cpp @@ -15,7 +15,7 @@ * set and scan codes are very similar to a PC keyboard (scan code "set 3"). * * Sources: - * - http://bitsavers.org/pdf/ibm/pc/rt/6489893_RT_PC_Technical_Reference_Volume_1_Nov85.pdf + * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987 * * Key switches are addressed using an 8 bit code as follows: * @@ -55,7 +55,7 @@ //#define VERBOSE (LOG_GENERAL) #include "logmacro.h" -DEFINE_DEVICE_TYPE(RTPC_KBD, rtpc_kbd_device, "rtpc_kbd", "IBM PC RT Keyboard") +DEFINE_DEVICE_TYPE(RTPC_KBD, rtpc_kbd_device, "rtpc_kbd", "IBM RT PC Keyboard") rtpc_kbd_device::rtpc_kbd_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, RTPC_KBD, tag, owner, clock) diff --git a/src/devices/cpu/romp/romp.cpp b/src/devices/cpu/romp/romp.cpp index 37d73c4932b..6057c7621d4 100644 --- a/src/devices/cpu/romp/romp.cpp +++ b/src/devices/cpu/romp/romp.cpp @@ -5,7 +5,7 @@ * IBM Research and Office Products Division Microprocessor (ROMP). * * Sources: - * - http://bitsavers.org/pdf/ibm/pc/rt/75X0232_RT_PC_Technical_Reference_Volume_1_Jun87.pdf + * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987 * * TODO: * - configurable storage channel @@ -322,7 +322,7 @@ void romp_device::execute_run() m_icount -= 4; break; case 0xcb: // ior: input/output read - if (((r3 + i) & 0xff00'0000U) || !m_mmu->ior(r3 + i, m_gpr[R2])) + if (((r3 + i) & 0xff00'0000U) || !m_mmu->pio_load(r3 + i, m_gpr[R2])) program_check(PCS_PCK | PCS_DAE); break; case 0xcc: // ti: trap on condition immediate @@ -433,7 +433,7 @@ void romp_device::execute_run() m_icount -= 4; break; case 0xdb: // iow: input/output write - if (((r3 + i) & 0xff00'0000U) || !m_mmu->iow(r3 + i, m_gpr[R2])) + if (((r3 + i) & 0xff00'0000U) || !m_mmu->pio_store(r3 + i, m_gpr[R2])) program_check(PCS_PCK | PCS_DAE); m_icount--; break; diff --git a/src/devices/cpu/romp/romp.h b/src/devices/cpu/romp/romp.h index 2d726bbcd4c..63d3e523de2 100644 --- a/src/devices/cpu/romp/romp.h +++ b/src/devices/cpu/romp/romp.h @@ -166,7 +166,7 @@ private: switch (address >> 28) { default: - if (m_mmu->load(address, data, mode)) + if (m_mmu->mem_load(address, data, mode)) f(data); else program_check(PCS_PCK | PCS_DAE); @@ -176,8 +176,13 @@ private: switch (address >> 24) { case 0xf0: + if (m_iou->pio_load(address, data, mode)) + f(data); + else + program_check(PCS_PCK | PCS_DAE); + break; case 0xf4: - if (m_iou->load(address, data, mode)) + if (m_iou->mem_load(address, data, mode)) f(data); else program_check(PCS_PCK | PCS_DAE); @@ -202,7 +207,7 @@ private: switch (address >> 28) { default: - if (!m_mmu->store(address, data, mode)) + if (!m_mmu->mem_store(address, data, mode)) program_check(PCS_PCK | PCS_DAE); break; @@ -210,8 +215,11 @@ private: switch (address >> 24) { case 0xf0: + if (!m_iou->pio_store(address, data, mode)) + program_check(PCS_PCK | PCS_DAE); + break; case 0xf4: - if (!m_iou->store(address, data, mode)) + if (!m_iou->mem_store(address, data, mode)) program_check(PCS_PCK | PCS_DAE); break; @@ -234,7 +242,7 @@ private: switch (address >> 28) { default: - if (!m_mmu->modify(address, f, mode)) + if (!m_mmu->mem_modify(address, f, mode)) program_check(PCS_PCK | PCS_DAE); break; @@ -242,8 +250,11 @@ private: switch (address >> 24) { case 0xf0: + if (!m_iou->pio_modify(address, f, mode)) + program_check(PCS_PCK | PCS_DAE); + break; case 0xf4: - if (!m_iou->modify(address, f, mode)) + if (!m_iou->mem_modify(address, f, mode)) program_check(PCS_PCK | PCS_DAE); break; diff --git a/src/devices/cpu/romp/rsc.h b/src/devices/cpu/romp/rsc.h index 6810a7cefcb..1f9655ce271 100644 --- a/src/devices/cpu/romp/rsc.h +++ b/src/devices/cpu/romp/rsc.h @@ -37,17 +37,29 @@ public: RSC_PUT = 7, }; - virtual bool load(u32 address, u8 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool load(u32 address, u16 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool load(u32 address, u32 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool store(u32 address, u8 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool store(u32 address, u16 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool store(u32 address, u32 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_store(u32 address, u8 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_store(u32 address, u16 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; + virtual bool mem_store(u32 address, u32 data, rsc_mode const mode = RSC_N, bool sp = false) = 0; - virtual bool modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; - virtual bool modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; - virtual bool modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + + virtual bool pio_load(u32 address, u8 &data, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_load(u32 address, u16 &data, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_load(u32 address, u32 &data, rsc_mode const mode = RSC_N) = 0; + + virtual bool pio_store(u32 address, u8 data, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_store(u32 address, u16 data, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_store(u32 address, u32 data, rsc_mode const mode = RSC_N) = 0; + + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode = RSC_N) = 0; protected: rsc_bus_interface(machine_config const &mconfig, device_t &device, char const *type) @@ -69,17 +81,14 @@ public: // cpu interface virtual bool fetch(u32 address, u16 &data, rsc_mode const mode = RSC_N) = 0; - virtual bool ior(u32 address, u32 &data) = 0; - virtual bool iow(u32 address, u32 data) = 0; - // rsc_bus_interface overrides - virtual bool load(u32 address, u8 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; - virtual bool load(u32 address, u16 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; - virtual bool load(u32 address, u32 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; - virtual bool store(u32 address, u8 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; - virtual bool store(u32 address, u16 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; - virtual bool store(u32 address, u32 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_store(u32 address, u8 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_store(u32 address, u16 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; + virtual bool mem_store(u32 address, u32 data, rsc_mode const mode = RSC_N, bool sp = true) override = 0; }; #endif // MAME_CPU_ROMP_RSC_H diff --git a/src/mame/ibm/rosetta.h b/src/mame/ibm/rosetta.h index a97036a01fc..f93c2050862 100644 --- a/src/mame/ibm/rosetta.h +++ b/src/mame/ibm/rosetta.h @@ -36,19 +36,27 @@ public: // 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(address, data, mode, sp); } - virtual bool load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode, sp); } - virtual bool load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode, sp); } - virtual bool store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } - virtual bool store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } - virtual bool store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } + virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode, sp); } + virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode, sp); } + virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode, sp); } + virtual bool mem_store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } + virtual bool mem_store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } + virtual bool mem_store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store(address, data, mode, sp); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } + + virtual bool pio_load(u32 address, u8 &data, rsc_mode const mode) override { return false; } + virtual bool pio_load(u32 address, u16 &data, rsc_mode const mode) override { return false; } + virtual bool pio_load(u32 address, u32 &data, rsc_mode const mode) override { return ior(address, data); } + virtual bool pio_store(u32 address, u8 data, rsc_mode const mode) override { return false; } + virtual bool pio_store(u32 address, u16 data, rsc_mode const mode) override { return false; } + virtual bool pio_store(u32 address, u32 data, rsc_mode const mode) override { return iow(address, data); } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return false; } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return false; } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return false; } protected: // device_t overrides @@ -64,6 +72,8 @@ protected: template bool load(u32 address, T &data, rsc_mode const mode, bool sp); template bool store(u32 address, T data, rsc_mode const mode, bool sp); template bool modify(u32 address, std::function f, rsc_mode const mode); + bool ior(u32 address, u32 &data); + bool iow(u32 address, u32 data); // register read handlers u32 segment_r(offs_t offset); diff --git a/src/mame/ibm/rtpc.cpp b/src/mame/ibm/rtpc.cpp index bb40b4e8e6d..458cdc7222e 100644 --- a/src/mame/ibm/rtpc.cpp +++ b/src/mame/ibm/rtpc.cpp @@ -5,7 +5,7 @@ * IBM RT PC. * * Sources: - * - http://bitsavers.org/pdf/ibm/pc/rt/75X0232_RT_PC_Technical_Reference_Volume_1_Jun87.pdf + * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987 * - http://www.cs.cmu.edu/afs/andrew.cmu.edu/usr/shadow/www/ibmrt.html * - http://ps-2.kev009.com/ohlandl/6152/rt_index.html * @@ -68,9 +68,8 @@ * https://ardent-tool.com/615x/rt_loadable_post.html * * WIP - * - diagnostic disk 1 fails with alternating code a6/13 - * exception at 0x16824: lcs r2,0x4(r9) # r9=40435c9c - * - aix vrm disk 1 fails with alternating code a6/13 + * - boots to vrm install disk menu + * - requires improved hard disk controller emulation */ #include "emu.h" @@ -94,7 +93,6 @@ #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" @@ -110,7 +108,7 @@ #define LOG_GENERAL (1U << 0) #define LOG_KLS (1U << 1) -//#define VERBOSE (LOG_GENERAL) +//#define VERBOSE (LOG_GENERAL|LOG_KLS) #include "logmacro.h" #include "debugger.h" @@ -152,23 +150,24 @@ protected: void iocc_mem_map(address_map &map) { map.unmap_value_high(); } template void iocc_pio_map(address_map &map); + void mcu_pgm_map(address_map &map); void common(machine_config &config); + void kls_cmd_w(u16 data); 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, s32 param) { - m_mcu_p3 ^= 0x10; - m_mcu->set_input_line(MCS51_T0_LINE, BIT(m_mcu_p3, 4)); + m_mcu->set_input_line(MCS51_T0_LINE, 1); + m_mcu->set_input_line(MCS51_T0_LINE, 0); } void speaker() @@ -195,13 +194,17 @@ protected: required_region_ptr m_ipl; - u8 m_mcu_p0 = 0; - u8 m_mcu_p1 = 0; - u8 m_mcu_p2 = 0; - u8 m_mcu_p3 = 0; + u8 m_kls_cmd; - u8 m_ppi_pb = 0; - u8 m_mcu_uart = 0; + u8 m_mcu_p0; + u8 m_mcu_p1; + u8 m_mcu_p2; + u8 m_mcu_p3; + u8 m_mcu_uart; + + u8 m_ppi_pa; + u8 m_ppi_pb; + u8 m_ppi_pc; u8 m_ch8er = 0; // dma channel 8 enable register u8 m_crra = 0; // component reset register a @@ -214,12 +217,17 @@ static double const speaker_levels[4] = { 0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0 }; void rtpc_state::machine_start() { + m_kls_cmd = 0; + m_mcu_p0 = 0; m_mcu_p1 = 0; m_mcu_p2 = 0; m_mcu_p3 = 0; + m_mcu_uart = 0; + m_ppi_pa = 0; m_ppi_pb = 0; + m_ppi_pc = 0; m_crra = 0xff; m_crrb = 0xff; @@ -250,12 +258,12 @@ template void rtpc_state::iocc_pio_map(address_map &map) // 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'8400, 0x00'8401).w(FUNC(rtpc_state::kls_cmd_w)).flags(rtpc_iocc_device::PIO_W); + map(0x00'8404, 0x00'8407).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write)); 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'8860, 0x00'887f).umask16(0x00ff).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)); @@ -275,10 +283,12 @@ template void rtpc_state::iocc_pio_map(address_map &map) // 8c82 diag dma mode? // 8c84 diag dma exit? map(0x00'8ce0, 0x00'8ce1).nopw(); // FIXME: hex display register? +} - 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)); +void rtpc_state::mcu_pgm_map(address_map &map) +{ + map(0x0000, 0x0fff).rom().region("mcu", 0); + map(0xf800, 0xffff).lr8([this]() { m_cpu->pulse_input_line(INPUT_LINE_IRQ0, attotime::from_msec(1)); return 0; }, "sys_atn"); } void rtpc_state::mcu_port1_w(u8 data) @@ -286,7 +296,7 @@ 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); + LOGMASKED(LOG_KLS, "kls 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 @@ -298,41 +308,57 @@ void rtpc_state::mcu_port1_w(u8 data) 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 + // bit i/o function + // 0 o ppi port c.0 (iid0) + // 1 o ppi port c.1 (iid1) + // 2 o ppi port c.2 (iid2) + // 3 o i/o channel system reset (active low) + // 4 o ppi port c.4 (-stb) + // 5 i ppi port c.5 (ibf) + // 6 o ppi port c.6 (-ack) + // 7 o speaker frequency if ((data ^ m_mcu_p2) & 7) - LOGMASKED(LOG_KLS, "mcu_port2_w interrupt %d\n", data & 7); + { + static const char *const mcu_code[] = + { + "informational", "received byte from keyboard", "received byte from uart", "returning byte requested by system", + "block transfer ready", "unassigned", "self-test performed", "error condition" + }; + LOGMASKED(LOG_KLS, "kls mcu iid %d: %s\n", data & 7, mcu_code[data & 7]); + } if ((data ^ m_mcu_p2) & 8) - LOGMASKED(LOG_KLS, "mcu_port2_w system reset %d\n", data & 8); + LOGMASKED(LOG_KLS, "kls mcu system reset %d\n", BIT(data, 3)); - m_ppi->pc4_w(BIT(data, 4)); - m_ppi->pc6_w(BIT(data, 6)); + if ((data ^ m_mcu_p2) & 0x10) + { + if (!BIT(data, 4)) + { + LOGMASKED(LOG_KLS, "kls mcu data out 0x%02x\n", m_mcu_p0); + m_ppi_pa = m_mcu_p0; + } + m_ppi->pc4_w(BIT(data, 4)); + } + + if ((data ^ m_mcu_p2) & 0x40) + { - m_mcu_p2 &= ~0xdf; - m_mcu_p2 |= data & 0xdf; + m_ppi->pc6_w(BIT(data, 6)); + if (!BIT(data, 6)) + { + LOGMASKED(LOG_KLS, "kls mcu data in 0x%02x\n", m_ppi_pa); + m_mcu_p0 = m_ppi_pa; + } + } + + m_mcu_p2 = (m_mcu_p2 & ~0xdf) | (data & 0xdf); // speaker frequency wraps to ppi port b.7 - m_ppi_pb &= ~0x80; - m_ppi_pb |= ~data & 0x80; + m_ppi_pb = (m_ppi_pb & ~0x80) | (~data & 0x80); + + // iid, ack, stb map to ppi port c + m_ppi_pc = (m_ppi_pc & ~0x57) | (data & 0x57); speaker(); } @@ -342,60 +368,98 @@ 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 + // 2 i kbd clock in (-int0) + // 3 i ppi -obf (-int1) + // 4 i 32 kHz (t0) // 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); } +/* + * bit i/o function + * 0 i iid0 + * 1 i iid1 + * 2 i iid2 + * 3 o +irq + * 4 i -stb + * 5 o ibf + * 6 i -ack + * 7 o -obf + */ 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)); + // bit 3 (+irq) -> i/o channel + if (BIT(m_ppi_pc ^ data, 3)) + { + LOGMASKED(LOG_KLS, "kls host irq %d\n", BIT(data, 3)); + m_pic[0]->ir5_w(BIT(data, 3)); + } + + // bit 5 (+ibf) -> mcu p2.5 + if (BIT(m_ppi_pc ^ data, 5)) + { + if (BIT(data, 5)) + m_mcu_p2 |= 0x20; + else + m_mcu_p2 &= ~0x20; + } + + // bit 7 (-obf) -> mcu p3.3 (-int1) + if (BIT(m_ppi_pc ^ data, 7)) + m_mcu->set_input_line(MCS51_INT1_LINE, !BIT(data, 7)); + + m_ppi_pc = (m_ppi_pc & ~0xa8) | (data & 0xa8); } -void rtpc_state::kls_cmd_w(offs_t offset, u16 data, u16 mem_mask) +void rtpc_state::kls_cmd_w(u16 data) { - LOGMASKED(LOG_KLS, "kls_cmd_w command 0x%02x data 0x%02x mask 0x%04x\n", u8(data), data >> 8, mem_mask); + LOGMASKED(LOG_KLS, "kls command 0x%02x data 0x%02x (%s)\n", data >> 8, u8(data), machine().describe_context()); // 00cc cccc dddd dddd - switch (mem_mask) + m_kls_cmd = BIT(data, 8, 6); + + switch (m_kls_cmd & 0x1f) { - case 0xff00: - m_ppi->write(0, data); + case 0x0: // extended command + switch (u8(data)) + { + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + LOGMASKED(LOG_KLS, "clr mode bit %d\n", data & 0xf); break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + LOGMASKED(LOG_KLS, "set mode bit %d\n", data & 0xf); break; + default: LOGMASKED(LOG_KLS, "extended command 0x%02x\n", data); break; + } break; - case 0x00ff: - m_ppi->write(1, data); + case 0x1: LOGMASKED(LOG_KLS, "write keyboard 0x%02x\n", data); break; + case 0x2: LOGMASKED(LOG_KLS, "write speaker 0x%02x\n", data); break; + case 0x3: LOGMASKED(LOG_KLS, "write uart control 0x%02x\n", data); break; + case 0x4: LOGMASKED(LOG_KLS, "write uart query 0x%02x\n", data); break; + case 0x5: LOGMASKED(LOG_KLS, "set uart rate 0x%02x\n", data); break; + case 0x6: LOGMASKED(LOG_KLS, "init uart 0x%02x\n", data); break; + case 0x7: LOGMASKED(LOG_KLS, "set speaker duration 0x%02x\n", data); break; + case 0x8: LOGMASKED(LOG_KLS, "set speaker freq-hi 0x%02x\n", data); break; + case 0x9: LOGMASKED(LOG_KLS, "set speaker freq-lo 0x%02x\n", data); break; + case 0xc: LOGMASKED(LOG_KLS, "diagnostic write 0x%02x\n", data); break; + case 0xa: case 0xb: case 0xd: case 0xe: case 0xf: + LOGMASKED(LOG_KLS, "unassigned\n"); break; - case 0xffff: - m_mcu_p1 = (m_mcu_p1 & ~0x3f) | (data & 0x3f); - m_ppi->write(0, data >> 8); + default: + LOGMASKED(LOG_KLS, "write shared ram addr 0x%x data 0x%02x\n", m_kls_cmd & 0xf, data); break; } + + m_mcu_p1 = (m_mcu_p1 & 0xe0) | (m_kls_cmd & 0x1f); + m_ppi->write(0, data); } void rtpc_state::crra_w(u8 data) @@ -417,7 +481,7 @@ void rtpc_state::crra_w(u8 data) void rtpc_state::crrb_w(u8 data) { - LOG("crrb_w 0x%02x\n", data); + LOG("crrb_w 0x%02x (%s)\n", data, machine().describe_context()); // bit function // 0 8530 @@ -431,8 +495,11 @@ void rtpc_state::crrb_w(u8 data) if (m_scc && 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 @@ -466,6 +533,17 @@ void rtpc_state::dia_w(u8 data) void rtpc_state::common(machine_config &config) { + /* + * irq source + * 0 mcu system attention + * 1 rtc interrupt + * 2 mmu program check, iocc error + * 3 pic 0 interrupt + * 4 pic 1 interrupt + * 5 (not connected, software interrupt?) + * 6 (not connected, software interrupt?) + * nmi mmu machine check, early power off + */ ROMP(config, m_cpu, 23'529'400 / 4); m_cpu->set_mmu(m_mmu); m_cpu->set_iou(m_iocc); @@ -491,27 +569,27 @@ void rtpc_state::common(machine_config &config) // (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->set_addrmap(AS_PROGRAM, &rtpc_state::mcu_pgm_map); + m_mcu->port_in_cb<0>().set([this]() { return m_mcu_p0; }); 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_in_cb<1>().set([this]() { return m_mcu_p1 | 0xc0; }); 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_in_cb<2>().set([this]() { return m_mcu_p2 | 0xdf; }); m_mcu->port_out_cb<2>().set(FUNC(rtpc_state::mcu_port2_w)); + m_mcu->port_in_cb<3>().set([this]() { return m_mcu_p3 | 0xce; }); 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)) + if (BIT(m_kls_cmd, 5)) { m_mcu_uart = data; m_mcu->set_input_line(MCS51_RX_LINE, 1); } else - logerror("uart tx 0x%02x\n", data); + LOGMASKED(LOG_KLS, "kls 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)); @@ -637,28 +715,21 @@ void rtpc_state::common(machine_config &config) // port C lower: input // port C upper: 8051 handshake // port C & 0x20 -> irq - m_ppi->in_pa_callback().set([this]() { return m_mcu_p0; }); + m_ppi->out_pa_callback().set([this](u8 data) { m_ppi_pa = data; }); + m_ppi->in_pa_callback().set([this]() { return m_ppi_pa; }); // 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; }); + m_ppi->in_pc_callback().set([this]() { return m_ppi_pc; }); 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); - }); + m_kbd_con->out_clock_cb().set_inputline(m_mcu, MCS51_INT0_LINE).invert(); // MC146818AP // IL 0A46D8729 @@ -693,7 +764,6 @@ void rtpc_isa8_cards(device_slot_interface &device) 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); } diff --git a/src/mame/ibm/rtpc_iocc.cpp b/src/mame/ibm/rtpc_iocc.cpp index aa98670da98..a82912dd9a4 100644 --- a/src/mame/ibm/rtpc_iocc.cpp +++ b/src/mame/ibm/rtpc_iocc.cpp @@ -5,14 +5,11 @@ * 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 + * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987 * * TODO: - * - bus spaces should be little endian + * - isa bus i/o space should be halfword addressed * - alternate controllers, region mode dma - * - improve rsc interface - * - state saving - * - refactoring and cleanup */ #include "emu.h" @@ -25,14 +22,14 @@ //#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") +DEFINE_DEVICE_TYPE(RTPC_IOCC, rtpc_iocc_device, "rtpc_iocc", "IBM 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_mem_config("mem", ENDIANNESS_LITTLE, 16, 24, 0) + , m_pio_config("pio", ENDIANNESS_LITTLE, 16, 24, 0) , m_out_int(*this) , m_out_rst(*this) , m_rsc(*this, "^mmu") @@ -66,6 +63,9 @@ void rtpc_iocc_device::device_start() save_item(NAME(m_tcw)); save_item(NAME(m_adc)); save_item(NAME(m_out_int_state)); + + space(AS_PROGRAM).specific(m_mem); + space(AS_IO).specific(m_pio); } void rtpc_iocc_device::device_reset() @@ -86,10 +86,10 @@ u8 rtpc_iocc_device::dma_b_r(offs_t offset) LOGMASKED(LOG_DMA, "dma0 tcw 0x%04x real 0x%08x\n", tcw, real); if (tcw & TCW_IOC) - data = space(AS_PROGRAM).read_byte(real); + data = m_mem.read_byte(real); else { - if (!m_rsc->load(real, data, RSC_N)) + if (!m_rsc->mem_load(real, data, RSC_N)) { // on dma exception // - assert interrupt (level 2) @@ -120,9 +120,9 @@ void rtpc_iocc_device::dma_b_w(offs_t offset, u8 data) LOGMASKED(LOG_DMA, "dma0 tcw 0x%04x real 0x%08x\n", tcw, real); if (tcw & TCW_IOC) - space(AS_PROGRAM).write_byte(real, data); + m_mem.write_byte(real, data); else - m_rsc->store(real, data, RSC_N); + m_rsc->mem_store(real, data, RSC_N); } else fatalerror("rtpc_iocc_device::dma_b_w() invalid dma operation\n"); @@ -139,9 +139,9 @@ u8 rtpc_iocc_device::dma_w_r(offs_t offset) LOGMASKED(LOG_DMA, "dma1 tcw 0x%04x real 0x%08x\n", tcw, real); if (tcw & TCW_IOC) - data = space(AS_PROGRAM).read_word(real); + data = swapendian_int16(m_mem.read_word(real)); else - m_rsc->load(real, data, RSC_N); + m_rsc->mem_load(real, data, RSC_N); } else fatalerror("rtpc_iocc_device::dma_w_r() invalid dma operation\n"); @@ -161,19 +161,22 @@ void rtpc_iocc_device::dma_w_w(offs_t offset, u8 data) 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); + m_mem.write_word(real, swapendian_int16(data)); else - m_rsc->store(real, u16(data), RSC_N); + m_rsc->mem_store(real, u16(data), RSC_N); } else fatalerror("rtpc_iocc_device::dma_w_w() invalid dma operation\n"); } -template bool rtpc_iocc_device::load(u32 address, T &data, rsc_mode const mode) -{ - unsigned const s = (address >> 24) & 15 ? AS_PROGRAM : AS_IO; +#ifdef _MSC_VER +// avoid incorrect MSVC warnings about excessive shift sizes below +#pragma warning(disable:4333) +#endif - if (s == AS_PROGRAM && (mode & RSC_U) && !(m_ccr & CCR_MMP)) +template bool rtpc_iocc_device::mem_load(u32 address, T &data, rsc_mode const mode) +{ + if ((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; @@ -181,68 +184,56 @@ template bool rtpc_iocc_device::load(u32 address, T &data, rsc_mode return false; } - if (s == AS_IO) + switch (sizeof(T)) { - 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; + case 1: data = m_mem.read_byte(address); break; + case 2: data = swapendian_int16(m_mem.read_word(address)); break; + case 4: + data = swapendian_int32(m_mem.read_word(address + 0)); + data |= swapendian_int16(m_mem.read_word(address + 2)); + break; + } + + return true; +} + +template bool rtpc_iocc_device::mem_store(u32 address, T data, rsc_mode const mode) +{ + int 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; } 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 1: m_mem.write_byte(address, data); break; + case 2: m_mem.write_word(address, swapendian_int16(data)); 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); + m_mem.write_word(address + 0, swapendian_int16(data >> 16)); + m_mem.write_word(address + 2, swapendian_int16(data >> 0)); break; } return true; } -#ifdef _MSC_VER -// avoid incorrect MSVC warnings about excessive shift sizes below -#pragma warning(disable:4333) -#endif - -template bool rtpc_iocc_device::store(u32 address, T data, rsc_mode const mode) +template bool rtpc_iocc_device::mem_modify(u32 address, std::function 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)) + if ((mode & RSC_U) && !(m_ccr & CCR_MMP)) { - LOG("store mem protection violation (%s)\n", machine().describe_context()); + LOG("modify mem protection violation (%s)\n", machine().describe_context()); m_csr |= CSR_PER | CSR_PD | CSR_PVIO; if (mode & RSC_T) { @@ -255,70 +246,92 @@ template bool rtpc_iocc_device::store(u32 address, T data, rsc_mode return true; } - if (spacenum == AS_IO && (mode & RSC_U)) + switch (sizeof(T)) { - if (address == 0xf001'0800U || !(m_ccr & CCR_IMP)) + case 1: m_mem.write_byte(address, f(m_mem.read_byte(address))); break; + case 2: m_mem.write_word(address, swapendian_int16(f(swapendian_int16(m_mem.read_word(address))))); break; + case 4: { - 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); + T data = swapendian_int32(m_mem.read_word(address + 0)); + data |= swapendian_int16(m_mem.read_word(address + 2)); - return true; + data = f(data); + + m_mem.write_word(address + 0, swapendian_int16(data >> 16)); + m_mem.write_word(address + 2, swapendian_int16(data >> 0)); } + break; + } + + return true; +} + +template bool rtpc_iocc_device::pio_load(u32 address, T &data, rsc_mode const mode) +{ + if ((mode & RSC_U) && (address == CSR_ADDR || !(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; + } + else if ((address & REG_MASK) == CSR_ADDR) + { + data = m_csr | CSR_RSV; + + return true; + } + else if ((address & REG_MASK) == TCW_BASE) + { + // the multiply creates a halfword smear needed to pass POST + data = m_tcw[(address & ~REG_MASK) >> 1] * 0x0001'0001U; + + return true; } switch (sizeof(T)) { - case 1: space(spacenum).write_byte(address, data); break; + case 1: data = m_pio.read_byte(address); break; case 2: - if (spacenum == AS_IO && target_size(address) < sizeof(T)) + switch (m_pio.lookup_read_word_flags(address) & PIO_SIZE) { - 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)); + case PIO_B: + data = swapendian_int16(m_pio.read_byte(address)); + data |= m_pio.read_byte(address); + LOGMASKED(LOG_WIDEPIO, "load pio w<-b 0x%08x data 0x%04x (%s)\n", address, data, machine().describe_context()); + break; + case PIO_W: + data = swapendian_int16(m_pio.read_word(address)); + break; } - else - space(spacenum).write_word(address, data); break; case 4: - if (spacenum == AS_IO && target_size(address) < sizeof(T)) + switch (m_pio.lookup_read_dword_flags(address) & PIO_SIZE) { - 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)); - } + case PIO_B: + data = u32(m_pio.read_byte(address)) << 24; + data |= u32(m_pio.read_byte(address)) << 16; + data |= u32(m_pio.read_byte(address)) << 8; + data |= u32(m_pio.read_byte(address)) << 0; + LOGMASKED(LOG_WIDEPIO, "load pio d<-b 0x%08x data 0x%08x (%s)\n", address, data, machine().describe_context()); + break; + case PIO_W: + data = swapendian_int32(m_pio.read_word(address)); + data |= swapendian_int16(m_pio.read_word(address)); + LOGMASKED(LOG_WIDEPIO, "load pio d<-w 0x%08x data 0x%08x(%s)\n", address, data, machine().describe_context()); + break; } - else - space(spacenum).write_dword(address, data); break; } return true; } -template bool rtpc_iocc_device::modify(u32 address, std::function f, rsc_mode const mode) +template bool rtpc_iocc_device::pio_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)) + if ((mode & RSC_U) && (address == CSR_ADDR || !(m_ccr & CCR_IMP))) { - LOG("modify mem protection violation (%s)\n", machine().describe_context()); + LOG("store pio protection violation (%s)\n", machine().describe_context()); m_csr |= CSR_PER | CSR_PD | CSR_PVIO; if (mode & RSC_T) { @@ -330,21 +343,64 @@ template bool rtpc_iocc_device::modify(u32 address, std::function> 1] = data; - return false; + return true; } 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; + case 1: m_pio.write_byte(address, data); break; + case 2: + switch (m_pio.lookup_write_word_flags(address) & PIO_SIZE) + { + case PIO_B: + LOGMASKED(LOG_WIDEPIO, "store pio w->b 0x%08x data 0x%04x (%s)\n", address, data, machine().describe_context()); + m_pio.write_byte(address, data >> 8); + m_pio.write_byte(address, data >> 0); + break; + case PIO_W: + m_pio.write_word(address, swapendian_int16(data)); + break; + } + break; + case 4: + switch (m_pio.lookup_write_dword_flags(address) & PIO_SIZE) + { + case PIO_B: + // HACK: suppress excessive logging from frequent delay register word writes + if (address != 0xf000'80e0U) + LOGMASKED(LOG_WIDEPIO, "store pio d->b 0x%08x data 0x%08x (%s)\n", address, data, machine().describe_context()); + m_pio.write_byte(address, data >> 24); + m_pio.write_byte(address, data >> 16); + m_pio.write_byte(address, data >> 8); + m_pio.write_byte(address, data >> 0); + break; + case PIO_W: + LOGMASKED(LOG_WIDEPIO, "store pio d->w 0x%08x data 0x%08x (%s)\n", address, data, machine().describe_context()); + m_pio.write_word(address, swapendian_int16(data >> 16)); + m_pio.write_word(address, swapendian_int16(data >> 0)); + break; + } + break; } return true; } + +template bool rtpc_iocc_device::pio_modify(u32 address, std::function f, rsc_mode const mode) +{ + LOG("modify pio space invalid operation (%s)\n", machine().describe_context()); + m_csr |= CSR_EXR | CSR_PER | CSR_PD | CSR_INVOP; + + return false; +} diff --git a/src/mame/ibm/rtpc_iocc.h b/src/mame/ibm/rtpc_iocc.h index bf4d925a61e..8621a50378f 100644 --- a/src/mame/ibm/rtpc_iocc.h +++ b/src/mame/ibm/rtpc_iocc.h @@ -19,6 +19,14 @@ public: auto out_int() { return m_out_int.bind(); } auto out_rst() { return m_out_rst.bind(); } + enum pio_flags : u16 + { + PIO_B = 0x0000, + PIO_W = 0x0001, + + PIO_SIZE = 0x0001, + }; + enum ccr_mask : u8 { CCR_RFE = 0x02, // refresh enable @@ -67,23 +75,30 @@ public: 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(address, data, mode); } - virtual bool load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode); } - virtual bool load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load(address, data, mode); } - virtual bool store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store(address, data, mode); } - virtual bool store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store(address, data, mode); } - virtual bool store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store(address, data, mode); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } - virtual bool modify(u32 address, std::function f, rsc_mode const mode) override { return modify(address, f, mode); } + // rsc_bus_interface overrides + virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return mem_load(address, data, mode); } + virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return mem_load(address, data, mode); } + virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return mem_load(address, data, mode); } + virtual bool mem_store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return mem_store(address, data, mode); } + virtual bool mem_store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return mem_store(address, data, mode); } + virtual bool mem_store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return mem_store(address, data, mode); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return mem_modify(address, f, mode); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return mem_modify(address, f, mode); } + virtual bool mem_modify(u32 address, std::function f, rsc_mode const mode) override { return mem_modify(address, f, mode); } + + virtual bool pio_load(u32 address, u8 &data, rsc_mode const mode) override { return pio_load(address, data, mode); } + virtual bool pio_load(u32 address, u16 &data, rsc_mode const mode) override { return pio_load(address, data, mode); } + virtual bool pio_load(u32 address, u32 &data, rsc_mode const mode) override { return pio_load(address, data, mode); } + virtual bool pio_store(u32 address, u8 data, rsc_mode const mode) override { return pio_store(address, data, mode); } + virtual bool pio_store(u32 address, u16 data, rsc_mode const mode) override { return pio_store(address, data, mode); } + virtual bool pio_store(u32 address, u32 data, rsc_mode const mode) override { return pio_store(address, data, mode); } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return pio_modify(address, f, mode); } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return pio_modify(address, f, mode); } + virtual bool pio_modify(u32 address, std::function f, rsc_mode const mode) override { return pio_modify(address, f, mode); } u8 ccr_r() { return m_ccr; } void ccr_w(u8 data) { m_ccr = data; } - template 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); @@ -94,9 +109,6 @@ public: 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 void dack_w(int state) { if (!state) m_adc = Channel; } // HACK: temporary workaround for eop handling @@ -111,9 +123,12 @@ protected: virtual space_config_vector memory_space_config() const override; //virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; - template bool load(u32 address, T &data, rsc_mode const mode); - template bool store(u32 address, T data, rsc_mode const mode); - template bool modify(u32 address, std::function f, rsc_mode const mode); + template bool mem_load(u32 address, T &data, rsc_mode const mode); + template bool mem_store(u32 address, T data, rsc_mode const mode); + template bool mem_modify(u32 address, std::function f, rsc_mode const mode); + template bool pio_load(u32 address, T &data, rsc_mode const mode); + template bool pio_store(u32 address, T data, rsc_mode const mode); + template bool pio_modify(u32 address, std::function f, rsc_mode const mode); void set_int(bool state) { @@ -121,39 +136,23 @@ protected: { 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'80e0U) - // exception for i/o delay register - return 4; - 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: + static constexpr u32 REG_MASK = 0xffff'f800U; // on-chip register mask + static constexpr u32 TCW_BASE = 0xf001'0000U; // translation control registers base address + static constexpr u32 CSR_ADDR = 0xf001'0800U; // channel status register address + address_space_config m_mem_config; address_space_config m_pio_config; + memory_access<24, 1, 0, ENDIANNESS_LITTLE>::specific m_mem; + memory_access<24, 1, 0, ENDIANNESS_LITTLE>::specific m_pio; + devcb_write_line m_out_int; devcb_write_line m_out_rst; -- cgit v1.2.3