mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
ps2sony: Added skeleton DMAC, INTC, and SIF devices, nw
This commit is contained in:
parent
790009096b
commit
ba4f99c559
@ -3058,10 +3058,18 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/ps2sony.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ps2timer.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ps2timer.h",
|
||||
MAME_DIR .. "src/mame/machine/ioptimer.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ioptimer.h",
|
||||
MAME_DIR .. "src/mame/machine/ps2dma.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ps2dma.h",
|
||||
MAME_DIR .. "src/mame/machine/ps2intc.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ps2intc.h",
|
||||
MAME_DIR .. "src/mame/machine/ps2sif.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ps2sif.h",
|
||||
MAME_DIR .. "src/mame/machine/iopdma.cpp",
|
||||
MAME_DIR .. "src/mame/machine/iopdma.h",
|
||||
MAME_DIR .. "src/mame/machine/iopintc.cpp",
|
||||
MAME_DIR .. "src/mame/machine/iopintc.h",
|
||||
MAME_DIR .. "src/mame/machine/ioptimer.cpp",
|
||||
MAME_DIR .. "src/mame/machine/ioptimer.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "sord")
|
||||
|
@ -635,10 +635,10 @@ void r3000_device::writecache_le_dword(offs_t offset, uint32_t data)
|
||||
EXECEPTION HANDLING
|
||||
***************************************************************************/
|
||||
|
||||
inline void r3000_device::generate_exception(int exception)
|
||||
inline void r3000_device::generate_exception(int exception, bool backup)
|
||||
{
|
||||
// set the exception PC
|
||||
m_cpr[0][COP0_EPC] = (exception == EXCEPTION_SYSCALL ? m_ppc : m_pc);
|
||||
m_cpr[0][COP0_EPC] = backup ? m_ppc : m_pc;
|
||||
|
||||
// put the cause in the low 8 bits and clear the branch delay flag
|
||||
CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
|
||||
@ -668,7 +668,7 @@ inline void r3000_device::generate_exception(int exception)
|
||||
|
||||
inline void r3000_device::invalid_instruction()
|
||||
{
|
||||
generate_exception(EXCEPTION_INVALIDOP);
|
||||
generate_exception(EXCEPTION_INVALIDOP, true);
|
||||
}
|
||||
|
||||
|
||||
@ -679,7 +679,7 @@ inline void r3000_device::invalid_instruction()
|
||||
void r3000_device::check_irqs()
|
||||
{
|
||||
if ((CAUSE & SR & 0xff00) && (SR & SR_IEc))
|
||||
generate_exception(EXCEPTION_INTERRUPT);
|
||||
generate_exception(EXCEPTION_INTERRUPT, false);
|
||||
}
|
||||
|
||||
|
||||
@ -756,7 +756,7 @@ inline void r3000_device::set_cop0_creg(int idx, uint32_t val)
|
||||
inline void r3000_device::handle_cop0()
|
||||
{
|
||||
if (!(SR & SR_COP0) && (SR & SR_KUc))
|
||||
generate_exception(EXCEPTION_BADCOP);
|
||||
generate_exception(EXCEPTION_BADCOP, true);
|
||||
|
||||
switch (RSREG)
|
||||
{
|
||||
@ -833,7 +833,7 @@ inline void r3000_device::set_cop1_creg(int idx, uint32_t val)
|
||||
inline void r3000_device::handle_cop1()
|
||||
{
|
||||
if (!(SR & SR_COP1))
|
||||
generate_exception(EXCEPTION_BADCOP);
|
||||
generate_exception(EXCEPTION_BADCOP, true);
|
||||
if (!m_hasfpu)
|
||||
return;
|
||||
|
||||
@ -901,7 +901,7 @@ inline void r3000_device::set_cop2_creg(int idx, uint32_t val)
|
||||
inline void r3000_device::handle_cop2()
|
||||
{
|
||||
if (!(SR & SR_COP2))
|
||||
generate_exception(EXCEPTION_BADCOP);
|
||||
generate_exception(EXCEPTION_BADCOP, true);
|
||||
|
||||
switch (RSREG)
|
||||
{
|
||||
@ -967,7 +967,7 @@ inline void r3000_device::set_cop3_creg(int idx, uint32_t val)
|
||||
inline void r3000_device::handle_cop3()
|
||||
{
|
||||
if (!(SR & SR_COP3))
|
||||
generate_exception(EXCEPTION_BADCOP);
|
||||
generate_exception(EXCEPTION_BADCOP, true);
|
||||
|
||||
switch (RSREG)
|
||||
{
|
||||
@ -1076,6 +1076,20 @@ void r3000_device::execute_run()
|
||||
m_ppc = m_pc;
|
||||
debugger_instruction_hook(m_pc);
|
||||
|
||||
if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C)
|
||||
{
|
||||
uint32_t ptr = m_r[5];
|
||||
uint32_t length = m_r[6];
|
||||
if (length >= 4096)
|
||||
length = 4095;
|
||||
while (length)
|
||||
{
|
||||
printf("%c", (char)RBYTE(ptr));
|
||||
ptr++;
|
||||
length--;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
// instruction fetch
|
||||
m_op = readop(m_pc);
|
||||
|
||||
@ -1102,9 +1116,9 @@ void r3000_device::execute_run()
|
||||
case 0x07: /* SRAV */ if (RDREG) RDVAL = (int32_t)RTVAL >> (RSVAL & 31); break;
|
||||
case 0x08: /* JR */ SETPC(RSVAL); break;
|
||||
case 0x09: /* JALR */ SETPCL(RSVAL, RDREG); break;
|
||||
case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL); break;
|
||||
case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK); break;
|
||||
case 0x0f: /* SYNC */ invalid_instruction(); break;
|
||||
case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL, true); break;
|
||||
case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK, true); break;
|
||||
case 0x0f: /* SYNC */ invalid_instruction(); break;
|
||||
case 0x10: /* MFHI */ if (RDREG) RDVAL = m_hi; break;
|
||||
case 0x11: /* MTHI */ m_hi = RSVAL; break;
|
||||
case 0x12: /* MFLO */ if (RDREG) RDVAL = m_lo; break;
|
||||
@ -1138,12 +1152,12 @@ void r3000_device::execute_run()
|
||||
m_icount -= 34;
|
||||
break;
|
||||
case 0x20: /* ADD */
|
||||
if (ENABLE_OVERFLOWS && RSVAL > ~RTVAL) generate_exception(EXCEPTION_OVERFLOW);
|
||||
if (ENABLE_OVERFLOWS && RSVAL > ~RTVAL) generate_exception(EXCEPTION_OVERFLOW, true);
|
||||
else RDVAL = RSVAL + RTVAL;
|
||||
break;
|
||||
case 0x21: /* ADDU */ if (RDREG) RDVAL = RSVAL + RTVAL; break;
|
||||
case 0x22: /* SUB */
|
||||
if (ENABLE_OVERFLOWS && RSVAL < RTVAL) generate_exception(EXCEPTION_OVERFLOW);
|
||||
if (ENABLE_OVERFLOWS && RSVAL < RTVAL) generate_exception(EXCEPTION_OVERFLOW, true);
|
||||
else RDVAL = RSVAL - RTVAL;
|
||||
break;
|
||||
case 0x23: /* SUBU */ if (RDREG) RDVAL = RSVAL - RTVAL; break;
|
||||
@ -1191,7 +1205,7 @@ void r3000_device::execute_run()
|
||||
case 0x06: /* BLEZ */ if ((int32_t)RSVAL <= 0) ADDPC(SIMMVAL); break;
|
||||
case 0x07: /* BGTZ */ if ((int32_t)RSVAL > 0) ADDPC(SIMMVAL); break;
|
||||
case 0x08: /* ADDI */
|
||||
if (ENABLE_OVERFLOWS && RSVAL > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW);
|
||||
if (ENABLE_OVERFLOWS && RSVAL > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW, true);
|
||||
else if (RTREG) RTVAL = RSVAL + SIMMVAL;
|
||||
break;
|
||||
case 0x09: /* ADDIU */ if (RTREG) RTVAL = RSVAL + SIMMVAL; break;
|
||||
|
@ -150,7 +150,7 @@ protected:
|
||||
void writecache_le_dword(offs_t offset, uint32_t data);
|
||||
|
||||
// interrupts
|
||||
void generate_exception(int exception);
|
||||
void generate_exception(int exception, bool backup);
|
||||
void check_irqs();
|
||||
void set_irq_line(int irqline, int state);
|
||||
void invalid_instruction();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,33 +16,156 @@ DEFINE_DEVICE_TYPE(SONYIOP_DMA, iop_dma_device, "iopdma", "Sony IOP DMA")
|
||||
|
||||
iop_dma_device::iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONYIOP_DMA, tag, owner, clock)
|
||||
, device_execute_interface(mconfig, *this)
|
||||
, m_intc(*this, finder_base::DUMMY_TAG)
|
||||
, m_ram(*this, finder_base::DUMMY_TAG)
|
||||
, m_sif(*this, finder_base::DUMMY_TAG)
|
||||
, m_icount(0)
|
||||
{
|
||||
}
|
||||
|
||||
void iop_dma_device::device_start()
|
||||
{
|
||||
set_icountptr(m_icount);
|
||||
|
||||
for (uint32_t channel = 0; channel < 16; channel++)
|
||||
{
|
||||
save_item(NAME(m_channels[channel].m_priority), channel);
|
||||
save_item(NAME(m_channels[channel].m_enabled), channel);
|
||||
save_item(NAME(m_channels[channel].m_busy), channel);
|
||||
save_item(NAME(m_channels[channel].m_end), channel);
|
||||
|
||||
save_item(NAME(m_channels[channel].m_addr), channel);
|
||||
save_item(NAME(m_channels[channel].m_block), channel);
|
||||
save_item(NAME(m_channels[channel].m_ctrl), channel);
|
||||
save_item(NAME(m_channels[channel].m_tag_addr), channel);
|
||||
|
||||
save_item(NAME(m_channels[channel].m_size), channel);
|
||||
save_item(NAME(m_channels[channel].m_count), channel);
|
||||
}
|
||||
|
||||
save_item(NAME(m_running_mask));
|
||||
save_item(NAME(m_icount));
|
||||
save_item(NAME(m_dpcr[0]));
|
||||
save_item(NAME(m_dpcr[1]));
|
||||
save_item(NAME(m_dicr[0]));
|
||||
save_item(NAME(m_dicr[1]));
|
||||
save_item(NAME(m_int_ctrl[0].m_mask));
|
||||
save_item(NAME(m_int_ctrl[0].m_status));
|
||||
save_item(NAME(m_int_ctrl[0].m_enabled));
|
||||
save_item(NAME(m_int_ctrl[1].m_mask));
|
||||
save_item(NAME(m_int_ctrl[1].m_status));
|
||||
save_item(NAME(m_int_ctrl[1].m_enabled));
|
||||
|
||||
save_item(NAME(m_last_serviced));
|
||||
}
|
||||
|
||||
void iop_dma_device::device_reset()
|
||||
{
|
||||
memset(m_channels, 0, sizeof(channel_t) * 16);
|
||||
memset(m_int_ctrl, 0, sizeof(intctrl_t) * 2);
|
||||
m_dpcr[0] = 0;
|
||||
m_dpcr[1] = 0;
|
||||
m_dicr[0] = 0;
|
||||
m_dicr[1] = 0;
|
||||
m_last_serviced = 0;
|
||||
}
|
||||
|
||||
READ32_MEMBER(iop_dma_device::ctrl0_r)
|
||||
void iop_dma_device::execute_run()
|
||||
{
|
||||
if (!m_running_mask)
|
||||
{
|
||||
m_icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while (m_icount > 0)
|
||||
{
|
||||
// TODO: Is this right? This doesn't seem right.
|
||||
for (; m_last_serviced < 16; m_last_serviced++)
|
||||
{
|
||||
const uint32_t channel = m_last_serviced;
|
||||
if (m_channels[channel].enabled() && m_channels[channel].busy())
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 11:
|
||||
transfer_sif1(channel);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: Attempting to transfer an unimplemented DMA channel (%d)\n", machine().describe_context(), channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_last_serviced == 16)
|
||||
m_last_serviced = 0;
|
||||
m_icount--;
|
||||
}
|
||||
}
|
||||
|
||||
void iop_dma_device::transfer_sif1(uint32_t chan)
|
||||
{
|
||||
channel_t &channel = m_channels[chan];
|
||||
if (channel.m_count)
|
||||
{
|
||||
if (m_sif->fifo_depth(1))
|
||||
{
|
||||
printf(".");
|
||||
const uint64_t data = m_sif->fifo_pop(1);
|
||||
m_ram[channel.m_addr >> 2] = data;
|
||||
|
||||
channel.m_addr += 4;
|
||||
channel.m_count--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channel.end())
|
||||
{
|
||||
channel.m_ctrl &= ~0x1000000;
|
||||
channel.m_busy = false;
|
||||
const uint32_t index = BIT(chan, 3);
|
||||
const uint8_t subchan = chan & 7;
|
||||
m_int_ctrl[index].m_status |= (1 << subchan);
|
||||
m_dicr[index] |= 1 << (subchan + 24);
|
||||
printf("channel.end\n");
|
||||
if (m_int_ctrl[index].m_status & m_int_ctrl[index].m_mask)
|
||||
{
|
||||
printf("raising interrupt\n");
|
||||
m_intc->raise_interrupt(iop_intc_device::INT_DMA);
|
||||
}
|
||||
}
|
||||
else if (m_sif->fifo_depth(1) >= 4)
|
||||
{
|
||||
const uint32_t next_tag = m_sif->fifo_pop(1);
|
||||
channel.m_addr = next_tag & 0x00ffffff;
|
||||
channel.m_count = m_sif->fifo_pop(1);
|
||||
|
||||
// ??
|
||||
m_sif->fifo_pop(1);
|
||||
m_sif->fifo_pop(1);
|
||||
|
||||
if (next_tag & 0xc0000000)
|
||||
{
|
||||
channel.m_end = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(iop_dma_device::bank0_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // 0x1f8010f0, DPCR
|
||||
case 0x70/4: // 0x1f8010f0, DPCR
|
||||
ret = m_dpcr[0];
|
||||
logerror("%s: ctrl0_r: DPCR (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: bank0_r: DPCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 1: // 0x1f8010f4, DICR
|
||||
case 0x74/4: // 0x1f8010f4, DICR
|
||||
ret = m_dicr[0];
|
||||
logerror("%s: ctrl0_r: DICR (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: bank0_r: DICR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
// Can't happen
|
||||
@ -51,16 +174,33 @@ READ32_MEMBER(iop_dma_device::ctrl0_r)
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(iop_dma_device::ctrl0_w)
|
||||
WRITE32_MEMBER(iop_dma_device::bank0_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // 0x1f8010f0, DPCR
|
||||
logerror("%s: ctrl0_w: DPCR = %08x\n", machine().describe_context(), data);
|
||||
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
|
||||
logerror("%s: bank0_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
|
||||
m_channels[offset >> 2].set_addr(data);
|
||||
break;
|
||||
case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4:
|
||||
logerror("%s: bank0_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
|
||||
m_channels[offset >> 2].set_block(data, mem_mask);
|
||||
break;
|
||||
case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4:
|
||||
logerror("%s: bank0_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
|
||||
m_channels[offset >> 2].set_ctrl(data);
|
||||
m_running_mask |= m_channels[offset >> 2].busy() ? (1 << (offset >> 2)) : 0;
|
||||
break;
|
||||
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
|
||||
logerror("%s: bank0_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), offset >> 2, data, mem_mask);
|
||||
m_channels[offset >> 2].set_tag_addr(data);
|
||||
break;
|
||||
case 0x70/4: // 0x1f8010f0, DPCR
|
||||
logerror("%s: bank0_w: DPCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
set_dpcr(data, 0);
|
||||
break;
|
||||
case 1: // 0x1f8010f4, DICR
|
||||
logerror("%s: ctrl0_w: DICR = %08x\n", machine().describe_context(), data);
|
||||
case 0x74/4: // 0x1f8010f4, DICR
|
||||
logerror("%s: bank0_w: DICR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
set_dicr(data, 0);
|
||||
break;
|
||||
default:
|
||||
@ -69,18 +209,18 @@ WRITE32_MEMBER(iop_dma_device::ctrl0_w)
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(iop_dma_device::ctrl1_r)
|
||||
READ32_MEMBER(iop_dma_device::bank1_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // 0x1f801570, DPCR2
|
||||
case 0x70/4: // 0x1f801570, DPCR2
|
||||
ret = m_dpcr[1];
|
||||
logerror("%s: ctrl1_r: DPCR2 (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: bank1_r: DPCR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 1: // 0x1f801574, DICR2
|
||||
case 0x74/4: // 0x1f801574, DICR2
|
||||
ret = m_dicr[1];
|
||||
logerror("%s: ctrl1_r: DICR2 (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: bank1_r: DICR2 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
// Can't happen
|
||||
@ -89,16 +229,33 @@ READ32_MEMBER(iop_dma_device::ctrl1_r)
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(iop_dma_device::ctrl1_w)
|
||||
WRITE32_MEMBER(iop_dma_device::bank1_w)
|
||||
{
|
||||
switch (offset)
|
||||
switch (offset & 0x1f)
|
||||
{
|
||||
case 0: // 0x1f8010f0, DPCR
|
||||
logerror("%s: ctrl1_w: DPCR2 = %08x\n", machine().describe_context(), data);
|
||||
case 0x00/4: case 0x10/4: case 0x20/4: case 0x30/4: case 0x40/4: case 0x50/4: case 0x60/4:
|
||||
logerror("%s: bank1_w: channel[%d].addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
|
||||
m_channels[(offset >> 2) + 8].set_addr(data);
|
||||
break;
|
||||
case 0x04/4: case 0x14/4: case 0x24/4: case 0x34/4: case 0x44/4: case 0x54/4: case 0x64/4:
|
||||
logerror("%s: bank1_w: channel[%d].block = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
|
||||
m_channels[(offset >> 2) + 8].set_block(data, mem_mask);
|
||||
break;
|
||||
case 0x08/4: case 0x18/4: case 0x28/4: case 0x38/4: case 0x48/4: case 0x58/4: case 0x68/4:
|
||||
logerror("%s: bank1_w: channel[%d].ctrl = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
|
||||
m_channels[(offset >> 2) + 8].set_ctrl(data);
|
||||
m_running_mask |= m_channels[(offset >> 2) + 8].busy() ? (1 << ((offset >> 2) + 8)) : 0;
|
||||
break;
|
||||
case 0x0c/4: case 0x1c/4: case 0x2c/4: case 0x3c/4: case 0x4c/4: case 0x5c/4: case 0x6c/4:
|
||||
logerror("%s: bank1_w: channel[%d].tag_addr = %08x & %08x\n", machine().describe_context(), (offset >> 2) + 8, data, mem_mask);
|
||||
m_channels[(offset >> 2) + 8].set_tag_addr(data);
|
||||
break;
|
||||
case 0x70/4: // 0x1f801570, DPCR2
|
||||
logerror("%s: bank1_w: DPCR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
set_dpcr(data, 1);
|
||||
break;
|
||||
case 1: // 0x1f8010f4, DICR
|
||||
logerror("%s: ctrl1_w: DICR2 = %08x\n", machine().describe_context(), data);
|
||||
case 0x74/4: // 0x1f801574, DICR2
|
||||
logerror("%s: bank1_w: DICR2 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
set_dicr(data, 1);
|
||||
break;
|
||||
default:
|
||||
@ -118,14 +275,11 @@ void iop_dma_device::set_dpcr(uint32_t data, uint32_t index)
|
||||
for (uint32_t channel = index*8, bit = 0; channel < index*8 + 8; channel++, bit += 4)
|
||||
{
|
||||
const uint8_t field = (data >> bit) & 0xf;
|
||||
const bool was_enabled = m_channels[channel].m_enabled;
|
||||
const bool is_enabled = BIT(field, 3);
|
||||
m_channels[channel].m_enabled = is_enabled;
|
||||
m_channels[channel].m_priority = field & 7;
|
||||
if (!was_enabled && is_enabled)
|
||||
{
|
||||
// Check for running status?
|
||||
}
|
||||
m_channels[channel].set_pri_ctrl(field);
|
||||
if (BIT(field, 3))
|
||||
m_running_mask |= 0x10000 << channel;
|
||||
else
|
||||
m_running_mask &= ~(0x10000 << channel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,3 +291,33 @@ void iop_dma_device::set_dicr(uint32_t data, uint32_t index)
|
||||
m_int_ctrl[index].m_enabled = BIT(data, 23);
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void iop_dma_device::channel_t::set_pri_ctrl(uint32_t pri_ctrl)
|
||||
{
|
||||
m_enabled = BIT(pri_ctrl, 3);
|
||||
m_priority = pri_ctrl & 7;
|
||||
}
|
||||
|
||||
void iop_dma_device::channel_t::set_addr(uint32_t addr)
|
||||
{
|
||||
m_addr = addr;
|
||||
}
|
||||
|
||||
void iop_dma_device::channel_t::set_block(uint32_t block, uint32_t mem_mask)
|
||||
{
|
||||
if (mem_mask & 0xffff)
|
||||
m_count = (uint16_t)block;
|
||||
if (mem_mask & 0xffff0000)
|
||||
m_size = (uint16_t)(block >> 16);
|
||||
}
|
||||
|
||||
void iop_dma_device::channel_t::set_ctrl(uint32_t ctrl)
|
||||
{
|
||||
m_ctrl = ctrl;
|
||||
m_busy = BIT(ctrl, 24);
|
||||
}
|
||||
|
||||
void iop_dma_device::channel_t::set_tag_addr(uint32_t tag_addr)
|
||||
{
|
||||
m_tag_addr = tag_addr;
|
||||
}
|
||||
|
@ -14,16 +14,48 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#include "ps2sif.h"
|
||||
#include "iopintc.h"
|
||||
|
||||
class iop_dma_device : public device_t
|
||||
class iop_dma_device : public device_t, public device_execute_interface
|
||||
{
|
||||
public:
|
||||
template <typename T, typename U, typename V>
|
||||
iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc_tag, U &&ram_tag, V &&sif_tag)
|
||||
: iop_dma_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
m_intc.set_tag(std::forward<T>(intc_tag));
|
||||
m_ram.set_tag(std::forward<U>(ram_tag));
|
||||
m_sif.set_tag(std::forward<V>(sif_tag));
|
||||
}
|
||||
|
||||
iop_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_READ32_MEMBER(ctrl0_r);
|
||||
DECLARE_WRITE32_MEMBER(ctrl0_w);
|
||||
DECLARE_READ32_MEMBER(ctrl1_r);
|
||||
DECLARE_WRITE32_MEMBER(ctrl1_w);
|
||||
DECLARE_READ32_MEMBER(bank0_r);
|
||||
DECLARE_WRITE32_MEMBER(bank0_w);
|
||||
DECLARE_READ32_MEMBER(bank1_r);
|
||||
DECLARE_WRITE32_MEMBER(bank1_w);
|
||||
|
||||
enum channel_type : uint32_t
|
||||
{
|
||||
MDEC_IN = 0,
|
||||
MDEC_OUT,
|
||||
GPU,
|
||||
CDVD,
|
||||
SPU,
|
||||
PIO,
|
||||
OTC,
|
||||
UNUSED_BANK0,
|
||||
SPU2,
|
||||
UNKNOWN0,
|
||||
SIF0,
|
||||
SIF1,
|
||||
SIO2_IN,
|
||||
SIO2_OUT,
|
||||
UNKNOWN1,
|
||||
UNUSED_BANK1
|
||||
};
|
||||
|
||||
protected:
|
||||
struct intctrl_t
|
||||
@ -33,23 +65,68 @@ protected:
|
||||
bool m_enabled;
|
||||
};
|
||||
|
||||
struct channel_t
|
||||
class channel_t
|
||||
{
|
||||
friend class iop_dma_device;
|
||||
|
||||
public:
|
||||
channel_t()
|
||||
: m_priority(0), m_enabled(false), m_addr(0), m_block(0), m_ctrl(0), m_tag_addr(0), m_size(0), m_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void set_pri_ctrl(uint32_t pri_ctrl);
|
||||
void set_addr(uint32_t addr);
|
||||
void set_block(uint32_t block, uint32_t mem_mask);
|
||||
void set_ctrl(uint32_t ctrl);
|
||||
void set_tag_addr(uint32_t tag_addr);
|
||||
|
||||
bool enabled() const { return m_enabled; }
|
||||
bool busy() const { return m_busy; }
|
||||
uint32_t addr() const { return m_addr; }
|
||||
uint32_t block() const { return m_block; }
|
||||
uint32_t ctrl() const { return m_ctrl; }
|
||||
uint32_t tag_addr() const { return m_tag_addr; }
|
||||
bool end() const { return m_end; }
|
||||
|
||||
protected:
|
||||
uint8_t m_priority;
|
||||
bool m_enabled;
|
||||
bool m_busy;
|
||||
bool m_end;
|
||||
|
||||
uint32_t m_addr;
|
||||
uint32_t m_block;
|
||||
uint32_t m_ctrl;
|
||||
uint32_t m_tag_addr;
|
||||
|
||||
uint32_t m_size;
|
||||
uint32_t m_count;
|
||||
};
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void execute_run() override;
|
||||
|
||||
void set_dpcr(uint32_t data, uint32_t index);
|
||||
void set_dicr(uint32_t data, uint32_t index);
|
||||
void update_interrupts();
|
||||
|
||||
void transfer_sif1(uint32_t chan);
|
||||
|
||||
required_device<iop_intc_device> m_intc;
|
||||
required_shared_ptr<uint32_t> m_ram;
|
||||
required_device<ps2_sif_device> m_sif;
|
||||
|
||||
int m_icount;
|
||||
|
||||
uint32_t m_dpcr[2];
|
||||
uint32_t m_dicr[2];
|
||||
channel_t m_channels[16];
|
||||
intctrl_t m_int_ctrl[2];
|
||||
|
||||
uint32_t m_running_mask;
|
||||
uint32_t m_last_serviced;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYIOP_DMA, iop_dma_device)
|
||||
|
98
src/mame/machine/iopintc.cpp
Normal file
98
src/mame/machine/iopintc.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 IOP interrupt controller device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iopintc.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SONYIOP_INTC, iop_intc_device, "iopintc", "Playstation 2 IOP INTC")
|
||||
|
||||
iop_intc_device::iop_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONYIOP_INTC, tag, owner, clock)
|
||||
, m_iop(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void iop_intc_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_mask));
|
||||
save_item(NAME(m_enabled));
|
||||
}
|
||||
|
||||
void iop_intc_device::device_reset()
|
||||
{
|
||||
m_status = 0;
|
||||
m_mask = 0;
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
READ32_MEMBER(iop_intc_device::read)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // I_STAT
|
||||
ret = m_status;
|
||||
logerror("%s: read: I_STAT %08x & %08x\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 1: // I_MASK
|
||||
ret = m_mask;
|
||||
logerror("%s: read: I_MASK %08x & %08x\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 2: // I_ENABLE
|
||||
ret = m_enabled ? 1 : 0;
|
||||
m_enabled = false;
|
||||
update_interrupts();
|
||||
//logerror("%s: read: I_ENABLE %08x & %08x\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: read: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1f801070 + (offset << 2), mem_mask);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(iop_intc_device::write)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // I_STAT
|
||||
logerror("%s: write: I_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_status &= data;
|
||||
update_interrupts();
|
||||
break;
|
||||
case 1: // I_MASK
|
||||
logerror("%s: write: I_MASK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_mask = data;
|
||||
update_interrupts();
|
||||
break;
|
||||
case 2: // I_ENABLE
|
||||
//logerror("%s: write: I_ENABLE = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_enabled = BIT(data, 0);
|
||||
update_interrupts();
|
||||
break;
|
||||
default:
|
||||
logerror("%s: write: Unknown offset %08x = %08x & %08x\n", machine().describe_context(), 0x1f801070 + (offset << 2), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void iop_intc_device::raise_interrupt(uint32_t line)
|
||||
{
|
||||
logerror("%s: raise_interrupt: %d\n", machine().describe_context(), line);
|
||||
m_status |= (1 << line);
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void iop_intc_device::update_interrupts()
|
||||
{
|
||||
bool active = (m_enabled && (m_status & m_mask));
|
||||
m_iop->set_input_line(R3000_IRQ0, active ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
59
src/mame/machine/iopintc.h
Normal file
59
src/mame/machine/iopintc.h
Normal file
@ -0,0 +1,59 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 IOP interrupt controller device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_IOPINTC_H
|
||||
#define MAME_MACHINE_IOPINTC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mips/r3000.h"
|
||||
|
||||
class iop_intc_device : public device_t
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
iop_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&iop_tag)
|
||||
: iop_intc_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
m_iop.set_tag(std::forward<T>(iop_tag));
|
||||
}
|
||||
|
||||
iop_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
|
||||
void raise_interrupt(uint32_t line);
|
||||
|
||||
enum
|
||||
{
|
||||
INT_VB_ON = 0,
|
||||
INT_DMA = 3,
|
||||
INT_VB_OFF = 11,
|
||||
INT_TIMER = 16
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void update_interrupts();
|
||||
|
||||
required_device<iop_device> m_iop;
|
||||
uint32_t m_status;
|
||||
uint32_t m_mask;
|
||||
bool m_enabled;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYIOP_INTC, iop_intc_device)
|
||||
|
||||
#endif // MAME_MACHINE_IOPINTC_H
|
@ -209,18 +209,18 @@ READ32_MEMBER(iop_timer_device::read)
|
||||
update_count();
|
||||
ret = m_count;
|
||||
if (old != m_count)
|
||||
logerror("%s: IOP timer read: COUNT (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: IOP timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x01:
|
||||
ret = m_ctrl | (m_ovf_int ? CTRL_OVFF : 0) | (m_cmp_int ? CTRL_CMPF : 0);
|
||||
logerror("%s: IOP timer read: MODE (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: IOP timer read: MODE (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
ret = m_compare;
|
||||
logerror("%s: IOP timer read: COMPARE (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: IOP timer read: COMPARE (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -235,7 +235,7 @@ WRITE32_MEMBER(iop_timer_device::write)
|
||||
{
|
||||
case 0x00:
|
||||
m_count = data;
|
||||
logerror("%s: IOP timer write: COUNT = %08x\n", machine().describe_context(), data);
|
||||
logerror("%s: IOP timer write: COUNT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
update_compare_timer();
|
||||
update_overflow_timer();
|
||||
break;
|
||||
@ -246,7 +246,7 @@ WRITE32_MEMBER(iop_timer_device::write)
|
||||
|
||||
case 0x02:
|
||||
{
|
||||
logerror("%s: IOP timer write: COMPARE = %08x\n", machine().describe_context(), data);
|
||||
logerror("%s: IOP timer write: COMPARE = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
if (m_compare == data)
|
||||
break;
|
||||
|
||||
|
544
src/mame/machine/ps2dma.cpp
Normal file
544
src/mame/machine/ps2dma.cpp
Normal file
@ -0,0 +1,544 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 DMAC device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ps2sif.h"
|
||||
#include "ps2dma.h"
|
||||
#include "cpu/mips/mips3.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SONYPS2_DMAC, ps2_dmac_device, "ps2dmac", "EE Core DMAC")
|
||||
|
||||
ps2_dmac_device::ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONYPS2_DMAC, tag, owner, clock)
|
||||
, device_execute_interface(mconfig, *this)
|
||||
, m_ee(*this, finder_base::DUMMY_TAG)
|
||||
, m_ram(*this, finder_base::DUMMY_TAG)
|
||||
, m_sif(*this, finder_base::DUMMY_TAG)
|
||||
, m_icount(0)
|
||||
{
|
||||
}
|
||||
|
||||
void ps2_dmac_device::device_start()
|
||||
{
|
||||
set_icountptr(m_icount);
|
||||
|
||||
for (uint32_t channel = 0; channel < 10; channel++)
|
||||
{
|
||||
//save_item(NAME(m_channels[channel].m_priority), channel);
|
||||
}
|
||||
|
||||
save_item(NAME(m_icount));
|
||||
save_item(NAME(m_ctrl));
|
||||
save_item(NAME(m_mem_drain));
|
||||
save_item(NAME(m_enabled));
|
||||
|
||||
save_item(NAME(m_disable_mask));
|
||||
|
||||
save_item(NAME(m_istat));
|
||||
save_item(NAME(m_imask));
|
||||
|
||||
save_item(NAME(m_last_serviced));
|
||||
|
||||
for (uint32_t channel = 0; channel < 10; channel++)
|
||||
{
|
||||
save_item(NAME(m_channels[channel].m_chcr), channel);
|
||||
save_item(NAME(m_channels[channel].m_mode), channel);
|
||||
save_item(NAME(m_channels[channel].m_enabled), channel);
|
||||
save_item(NAME(m_channels[channel].m_end_tag), channel);
|
||||
save_item(NAME(m_channels[channel].m_qwc), channel);
|
||||
save_item(NAME(m_channels[channel].m_addr), channel);
|
||||
}
|
||||
}
|
||||
|
||||
void ps2_dmac_device::device_reset()
|
||||
{
|
||||
m_ctrl = 0;
|
||||
m_mem_drain = 0;
|
||||
m_enabled = false;
|
||||
|
||||
m_disable_mask = 0x1201;
|
||||
|
||||
m_istat = 0;
|
||||
m_imask = 0;
|
||||
|
||||
m_last_serviced = 0;
|
||||
}
|
||||
|
||||
void ps2_dmac_device::execute_run()
|
||||
{
|
||||
if (!m_enabled || (m_disable_mask & 0x10000))
|
||||
{
|
||||
m_icount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while (m_icount > 0)
|
||||
{
|
||||
for (; m_last_serviced < 10 && m_icount > 0; m_last_serviced++, m_icount--)
|
||||
{
|
||||
if (!m_channels[m_last_serviced].enabled())
|
||||
continue;
|
||||
|
||||
switch (m_last_serviced)
|
||||
{
|
||||
case SIF0:
|
||||
transfer_sif0();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_last_serviced == 10)
|
||||
m_last_serviced = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ps2_dmac_device::transfer_sif0()
|
||||
{
|
||||
channel_t &channel = m_channels[SIF0];
|
||||
const uint32_t count = channel.quadword_count();
|
||||
if (count)
|
||||
{
|
||||
printf("count\n");
|
||||
if (m_sif->fifo_depth(0) > 4)
|
||||
{
|
||||
const uint32_t addr = channel.addr();
|
||||
for (uint32_t word = 0; word < 4; word++)
|
||||
{
|
||||
m_ee->space(AS_PROGRAM).write_dword(addr + word, m_sif->fifo_pop(0));
|
||||
}
|
||||
channel.set_addr(addr + 0x10);
|
||||
channel.set_quadword_count(count - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channel.end_tag())
|
||||
{
|
||||
printf("end\n");
|
||||
transfer_finish(SIF0);
|
||||
}
|
||||
else if (m_sif->fifo_depth(0) >= 2)
|
||||
{
|
||||
printf("follow\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ps2_dmac_device::follow_tag(uint32_t channel)
|
||||
{
|
||||
}
|
||||
|
||||
void ps2_dmac_device::transfer_finish(uint32_t chan)
|
||||
{
|
||||
channel_t &channel = m_channels[chan];
|
||||
channel.set_chcr(channel.chcr() & ~0x100);
|
||||
m_istat |= (1 << chan);
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void ps2_dmac_device::update_interrupts()
|
||||
{
|
||||
logerror("%s: update_interrupts: %d\n", machine().describe_context(), (m_istat & m_imask) ? 1 : 0);
|
||||
m_ee->set_input_line(MIPS3_IRQ1, (m_istat & m_imask) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_dmac_device::read)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0: /* D_CTRL */
|
||||
ret = m_ctrl;
|
||||
logerror("%s: dmac_r: D_CTRL (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 2: /* D_STAT */
|
||||
ret = m_istat | (m_imask << 16);
|
||||
logerror("%s: dmac_r: D_STAT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 4: /* D_PCR */
|
||||
logerror("%s: dmac_r: D_PCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 6: /* D_SQWC */
|
||||
logerror("%s: dmac_r: D_SQWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 8: /* D_RBSR */
|
||||
logerror("%s: dmac_r: D_RBSR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 10: /* D_RBOR */
|
||||
logerror("%s: dmac_r: D_RBOR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 12: /* D_STADR */
|
||||
logerror("%s: dmac_r: D_STADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: dmac_r: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1000e000 + (offset << 3), mem_mask);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_dmac_device::write)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: /* D_CTRL */
|
||||
logerror("%s: dmac_w: D_CTRL = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
logerror("%s: ENABLE=%d MEM_DRAIN=%d\n", machine().describe_context(), BIT(data, 0), (data >> 2) & 3);
|
||||
m_enabled = BIT(data, 0);
|
||||
m_mem_drain = (data >> 2) & 3;
|
||||
break;
|
||||
case 2: /* D_STAT */
|
||||
logerror("%s: dmac_w: D_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_istat &= ~(data & 0x7fff);
|
||||
m_imask ^= (data >> 16) & 0x7fff;
|
||||
update_interrupts();
|
||||
break;
|
||||
case 4: /* D_PCR */
|
||||
logerror("%s: dmac_w: D_PCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 6: /* D_SQWC */
|
||||
logerror("%s: dmac_w: D_SQWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 8: /* D_RBSR */
|
||||
logerror("%s: dmac_w: D_RBSR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 10: /* D_RBOR */
|
||||
logerror("%s: dmac_w: D_RBOR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 12: /* D_STADR */
|
||||
logerror("%s: dmac_w: D_STADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: dmac_w: Unknown offset %08x = %08X & %08x\n", machine().describe_context(), 0x1000e000 + (offset << 3), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_dmac_device::channel_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset + 0x8000/8)
|
||||
{
|
||||
case 0x8000/8: /* D0_CHCR */
|
||||
logerror("%s: dmac_channel_r: D0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x8010/8: /* D0_MADR */
|
||||
logerror("%s: dmac_channel_r: D0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x8020/8: /* D0_QWC */
|
||||
logerror("%s: dmac_channel_r: D0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x8030/8: /* D0_TADR */
|
||||
logerror("%s: dmac_channel_r: D0_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x8040/8: /* D0_ASR0 */
|
||||
logerror("%s: dmac_channel_r: D0_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x8050/8: /* D0_ASR1 */
|
||||
logerror("%s: dmac_channel_r: D0_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9000/8: /* D1_CHCR */
|
||||
logerror("%s: dmac_channel_r: D1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9010/8: /* D1_MADR */
|
||||
logerror("%s: dmac_channel_r: D1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9020/8: /* D1_QWC */
|
||||
logerror("%s: dmac_channel_r: D1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9030/8: /* D1_TADR */
|
||||
logerror("%s: dmac_channel_r: D1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9040/8: /* D1_ASR0 */
|
||||
logerror("%s: dmac_channel_r: D1_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0x9050/8: /* D1_ASR1 */
|
||||
logerror("%s: dmac_channel_r: D1_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa000/8: /* D2_CHCR */
|
||||
logerror("%s: dmac_channel_r: D2_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa010/8: /* D2_MADR */
|
||||
logerror("%s: dmac_channel_r: D2_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa020/8: /* D2_QWC */
|
||||
logerror("%s: dmac_channel_r: D2_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa030/8: /* D2_TADR */
|
||||
logerror("%s: dmac_channel_r: D2_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa040/8: /* D2_ASR0 */
|
||||
logerror("%s: dmac_channel_r: D2_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xa050/8: /* D2_ASR1 */
|
||||
logerror("%s: dmac_channel_r: D2_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb000/8: /* D3_CHCR */
|
||||
logerror("%s: dmac_channel_r: D3_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb010/8: /* D3_MADR */
|
||||
logerror("%s: dmac_channel_r: D3_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb020/8: /* D3_QWC */
|
||||
logerror("%s: dmac_channel_r: D3_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb400/8: /* D4_CHCR */
|
||||
logerror("%s: dmac_channel_r: D4_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb410/8: /* D4_MADR */
|
||||
logerror("%s: dmac_channel_r: D4_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb420/8: /* D4_QWC */
|
||||
logerror("%s: dmac_channel_r: D4_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xb430/8: /* D4_TADR */
|
||||
logerror("%s: dmac_channel_r: D4_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc000/8: /* SIF0_CHCR */
|
||||
ret = m_channels[SIF0].chcr();
|
||||
logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc010/8: /* SIF0_MADR */
|
||||
ret = m_channels[SIF0].addr();
|
||||
logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc020/8: /* SIF0_QWC */
|
||||
ret = m_channels[SIF0].quadword_count();
|
||||
logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc400/8: /* D6_CHCR */
|
||||
logerror("%s: dmac_channel_r: D6_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc410/8: /* D6_MADR */
|
||||
logerror("%s: dmac_channel_r: D6_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc420/8: /* D6_QWC */
|
||||
logerror("%s: dmac_channel_r: D6_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc430/8: /* D6_TADR */
|
||||
logerror("%s: dmac_channel_r: D6_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc800/8: /* D7_CHCR */
|
||||
logerror("%s: dmac_channel_r: D7_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc810/8: /* D7_MADR */
|
||||
logerror("%s: dmac_channel_r: D7_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xc820/8: /* D7_QWC */
|
||||
logerror("%s: dmac_channel_r: D7_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd000/8: /* D8_CHCR */
|
||||
logerror("%s: dmac_channel_r: D8_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd010/8: /* D8_MADR */
|
||||
logerror("%s: dmac_channel_r: D8_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd020/8: /* D8_QWC */
|
||||
logerror("%s: dmac_channel_r: D8_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd080/8: /* D8_SADR */
|
||||
logerror("%s: dmac_channel_r: D8_SADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd400/8: /* D9_CHCR */
|
||||
logerror("%s: dmac_channel_r: D9_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd410/8: /* D9_MADR */
|
||||
logerror("%s: dmac_channel_r: D9_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd420/8: /* D9_QWC */
|
||||
logerror("%s: dmac_channel_r: D9_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd430/8: /* D9_TADR */
|
||||
logerror("%s: dmac_channel_r: D9_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 0xd480/8: /* D9_SADR */
|
||||
logerror("%s: dmac_channel_r: D9_SADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: dmac_channel_r: Unknown offset %08x & %08x\n", machine().describe_context(), 0x10008000 + (offset << 3), mem_mask);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_dmac_device::channel_w)
|
||||
{
|
||||
static const char* mode_strings[4] = { "Normal", "Chain", "Interleave", "Undefined" };
|
||||
|
||||
switch (offset + 0x8000/8)
|
||||
{
|
||||
case 0x8000/8: /* D0_CHCR */
|
||||
logerror("%s: dmac_channel_w: D0_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x8010/8: /* D0_MADR */
|
||||
logerror("%s: dmac_channel_w: D0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x8020/8: /* D0_QWC */
|
||||
logerror("%s: dmac_channel_w: D0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x8030/8: /* D0_TADR */
|
||||
logerror("%s: dmac_channel_w: D0_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x8040/8: /* D0_ASR0 */
|
||||
logerror("%s: dmac_channel_w: D0_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x8050/8: /* D0_ASR1 */
|
||||
logerror("%s: dmac_channel_w: D0_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9000/8: /* D1_CHCR */
|
||||
logerror("%s: dmac_channel_w: D1_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9010/8: /* D1_MADR */
|
||||
logerror("%s: dmac_channel_w: D1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9020/8: /* D1_QWC */
|
||||
logerror("%s: dmac_channel_w: D1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9030/8: /* D1_TADR */
|
||||
logerror("%s: dmac_channel_w: D1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9040/8: /* D1_ASR0 */
|
||||
logerror("%s: dmac_channel_w: D1_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0x9050/8: /* D1_ASR1 */
|
||||
logerror("%s: dmac_channel_w: D1_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa000/8: /* D2_CHCR */
|
||||
logerror("%s: dmac_channel_w: D2_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa010/8: /* D2_MADR */
|
||||
logerror("%s: dmac_channel_w: D2_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa020/8: /* D2_QWC */
|
||||
logerror("%s: dmac_channel_w: D2_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa030/8: /* D2_TADR */
|
||||
logerror("%s: dmac_channel_w: D2_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa040/8: /* D2_ASR0 */
|
||||
logerror("%s: dmac_channel_w: D2_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xa050/8: /* D2_ASR1 */
|
||||
logerror("%s: dmac_channel_w: D2_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb000/8: /* D3_CHCR */
|
||||
logerror("%s: dmac_channel_w: D3_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb010/8: /* D3_MADR */
|
||||
logerror("%s: dmac_channel_w: D3_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb020/8: /* D3_QWC */
|
||||
logerror("%s: dmac_channel_w: D3_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb400/8: /* D4_CHCR */
|
||||
logerror("%s: dmac_channel_w: D4_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb410/8: /* D4_MADR */
|
||||
logerror("%s: dmac_channel_w: D4_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb420/8: /* D4_QWC */
|
||||
logerror("%s: dmac_channel_w: D4_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xb430/8: /* D4_TADR */
|
||||
logerror("%s: dmac_channel_w: D4_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc000/8: /* SIF0_CHCR */
|
||||
logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
|
||||
logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
|
||||
m_channels[SIF0].set_chcr(data);
|
||||
break;
|
||||
case 0xc010/8: /* SIF0_MADR */
|
||||
logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_channels[SIF0].set_addr(data);
|
||||
break;
|
||||
case 0xc020/8: /* SIF0_QWC */
|
||||
logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_channels[SIF0].set_quadword_count(data);
|
||||
break;
|
||||
case 0xc400/8: /* D6_CHCR */
|
||||
logerror("%s: dmac_channel_w: D6_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc410/8: /* D6_MADR */
|
||||
logerror("%s: dmac_channel_w: D6_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc420/8: /* D6_QWC */
|
||||
logerror("%s: dmac_channel_w: D6_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc430/8: /* D6_TADR */
|
||||
logerror("%s: dmac_channel_w: D6_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc800/8: /* D7_CHCR */
|
||||
logerror("%s: dmac_channel_w: D7_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc810/8: /* D7_MADR */
|
||||
logerror("%s: dmac_channel_w: D7_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xc820/8: /* D7_QWC */
|
||||
logerror("%s: dmac_channel_w: D7_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd000/8: /* D8_CHCR */
|
||||
logerror("%s: dmac_channel_w: D8_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd010/8: /* D8_MADR */
|
||||
logerror("%s: dmac_channel_w: D8_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd020/8: /* D8_QWC */
|
||||
logerror("%s: dmac_channel_w: D8_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd080/8: /* D8_SADR */
|
||||
logerror("%s: dmac_channel_w: D8_SADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd400/8: /* D9_CHCR */
|
||||
logerror("%s: dmac_channel_w: D9_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd410/8: /* D9_MADR */
|
||||
logerror("%s: dmac_channel_w: D9_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd420/8: /* D9_QWC */
|
||||
logerror("%s: dmac_channel_w: D9_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd430/8: /* D9_TADR */
|
||||
logerror("%s: dmac_channel_w: D9_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
case 0xd480/8: /* D9_SADR */
|
||||
logerror("%s: dmac_channel_w: D9_SADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: dmac_channel_w: Unknown offset %08x = %08x & %08x\n", machine().describe_context(), 0x10008000 + (offset << 3), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_dmac_device::disable_mask_r)
|
||||
{
|
||||
uint32_t ret = m_disable_mask;
|
||||
logerror("%s: m_disable_mask = %08x & %08x\n", machine().describe_context(), ret, mem_mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_dmac_device::disable_mask_w)
|
||||
{
|
||||
logerror("%s: m_disable_mask = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_disable_mask = data;
|
||||
}
|
||||
|
||||
void ps2_dmac_device::channel_t::set_chcr(uint32_t data)
|
||||
{
|
||||
m_chcr = data;
|
||||
m_mode = (data >> 2) & 3;
|
||||
bool was_enabled = m_enabled;
|
||||
m_enabled = BIT(m_chcr, 8);
|
||||
if (!was_enabled && m_enabled)
|
||||
{
|
||||
m_end_tag = m_mode == 0;
|
||||
}
|
||||
}
|
117
src/mame/machine/ps2dma.h
Normal file
117
src/mame/machine/ps2dma.h
Normal file
@ -0,0 +1,117 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 DMAC device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_PS2DMAC_H
|
||||
#define MAME_MACHINE_PS2DMAC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
class ps2_dmac_device : public device_t, public device_execute_interface
|
||||
{
|
||||
public:
|
||||
template <typename T, typename U, typename V>
|
||||
ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&ee_tag, U &&ram_tag, V &&sif_tag)
|
||||
: ps2_dmac_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
m_ee.set_tag(std::forward<T>(ee_tag));
|
||||
m_ram.set_tag(std::forward<U>(ram_tag));
|
||||
m_sif.set_tag(std::forward<V>(sif_tag));
|
||||
}
|
||||
|
||||
ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
enum channel_type : uint32_t
|
||||
{
|
||||
VIF0 = 0,
|
||||
VIF1,
|
||||
IPU_OUT,
|
||||
IPU_IN,
|
||||
SIF0,
|
||||
SIF1,
|
||||
SIF2,
|
||||
SPR_OUT,
|
||||
SPR_IN
|
||||
};
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
DECLARE_READ32_MEMBER(channel_r);
|
||||
DECLARE_WRITE32_MEMBER(channel_w);
|
||||
|
||||
DECLARE_READ32_MEMBER(disable_mask_r);
|
||||
DECLARE_WRITE32_MEMBER(disable_mask_w);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void execute_run() override;
|
||||
|
||||
class channel_t
|
||||
{
|
||||
friend class ps2_dmac_device;
|
||||
|
||||
public:
|
||||
channel_t()
|
||||
: m_chcr(0), m_mode(0), m_enabled(false), m_end_tag(false), m_addr(0), m_qwc(0)
|
||||
{
|
||||
}
|
||||
|
||||
void set_chcr(uint32_t data);
|
||||
uint32_t chcr() const { return m_chcr; }
|
||||
uint32_t mode() const { return m_mode; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
bool end_tag() const { return m_end_tag; }
|
||||
|
||||
uint32_t addr() const { return m_addr; }
|
||||
void set_addr(uint32_t addr) { m_addr = addr; }
|
||||
|
||||
uint32_t quadword_count() const { return m_qwc; }
|
||||
void set_quadword_count(uint32_t qwc) { m_qwc = qwc; }
|
||||
|
||||
protected:
|
||||
uint32_t m_chcr;
|
||||
uint32_t m_mode;
|
||||
bool m_enabled;
|
||||
bool m_end_tag;
|
||||
|
||||
uint32_t m_addr;
|
||||
uint32_t m_qwc;
|
||||
};
|
||||
|
||||
void transfer_sif0();
|
||||
void transfer_finish(uint32_t chan);
|
||||
void follow_tag(uint32_t channel);
|
||||
void update_interrupts();
|
||||
|
||||
required_device<cpu_device> m_ee;
|
||||
required_shared_ptr<uint64_t> m_ram;
|
||||
required_device<ps2_sif_device> m_sif;
|
||||
|
||||
int m_icount;
|
||||
|
||||
uint32_t m_ctrl;
|
||||
uint32_t m_mem_drain;
|
||||
bool m_enabled;
|
||||
|
||||
uint32_t m_disable_mask;
|
||||
|
||||
uint32_t m_istat;
|
||||
uint32_t m_imask;
|
||||
|
||||
uint32_t m_last_serviced;
|
||||
channel_t m_channels[10];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYPS2_DMAC, ps2_dmac_device)
|
||||
|
||||
#endif // MAME_MACHINE_PS2DMAC_H
|
79
src/mame/machine/ps2intc.cpp
Normal file
79
src/mame/machine/ps2intc.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 EE interrupt controller device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ps2intc.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SONYPS2_INTC, ps2_intc_device, "ps2intc", "Playstation 2 EE INTC")
|
||||
|
||||
ps2_intc_device::ps2_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONYPS2_INTC, tag, owner, clock)
|
||||
, m_ee(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void ps2_intc_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_mask));
|
||||
}
|
||||
|
||||
void ps2_intc_device::device_reset()
|
||||
{
|
||||
m_status = 0;
|
||||
m_mask = 0;
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_intc_device::read)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // I_STAT
|
||||
//logerror("%s: read: I_STAT %08x & %08x\n", machine().describe_context(), m_status, mem_mask);
|
||||
return m_status;
|
||||
case 2: // I_MASK
|
||||
logerror("%s: read: I_MASK %08x & %08x\n", machine().describe_context(), m_mask, mem_mask);
|
||||
return m_mask;
|
||||
default:
|
||||
logerror("%s: read: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1000f000 + (offset << 2), mem_mask);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_intc_device::write)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // I_STAT
|
||||
logerror("%s: write: I_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_status &= ~data;
|
||||
update_interrupts();
|
||||
break;
|
||||
case 2: // I_MASK
|
||||
logerror("%s: write: I_MASK = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
m_mask ^= data & 0x7fff;
|
||||
update_interrupts();
|
||||
break;
|
||||
default:
|
||||
logerror("%s: intc_w: Unknown offset %08x = %08x & %08x\n", machine().describe_context(), 0x1000f000 + (offset << 2), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ps2_intc_device::update_interrupts()
|
||||
{
|
||||
m_ee->set_input_line(MIPS3_IRQ0, (m_status & m_mask) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void ps2_intc_device::raise_interrupt(uint32_t line)
|
||||
{
|
||||
m_status |= (1 << line);
|
||||
update_interrupts();
|
||||
}
|
70
src/mame/machine/ps2intc.h
Normal file
70
src/mame/machine/ps2intc.h
Normal file
@ -0,0 +1,70 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 EE interrupt controller device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_PS2INTC_H
|
||||
#define MAME_MACHINE_PS2INTC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mips/mips3.h"
|
||||
|
||||
class ps2_intc_device : public device_t
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
ps2_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&ee_tag)
|
||||
: ps2_intc_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
m_ee.set_tag(std::forward<T>(ee_tag));
|
||||
}
|
||||
|
||||
ps2_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
|
||||
void raise_interrupt(uint32_t line);
|
||||
|
||||
enum
|
||||
{
|
||||
INT_GS = 0,
|
||||
INT_SBUS,
|
||||
INT_VB_ON,
|
||||
INT_VB_OFF,
|
||||
INT_VIF0,
|
||||
INT_VIF1,
|
||||
INT_VU0,
|
||||
INT_VU1,
|
||||
INT_IPU,
|
||||
INT_TIMER0,
|
||||
INT_TIMER1,
|
||||
INT_TIMER2,
|
||||
INT_TIMER3,
|
||||
INT_SFIFO,
|
||||
INT_VU0WD
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void update_interrupts();
|
||||
|
||||
required_device<cpu_device> m_ee;
|
||||
|
||||
uint32_t m_status;
|
||||
uint32_t m_mask;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYPS2_INTC, ps2_intc_device)
|
||||
|
||||
#endif // MAME_MACHINE_PS2SIF_H
|
187
src/mame/machine/ps2sif.cpp
Normal file
187
src/mame/machine/ps2sif.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 SIF device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ps2sif.h"
|
||||
|
||||
/*static*/ const size_t ps2_sif_device::MAX_FIFO_DEPTH = 0x20;
|
||||
|
||||
DEFINE_DEVICE_TYPE(SONYPS2_SIF, ps2_sif_device, "ps2sif", "Playstation 2 SIF")
|
||||
|
||||
ps2_sif_device::ps2_sif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONYPS2_SIF, tag, owner, clock)
|
||||
, m_intc(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void ps2_sif_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_ms_mailbox));
|
||||
save_item(NAME(m_sm_mailbox));
|
||||
save_item(NAME(m_ms_flag));
|
||||
save_item(NAME(m_sm_flag));
|
||||
save_item(NAME(m_ctrl));
|
||||
|
||||
m_fifo[0] = std::make_unique<uint32_t[]>(MAX_FIFO_DEPTH);
|
||||
m_fifo[1] = std::make_unique<uint32_t[]>(MAX_FIFO_DEPTH);
|
||||
}
|
||||
|
||||
void ps2_sif_device::device_reset()
|
||||
{
|
||||
m_ms_mailbox = 0;
|
||||
m_sm_mailbox = 0;
|
||||
m_ms_flag = 0;
|
||||
m_sm_flag = 0;
|
||||
m_ctrl = 0;
|
||||
|
||||
memset(m_fifo[0].get(), 0, sizeof(uint32_t) * MAX_FIFO_DEPTH);
|
||||
memset(m_fifo[1].get(), 0, sizeof(uint32_t) * MAX_FIFO_DEPTH);
|
||||
m_fifo_curr[0] = 0;
|
||||
m_fifo_curr[1] = 0;
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_sif_device::ee_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
ret = m_ms_mailbox;
|
||||
logerror("%s: ee_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 2:
|
||||
ret = m_sm_mailbox;
|
||||
logerror("%s: ee_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 4:
|
||||
ret = m_ms_flag;
|
||||
logerror("%s: ee_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 6:
|
||||
ret = m_sm_flag;
|
||||
if (ret != 0)
|
||||
logerror("%s: ee_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 8:
|
||||
ret = m_ctrl | 0xF0000102;
|
||||
logerror("%s: ee_r: SIF control (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: ee_r: Unknown (%08x & %08x)\n", machine().describe_context(), 0x1000f200 + (offset << 3), mem_mask);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_sif_device::ee_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
logerror("%s: ee_w: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_ms_mailbox = data;
|
||||
break;
|
||||
case 4:
|
||||
logerror("%s: ee_w: SIF set master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_ms_flag |= data;
|
||||
break;
|
||||
case 6:
|
||||
logerror("%s: ee_w: SIF clear slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_sm_flag &= ~data;
|
||||
break;
|
||||
case 8:
|
||||
logerror("%s: ee_w: SIF control = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
if (BIT(data, 8))
|
||||
m_ctrl |= (1 << 8);
|
||||
else
|
||||
m_ctrl &= ~(1 << 8);
|
||||
// ??
|
||||
break;
|
||||
default:
|
||||
logerror("%s: ee_w: Unknown %08x = %08x & %08x\n", machine().describe_context(), 0x1000f200 + (offset << 3), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(ps2_sif_device::iop_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
ret = m_ms_mailbox;
|
||||
logerror("%s: iop_r: SIF master->slave mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 4:
|
||||
ret = m_sm_mailbox;
|
||||
logerror("%s: iop_r: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 8:
|
||||
ret = m_ms_flag;
|
||||
if (ret != 0)
|
||||
logerror("%s: iop_r: SIF master->slave flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 12:
|
||||
ret = m_sm_flag;
|
||||
logerror("%s: iop_r: SIF slave->master flag (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
case 16:
|
||||
ret = m_ctrl | 0xf0000002;
|
||||
logerror("%s: iop_r: SIF control register (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
default:
|
||||
logerror("%s: iop_r: Unknown read (%08x & %08x)\n", machine().describe_context(), 0x1d000000 + (offset << 2), mem_mask);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ps2_sif_device::iop_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 4:
|
||||
logerror("%s: iop_w: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_sm_mailbox = data;
|
||||
break;
|
||||
case 12:
|
||||
logerror("%s: iop_w: SIF set slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_sm_flag |= data;
|
||||
break;
|
||||
case 16:
|
||||
logerror("%s: iop_w: SIF set control (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
|
||||
m_ctrl ^= data & 0xf0;
|
||||
break;
|
||||
default:
|
||||
logerror("%s: iop_w: Unknown write %08x = %08x & %08x\n", machine().describe_context(), 0x1d000000 + (offset << 2), data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ps2_sif_device::fifo_depth(uint32_t channel)
|
||||
{
|
||||
assert(channel < 2);
|
||||
return m_fifo_curr[channel];
|
||||
}
|
||||
|
||||
uint32_t ps2_sif_device::fifo_pop(uint32_t channel)
|
||||
{
|
||||
assert(channel < 2);
|
||||
assert(m_fifo_curr[channel] > 0);
|
||||
m_fifo_curr[channel]--;
|
||||
return m_fifo[channel][m_fifo_curr[channel]];
|
||||
}
|
||||
|
||||
void ps2_sif_device::fifo_push(uint32_t channel, uint32_t value)
|
||||
{
|
||||
assert(m_fifo_curr[channel] < MAX_FIFO_DEPTH);
|
||||
m_fifo[channel][m_fifo_curr[channel]] = value;
|
||||
m_fifo_curr[channel]++;
|
||||
}
|
61
src/mame/machine/ps2sif.h
Normal file
61
src/mame/machine/ps2sif.h
Normal file
@ -0,0 +1,61 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sony Playstation 2 SIF device skeleton
|
||||
*
|
||||
* To Do:
|
||||
* Everything
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_PS2SIF_H
|
||||
#define MAME_MACHINE_PS2SIF_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#include "ps2intc.h"
|
||||
|
||||
class ps2_sif_device : public device_t
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
ps2_sif_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&intc_tag)
|
||||
: ps2_sif_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
m_intc.set_tag(std::forward<T>(intc_tag));
|
||||
}
|
||||
|
||||
ps2_sif_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_READ32_MEMBER(ee_r);
|
||||
DECLARE_WRITE32_MEMBER(ee_w);
|
||||
DECLARE_READ32_MEMBER(iop_r);
|
||||
DECLARE_WRITE32_MEMBER(iop_w);
|
||||
|
||||
uint32_t fifo_depth(uint32_t channel);
|
||||
void fifo_push(uint32_t channel, uint32_t value);
|
||||
uint32_t fifo_pop(uint32_t channel);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
required_device<ps2_intc_device> m_intc;
|
||||
|
||||
uint32_t m_ms_mailbox;
|
||||
uint32_t m_sm_mailbox;
|
||||
uint32_t m_ms_flag;
|
||||
uint32_t m_sm_flag;
|
||||
uint32_t m_ctrl;
|
||||
|
||||
std::unique_ptr<uint32_t[]> m_fifo[2];
|
||||
uint32_t m_fifo_curr[2];
|
||||
|
||||
static const size_t MAX_FIFO_DEPTH;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYPS2_SIF, ps2_sif_device)
|
||||
|
||||
#endif // MAME_MACHINE_PS2SIF_H
|
@ -201,23 +201,23 @@ READ32_MEMBER(ps2_timer_device::read)
|
||||
update_count();
|
||||
ret = m_count;
|
||||
if (old != m_count)
|
||||
logerror("%s: PS2 timer read: COUNT (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: PS2 timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x02:
|
||||
ret = m_mode;
|
||||
logerror("%s: PS2 timer read: MODE (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: PS2 timer read: MODE (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
ret = m_compare;
|
||||
logerror("%s: PS2 timer read: COMP (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: PS2 timer read: COMP (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
ret = m_hold;
|
||||
logerror("%s: PS2 timer read: HOLD (%08x)\n", machine().describe_context(), ret);
|
||||
logerror("%s: PS2 timer read: HOLD (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -232,7 +232,7 @@ WRITE32_MEMBER(ps2_timer_device::write)
|
||||
{
|
||||
case 0x00:
|
||||
m_count = data;
|
||||
logerror("%s: PS2 timer write: COUNT = %08x\n", machine().describe_context(), data);
|
||||
logerror("%s: PS2 timer write: COUNT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
update_compare_timer();
|
||||
update_overflow_timer();
|
||||
break;
|
||||
@ -243,7 +243,7 @@ WRITE32_MEMBER(ps2_timer_device::write)
|
||||
|
||||
case 0x04:
|
||||
{
|
||||
logerror("%s: PS2 timer write: COMP = %08x\n", machine().describe_context(), data);
|
||||
logerror("%s: PS2 timer write: COMP = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
if (m_compare == data)
|
||||
break;
|
||||
|
||||
@ -257,7 +257,7 @@ WRITE32_MEMBER(ps2_timer_device::write)
|
||||
if (!m_can_hold)
|
||||
break;
|
||||
|
||||
logerror("%s: PS2 timer write: HOLD = %08x\n", machine().describe_context(), data);
|
||||
logerror("%s: PS2 timer write: HOLD = %08x & %08x\n", machine().describe_context(), data, mem_mask);
|
||||
if (m_hold == data)
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user