mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
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
This commit is contained in:
parent
e28f20b2d5
commit
07c20e3faf
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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<u8(u8)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool mem_modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool mem_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool mem_modify(u32 address, std::function<u32(u32)> 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<u8(u8)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool pio_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode = RSC_N) = 0;
|
||||
virtual bool pio_modify(u32 address, std::function<u32(u32)> 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
|
||||
|
@ -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<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); }
|
||||
virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return load<u8>(address, data, mode, sp); }
|
||||
virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return load<u16>(address, data, mode, sp); }
|
||||
virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return load<u32>(address, data, mode, sp); }
|
||||
virtual bool mem_store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return store<u8>(address, data, mode, sp); }
|
||||
virtual bool mem_store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return store<u16>(address, data, mode, sp); }
|
||||
virtual bool mem_store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return store<u32>(address, data, mode, sp); }
|
||||
virtual bool mem_modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode) override { return modify<u8>(address, f, mode); }
|
||||
virtual bool mem_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return modify<u16>(address, f, mode); }
|
||||
virtual bool mem_modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return modify<u32>(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<u8(u8)> f, rsc_mode const mode) override { return false; }
|
||||
virtual bool pio_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return false; }
|
||||
virtual bool pio_modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return false; }
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
@ -64,6 +72,8 @@ protected:
|
||||
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);
|
||||
bool ior(u32 address, u32 &data);
|
||||
bool iow(u32 address, u32 data);
|
||||
|
||||
// register read handlers
|
||||
u32 segment_r(offs_t offset);
|
||||
|
@ -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 <bool SCC> 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<u32> 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 <bool SCC> 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 <bool SCC> 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));
|
||||
}
|
||||
|
||||
m_mcu_p2 &= ~0xdf;
|
||||
m_mcu_p2 |= data & 0xdf;
|
||||
if ((data ^ m_mcu_p2) & 0x40)
|
||||
{
|
||||
|
||||
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 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 -> mcu p2.5 (ibf)
|
||||
if (BIT(data, 5))
|
||||
m_mcu_p2 |= 0x20;
|
||||
else
|
||||
m_mcu_p2 &= ~0x20;
|
||||
// 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 -> 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 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);
|
||||
}
|
||||
|
||||
|
@ -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,84 +161,45 @@ 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 <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)
|
||||
template <typename T> bool rtpc_iocc_device::mem_load(u32 address, T &data, rsc_mode const mode)
|
||||
{
|
||||
unsigned const spacenum = (address >> 24) & 15 ? AS_PROGRAM : AS_IO;
|
||||
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;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (sizeof(T))
|
||||
{
|
||||
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 <typename T> 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))
|
||||
{
|
||||
@ -255,68 +216,22 @@ template <typename T> bool rtpc_iocc_device::store(u32 address, T data, rsc_mode
|
||||
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 1: m_mem.write_byte(address, data); break;
|
||||
case 2: m_mem.write_word(address, swapendian_int16(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);
|
||||
m_mem.write_word(address + 0, swapendian_int16(data >> 16));
|
||||
m_mem.write_word(address + 2, swapendian_int16(data >> 0));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool rtpc_iocc_device::modify(u32 address, std::function<T(T)> f, rsc_mode const mode)
|
||||
template <typename T> bool rtpc_iocc_device::mem_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))
|
||||
if ((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;
|
||||
@ -331,20 +246,161 @@ template <typename T> bool rtpc_iocc_device::modify(u32 address, std::function<T
|
||||
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;
|
||||
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:
|
||||
{
|
||||
T data = swapendian_int32(m_mem.read_word(address + 0));
|
||||
data |= swapendian_int16(m_mem.read_word(address + 2));
|
||||
|
||||
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 <typename T> 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: data = m_pio.read_byte(address); break;
|
||||
case 2:
|
||||
switch (m_pio.lookup_read_word_flags(address) & PIO_SIZE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch (m_pio.lookup_read_dword_flags(address) & PIO_SIZE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool rtpc_iocc_device::pio_store(u32 address, T data, rsc_mode const mode)
|
||||
{
|
||||
if ((mode & RSC_U) && (address == CSR_ADDR || !(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;
|
||||
}
|
||||
else if ((address & REG_MASK) == CSR_ADDR)
|
||||
{
|
||||
m_csr = 0;
|
||||
set_int(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ((address & REG_MASK) == TCW_BASE)
|
||||
{
|
||||
m_tcw[(address & ~REG_MASK) >> 1] = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (sizeof(T))
|
||||
{
|
||||
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 <typename T> bool rtpc_iocc_device::pio_modify(u32 address, std::function<T(T)> 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;
|
||||
}
|
||||
|
@ -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<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); }
|
||||
// rsc_bus_interface overrides
|
||||
virtual bool mem_load(u32 address, u8 &data, rsc_mode const mode, bool sp) override { return mem_load<u8>(address, data, mode); }
|
||||
virtual bool mem_load(u32 address, u16 &data, rsc_mode const mode, bool sp) override { return mem_load<u16>(address, data, mode); }
|
||||
virtual bool mem_load(u32 address, u32 &data, rsc_mode const mode, bool sp) override { return mem_load<u32>(address, data, mode); }
|
||||
virtual bool mem_store(u32 address, u8 data, rsc_mode const mode, bool sp) override { return mem_store<u8>(address, data, mode); }
|
||||
virtual bool mem_store(u32 address, u16 data, rsc_mode const mode, bool sp) override { return mem_store<u16>(address, data, mode); }
|
||||
virtual bool mem_store(u32 address, u32 data, rsc_mode const mode, bool sp) override { return mem_store<u32>(address, data, mode); }
|
||||
virtual bool mem_modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode) override { return mem_modify<u8>(address, f, mode); }
|
||||
virtual bool mem_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return mem_modify<u16>(address, f, mode); }
|
||||
virtual bool mem_modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return mem_modify<u32>(address, f, mode); }
|
||||
|
||||
virtual bool pio_load(u32 address, u8 &data, rsc_mode const mode) override { return pio_load<u8>(address, data, mode); }
|
||||
virtual bool pio_load(u32 address, u16 &data, rsc_mode const mode) override { return pio_load<u16>(address, data, mode); }
|
||||
virtual bool pio_load(u32 address, u32 &data, rsc_mode const mode) override { return pio_load<u32>(address, data, mode); }
|
||||
virtual bool pio_store(u32 address, u8 data, rsc_mode const mode) override { return pio_store<u8>(address, data, mode); }
|
||||
virtual bool pio_store(u32 address, u16 data, rsc_mode const mode) override { return pio_store<u16>(address, data, mode); }
|
||||
virtual bool pio_store(u32 address, u32 data, rsc_mode const mode) override { return pio_store<u32>(address, data, mode); }
|
||||
virtual bool pio_modify(u32 address, std::function<u8(u8)> f, rsc_mode const mode) override { return pio_modify<u8>(address, f, mode); }
|
||||
virtual bool pio_modify(u32 address, std::function<u16(u16)> f, rsc_mode const mode) override { return pio_modify<u16>(address, f, mode); }
|
||||
virtual bool pio_modify(u32 address, std::function<u32(u32)> f, rsc_mode const mode) override { return pio_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);
|
||||
@ -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 <unsigned Channel> 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 <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);
|
||||
template <typename T> bool mem_load(u32 address, T &data, rsc_mode const mode);
|
||||
template <typename T> bool mem_store(u32 address, T data, rsc_mode const mode);
|
||||
template <typename T> bool mem_modify(u32 address, std::function<T(T)> f, rsc_mode const mode);
|
||||
template <typename T> bool pio_load(u32 address, T &data, rsc_mode const mode);
|
||||
template <typename T> bool pio_store(u32 address, T data, rsc_mode const mode);
|
||||
template <typename T> bool pio_modify(u32 address, std::function<T(T)> 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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user