diff options
Diffstat (limited to 'src/devices/machine/ps2dma.cpp')
-rw-r--r-- | src/devices/machine/ps2dma.cpp | 791 |
1 files changed, 791 insertions, 0 deletions
diff --git a/src/devices/machine/ps2dma.cpp b/src/devices/machine/ps2dma.cpp new file mode 100644 index 00000000000..5bb422398bd --- /dev/null +++ b/src/devices/machine/ps2dma.cpp @@ -0,0 +1,791 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony PlayStation 2 EE DMA controller device skeleton +* +* To Do: +* Everything +* +*/ + +#include "ps2sif.h" +#include "ps2dma.h" +#include "cpu/mips/mips3.h" +#include "cpu/mips/ps2vif1.h" +#include "video/ps2gif.h" + +DEFINE_DEVICE_TYPE(SONYPS2_DMAC, ps2_dmac_device, "ps2dmac", "PlayStation 2 EE 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_gs(*this, finder_base::DUMMY_TAG) + , m_vu1(*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_end_irq), channel); + save_item(NAME(m_channels[channel].m_ienable), channel); + save_item(NAME(m_channels[channel].m_qwc), channel); + save_item(NAME(m_channels[channel].m_addr), channel); + save_item(NAME(m_channels[channel].m_tag_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 VIF1: + transfer_vif1(); + break; + case GIF: + transfer_gif(); + break; + case SIF0: + transfer_sif0(); + break; + case SIF1: + transfer_sif1(); + break; + default: + logerror("%s: Attempting to service unimplemented DMA channel %d\n", machine().describe_context(), m_last_serviced); + break; + } + } + if (m_last_serviced == 10) + m_last_serviced = 0; + } +} + +void ps2_dmac_device::transfer_vif1() +{ + if (m_mem_drain) + { + logerror("%s: transfer_vif1: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context()); + transfer_finish(VIF1); + return; + } + + channel_t &channel = m_channels[VIF1]; + const uint32_t count = channel.quadword_count(); + if (count) + { + //logerror("%s: DMAC VIF1 quadword count: %08x\n", machine().describe_context(), count); + if (m_vu1->interface()->fifo_available(4)) + { + uint32_t addr = channel.addr(); + if (BIT(addr, 31)) + addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + uint32_t words[4] = { 0, 0, 0, 0 }; + for (int word = 0; word < 4; word++) + { + words[word] = space.read_dword(addr); + addr += 4; + } + m_vu1->interface()->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]); + channel.set_addr(channel.addr() + 0x10); + channel.set_quadword_count(count - 1); + } + } + else if (channel.end_tag()) + { + logerror("%s: DMAC VIF1 end tag\n", machine().describe_context()); + transfer_finish(VIF1); + } + else if (m_vu1->interface()->fifo_available(2)) + { + logerror("%s: DMAC VIF1 following source tag\n", machine().describe_context()); + uint32_t tag_addr = channel.tag_addr(); + if (BIT(tag_addr, 31)) + tag_addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + uint32_t words[4] = { 0, 0, 0, 0 }; + for (int word = 0; word < 4; word++) + { + words[word] = space.read_dword(tag_addr); + tag_addr += 4; + } + m_vu1->interface()->tag_write(words); + follow_source_tag(VIF1); + } +} + +void ps2_dmac_device::transfer_gif() +{ + if (m_mem_drain) + { + logerror("%s: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context()); + transfer_finish(GIF); + return; + } + + channel_t &channel = m_channels[GIF]; + const uint32_t count = channel.quadword_count(); + if (count) + { + //logerror("%s: DMAC GIF quadword count: %08x\n", machine().describe_context(), count); + uint32_t addr = channel.addr(); + if (BIT(addr, 31)) + addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + uint32_t words[4] = { 0, 0, 0, 0 }; + for (int word = 0; word < 4; word++) + { + words[word] = space.read_dword(addr); + addr += 4; + } + m_gs->interface()->write_path3(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]); + channel.set_addr(channel.addr() + 0x10); + channel.set_quadword_count(count - 1); + } + else if (channel.end_tag()) + { + logerror("%s: DMAC GIF end tag\n", machine().describe_context()); + transfer_finish(GIF); + } + else + { + logerror("%s: DMAC GIF following source tag\n", machine().describe_context()); + follow_source_tag(GIF); + } +} + +void ps2_dmac_device::transfer_sif0() +{ + channel_t &channel = m_channels[SIF0]; + const uint32_t count = channel.quadword_count(); + if (count) + { + if (m_sif->fifo_depth(0) >= 4) + { + //logerror("%s: SIF0 depth is %d\n", machine().describe_context(), m_sif->fifo_depth(0)); + uint32_t addr = channel.addr(); + if (BIT(addr, 31)) + addr -= 0x10000000; + for (int word = 0; word < 4; word++) + { + const uint32_t data = m_sif->fifo_pop(0); + //logerror("%s: SIF0 popping %08x -> %08x\n", machine().describe_context(), data, addr); + m_ee->space(AS_PROGRAM).write_dword(addr, data); + addr += 4; + } + channel.set_addr(channel.addr() + 0x10); + channel.set_quadword_count(count - 1); + //logerror("%s: SIF0 remaining count: %08x\n", machine().describe_context(), channel.quadword_count()); + } + } + else if (channel.end_tag()) + { + //logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context()); + transfer_finish(SIF0); + } + else if (m_sif->fifo_depth(0) >= 2) + { + const uint32_t hi = m_sif->fifo_pop(0); + const uint32_t lo = m_sif->fifo_pop(0); + const uint32_t tag = hi; + //logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo); + channel.set_addr(lo); + channel.set_tag_addr(channel.tag_addr() + 0x10); + channel.set_quadword_count(tag & 0x0000ffff); + channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000)); + + const uint8_t mode = (tag >> 28) & 7; + if ((channel.irq_enable() && BIT(tag, 31)) || mode == ID_END) + { + channel.set_end_tag(true); + } + } +} + +void ps2_dmac_device::transfer_sif1() +{ + channel_t &channel = m_channels[SIF1]; + const uint32_t count = channel.quadword_count(); + if (count) + { + //logerror("%s: DMAC SIF1 quadword count: %08x\n", machine().describe_context(), count); + if (m_sif->fifo_depth(1) < (ps2_sif_device::MAX_FIFO_DEPTH - 4)) + { + uint32_t addr = channel.addr(); + if (BIT(addr, 31)) + addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + for (int word = 0; word < 4; word++) + { + const uint32_t data = space.read_dword(addr); + //logerror("%s: DMAC SIF1 Pushing %08x\n", machine().describe_context(), data); + addr += 4; + m_sif->fifo_push(1, data); + } + channel.set_addr(channel.addr() + 0x10); + channel.set_quadword_count(count - 1); + } + } + else if (channel.end_tag()) + { + //logerror("%s: DMAC SIF1 end tag\n", machine().describe_context()); + transfer_finish(SIF1); + } + else + { + //logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context()); + follow_source_tag(SIF1); + } +} + +void ps2_dmac_device::follow_source_tag(uint32_t chan) +{ + channel_t &channel = m_channels[chan]; + uint32_t tag_addr = channel.tag_addr(); + if (BIT(tag_addr, 31)) + tag_addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + const uint64_t hi = space.read_qword(tag_addr); + const uint64_t lo = space.read_dword(tag_addr + 8); + const uint32_t tag = (uint32_t)hi; + const uint32_t addr = (uint32_t)(hi >> 32) & ~0xf; + if (chan != GIF && chan != VIF1) + logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); + + channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000)); + channel.set_quadword_count(tag & 0x0000ffff); + const uint32_t id = (tag >> 28) & 7; + const bool irq = BIT(tag, 31); + + switch (id) + { + case ID_CNT: + channel.set_addr(channel.tag_addr() + 0x10); + channel.set_tag_addr(channel.addr() + (channel.quadword_count() << 4)); + break; + case ID_REFE: + channel.set_end_tag(true); + // Intentional fall-through + case ID_REF: + channel.set_addr(addr); + channel.set_tag_addr(channel.tag_addr() + 0x10); + break; + case ID_REFS: + // We don't handle stalls yet, just act the same as REF for now + channel.set_addr(addr); + channel.set_tag_addr(channel.tag_addr() + 0x10); + break; + case ID_NEXT: + channel.set_addr(channel.tag_addr() + 0x10); + channel.set_tag_addr(addr); + break; + case ID_END: + channel.set_addr(channel.tag_addr() + 0x10); + channel.set_end_tag(true); + break; + default: + logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id); + break; + } + + if (irq && channel.irq_enable()) + { + channel.set_end_tag(true); + } +} + +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_ctrl = data; + 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: /* VIF1_CHCR */ + ret = m_channels[VIF1].chcr(); + //logerror("%s: dmac_channel_r: VIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0x9010/8: /* VIF1_MADR */ + ret = m_channels[VIF1].addr(); + logerror("%s: dmac_channel_r: VIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0x9020/8: /* VIF1_QWC */ + ret = m_channels[VIF1].quadword_count(); + logerror("%s: dmac_channel_r: VIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0x9030/8: /* VIF1_TADR */ + ret = m_channels[VIF1].tag_addr(); + logerror("%s: dmac_channel_r: VIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0x9040/8: /* VIF1_ASR0 */ + logerror("%s: dmac_channel_r: VIF1_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0x9050/8: /* VIF1_ASR1 */ + logerror("%s: dmac_channel_r: VIF1_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa000/8: /* GIF_CHCR */ + ret = m_channels[GIF].chcr(); + //logerror("%s: dmac_channel_r: GIF_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa010/8: /* GIF_MADR */ + ret = m_channels[GIF].addr(); + logerror("%s: dmac_channel_r: GIF_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa020/8: /* GIF_QWC */ + ret = m_channels[GIF].quadword_count(); + logerror("%s: dmac_channel_r: GIF_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa030/8: /* GIF_TADR */ + ret = m_channels[GIF].tag_addr(); + logerror("%s: dmac_channel_r: GIF_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa040/8: /* GIF_ASR0 */ + logerror("%s: dmac_channel_r: GIF_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xa050/8: /* GIF_ASR1 */ + logerror("%s: dmac_channel_r: GIF_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: /* SIF1_CHCR */ + ret = m_channels[SIF1].chcr(); + //logerror("%s: dmac_channel_r: SIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xc410/8: /* SIF1_MADR */ + ret = m_channels[SIF1].addr(); + //logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xc420/8: /* SIF1_QWC */ + ret = m_channels[SIF1].quadword_count(); + //logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + break; + case 0xc430/8: /* SIF1_TADR */ + ret = m_channels[SIF1].tag_addr(); + //logerror("%s: dmac_channel_r: SIF1_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: /* VIF1_CHCR */ + logerror("%s: dmac_channel_w: VIF1_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[VIF1].set_chcr(data); + break; + case 0x9010/8: /* VIF1_MADR */ + logerror("%s: dmac_channel_w: VIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[VIF1].set_addr(data); + break; + case 0x9020/8: /* VIF1_QWC */ + logerror("%s: dmac_channel_w: VIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[VIF1].set_quadword_count(data); + break; + case 0x9030/8: /* VIF1_TADR */ + logerror("%s: dmac_channel_w: VIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[VIF1].set_tag_addr(data); + break; + case 0x9040/8: /* VIF1_ASR0 */ + logerror("%s: dmac_channel_w: VIF1_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0x9050/8: /* VIF1_ASR1 */ + logerror("%s: dmac_channel_w: VIF1_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0xa000/8: /* GIF_CHCR */ + logerror("%s: dmac_channel_w: GIF_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[GIF].set_chcr(data); + break; + case 0xa010/8: /* GIF_MADR */ + logerror("%s: dmac_channel_w: GIF_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[GIF].set_addr(data); + break; + case 0xa020/8: /* GIF_QWC */ + logerror("%s: dmac_channel_w: GIF_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[GIF].set_quadword_count(data); + break; + case 0xa030/8: /* GIF_TADR */ + logerror("%s: dmac_channel_w: GIF_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[GIF].set_tag_addr(data); + break; + case 0xa040/8: /* GIF_ASR0 */ + logerror("%s: dmac_channel_w: GIF_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + break; + case 0xa050/8: /* GIF_ASR1 */ + logerror("%s: dmac_channel_w: GIF_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: SIF1_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[SIF1].set_chcr(data); + break; + case 0xc410/8: /* D6_MADR */ + //logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[SIF1].set_addr(data); + break; + case 0xc420/8: /* D6_QWC */ + //logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[SIF1].set_quadword_count(data); + break; + case 0xc430/8: /* D6_TADR */ + //logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + m_channels[SIF1].set_tag_addr(data); + 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_ienable = BIT(m_chcr, 7); + m_enabled = BIT(m_chcr, 8); + if (!was_enabled && m_enabled) + { + m_end_tag = m_mode == 0; + } + else + { + m_end_tag = false; + } +}
\ No newline at end of file |